Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[mypy] "Only concrete class can be given" fails with Dependency provider and abc #497

Open
zerlok opened this issue Aug 26, 2021 · 6 comments
Assignees
Labels

Comments

@zerlok
Copy link

zerlok commented Aug 26, 2021

I'm trying to use Dependency provider according to the documentation, and the code works well, but mypy returns an error Only concrete class can be given where "Type[Animal]" is expected. I found this mypy issue, but I'm not sure is that problem related to me. Should I comment to the mypy issue and wait for it to be solved in mypy?

import abc

from dependency_injector.containers import DeclarativeContainer
from dependency_injector.providers import Dependency, Factory


class Animal(metaclass=abc.ABCMeta):
    @abc.abstractmethod
    def say(self) -> str:
        raise NotImplementedError


class Dog(Animal):
    def say(self) -> str:
        return "bark"


class Container(DeclarativeContainer):
    # mypy error: Only concrete class can be given where "Type[Animal]" is expected
    animal_dependency = Dependency(Animal)

    # no mypy errors
    animal_factory = Factory(Animal)


def main() -> None:
    container = Container()

    container.animal_dependency.override(Factory(Dog))
    container.animal_factory.override(Factory(Dog))

    print(container.animal_dependency().say())
    print(container.animal_factory().say())


if __name__ == "__main__":
    main()

project dependencies

dependency-injector==4.36.0
mypy==0.910
mypy-extensions==0.4.3
six==1.16.0
toml==0.10.2
typing-extensions==3.10.0.0

mypy settings in project.toml

[tool.mypy]
python_version = "3.8"

disallow_any_unimported = true
disallow_any_decorated = true
disallow_any_generics = true
disallow_subclassing_any = true
disallow_untyped_calls = true
disallow_untyped_defs = true
disallow_incomplete_defs = true
disallow_untyped_decorators = true
no_implicit_optional = true
strict_optional = true

warn_redundant_casts = true
warn_unused_ignores = true
warn_no_return = true
warn_return_any = true
warn_unreachable = true

strict_equality = true
implicit_reexport = false

show_error_context = true
show_column_numbers = true
show_error_codes = true
pretty = true

warn_unused_configs = true
@rmk135 rmk135 self-assigned this Aug 26, 2021
@rmk135
Copy link
Member

rmk135 commented Aug 26, 2021

Hi @zerlok. Yeah, this seems to be a mypy issue. There is no error on Factory provider because it uses Callable[..., T] instead of Type[T]:

class Dependency(Provider[T]):
    def __init__(self, instance_of: Type[T] = object, default: Optional[Union[Provider, Any]] = None) -> None: ...


class Factory(Provider[T]):
    def __init__(self, provides: Optional[_Callable[..., T]] = None, *args: Injection, **kwargs: Injection) -> None: ...

@rmk135
Copy link
Member

rmk135 commented Aug 26, 2021

Checked a bunch of different ideas but neither works. I'm sorry, I can not fix it in the Dependency Injector. I probably need to update the documentation removing abc usage.

Thanks for reporting the issue.

@rmk135 rmk135 added the bug label Aug 26, 2021
@rmk135 rmk135 changed the title mypy fails with Dependency provider [mypy] "Only concrete class can be given" fails with Dependency provider Aug 26, 2021
@rmk135 rmk135 changed the title [mypy] "Only concrete class can be given" fails with Dependency provider [mypy] "Only concrete class can be given" fails with Dependency provider and abc Aug 26, 2021
@zerlok
Copy link
Author

zerlok commented Aug 31, 2021

Hi, @ rmk135, thanks for response. I hope then mypy will fix it somehow. I leave the issue open by now. Also I think that you may add a simple note about mypy behavior in the docs, not removing abc usage (Dependency provider works as expected).

@zerlok
Copy link
Author

zerlok commented Aug 18, 2022

Hey, @rmk135 . The related mypy issue was closed. I tried to update mypy and dependency-injector and retry my code - the issue remains the same:

mycontainer.py: note: In class "Container":
mycontainer.py:20:36: error: Only concrete class can be given where
"Type[Animal]" is expected  [misc]
        animal_dependency = Dependency(Animal)
                                       ^
Found 1 error in 1 file (checked 1 source file)

Any ideas how to fix it?

@samuelslva-jlfs
Copy link

samuelslva-jlfs commented Oct 18, 2022

Just an update, because this issue is top on google, there was some heated debates on mypy side about this because mypy allows for some behaviour where they need to ensure any instance of Type[X] is instanceable, so they can't allow an ABCs to fulfil Type[X] I didn't quite follow the details, but

TL;DR but there was some push back about this and the best people could agree on was moving the check behind its dedicated own error code (instead of the current misc) (this PR) that will be available on mypy 0.990 (not released at time of writing) after which we will be MyPy 0.990 has landed and we're able to purposefully ignore.

Current workaround I've been using is:

class Container(containers.DeclarativeContainer):
    progress_monitoring = providers.Dependency(
        # https://github.com/python/mypy/issues/5374
        instance_of=ProgressMonitor,  # type: ignore[type-abstract]
        default=providers.Factory(
            PubsubProgressMonitor,
            tasks_lifecycle_topic=config.tasks_lifecycle_topic,
            pubsub=pubsub,
        ),
    )

@samuelslva-jlfs
Copy link

Maybe add a mention to this to the MyPy section of the docs?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants