-
-
Notifications
You must be signed in to change notification settings - Fork 332
Fix type annotations for .provides #491
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
Conversation
@thiromi Wow! That's great! Thanks for the PR. I'll make a review later today |
Didn't get to the review today. Will take a look tomorrow |
@@ -144,7 +145,7 @@ class DependenciesContainer(Object): | |||
class Callable(Provider[T]): | |||
def __init__(self, provides: Optional[_Callable[..., T]] = None, *args: Injection, **kwargs: Injection) -> None: ... | |||
@property | |||
def provides(self) -> Optional[T]: ... | |||
def provides(self) -> Type[T]: ... |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So in that case we better return _Callable[..., T]
. Attribute .provides
should return what was provided in .__init__()
or .set_provides()
. Could you, please, update it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, I can. But If I could then propose here, because we can have the providers declared in two ways (they're semantically correct):
provider10 = providers.Callable(Cat)
and this
provider10 = providers.Callable[Animal](Cat)
mypy complains about the latter expecting that Cat
(Type[Cat]
) is not _Callable[..., T]
.
what do you think of using Union[Type[T], _Callable[..., T]]
?
I was going to propose that in another PR, but as you brought up this point, I thought it would be a pertinent question 😅
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, that makes sense. Go for it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, that's embarrassing... I added the tests using the explicit type on typevar
provider10 = providers.Callable[Animal](Cat)
and mypy didn't complain 😅
I might have done something wrong on my project 🤔
anyway, changed the code as you suggested at 47cf4c2
@property | ||
def provides(self) -> T: ... | ||
def provides(self) -> Type[T]: ... |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Like in the case with Callable
provider we better return _Callable[..., T]
here. With the current design Factory
and Singleton
providers can take not only classes but any callables. This change design change was made to support factory method and functions like sqlite.connect()
, logging.getLogger()
, etc.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done 47cf4c2
@@ -249,9 +250,9 @@ class Factory(Provider[T]): | |||
provided_type: Optional[Type] | |||
def __init__(self, provides: Optional[_Callable[..., T]] = None, *args: Injection, **kwargs: Injection) -> None: ... | |||
@property | |||
def cls(self) -> T: ... | |||
def cls(self) -> Type[T]: ... |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
At the same time, Factory
provider still has a strong use case when it is used with a class. When you need to access factory class, attribute .cls
is better from the readability and understandability perspectives. Even despite .cls
and .provides
are now aliases and have the same implementation, I think we should treat them differently. With that said, I think that's ok if we type .cls -> Type[T]
, and .provides -> _Callable[..., T]
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
okidoki 👍
once we resolve the conversation at https://github.com/ets-labs/python-dependency-injector/pull/491/files#r692507266, I'll do the changes 🙏
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done 47cf4c2
Looking at this PR I started think about proper typing (and behavior) for class Object(Provider[T]):
...
@property
def provides(self) -> Optional[T]: ...
... This might be inconvenient from typing perspective cause every time when you use Considering that I'm thinking about two changes:
Appreciate your thoughts on this. |
I think your suggestion on ensuring the provider is initialized is great! That would improve the cleanliness of the type hinting of |
as @rmk135 suggested
Merged the PR in develop branch. Next release to the PyPI will be on Wednesday August 25th. |
Published in |
I'm using this package for a project that relies on mypy static typing checks and bumped into a stub that has a strange behavior:
When I define let's say a
Singleton[int]
provider and want to access the class type via the propertySingleton.cls
, mypy complains the type is an instance ofint
rather thanType[int]
And as
Singleton.cls
is an alias toSingleton.provides
, I revised the types from that property as well to check if their types were correctly definedthank you for any feedback provided 🙏