-
Notifications
You must be signed in to change notification settings - Fork 369
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
test: update mypy typings #956
base: main
Are you sure you want to change the base?
Conversation
@bitprophet this should resolve multiple open issues with typing. |
@bitprophet do you think you can review this soon? It should resolve multiple outstanding issues. |
@Dreamsorcerer fysa |
@@ -286,7 +287,7 @@ def get_arguments( | |||
return args | |||
|
|||
|
|||
def task(*args: Any, **kwargs: Any) -> Callable: | |||
def task(*args: Any, **kwargs: Any) -> "Task[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.
The TypeVar is not being used correctly in this function. Either use Task[Any]
, or if you want to spend a bit more time on it, you could try and type it properly.
I think the correct signature would look something along the lines of:
@overload
def task(arg: T, *, klass: Callable[[T]], U], **kwargs: Any) -> U:
...
@overload
def task(arg: T, **kwargs: Any) -> Task[T]:
...
@overload
def task(*args, klass: Callable[[Callable], T], **kwargs: Any) -> Callable[[Callable], T]:
...
@overload
def task(*args: Any, **kwargs: Any) -> Callable[[T], Task[T]]: # T should actually be bound to Callable on this one.
...
But, frankly, it's rather complicated.
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.
This is following the recommendation provided by mypy documentation: https://mypy.readthedocs.io/en/stable/generics.html#declaring-decorators
Commented on the wrong example.
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.
The mistake is that a TypeVar is being used as a return type, but does not appear in the parameters (or anywhere else), which means that it is not doing the job of a TypeVar. The point of a TypeVar is to infer the precise type based on context. e.g. def foo(a: T) -> T:
means that the return type will be the same as the input type. If you only put it in one place, then this gives no information at all (it wouldn't surprise me if mypy were to produce a type error in future, due to this being obviously incorrect usage).
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.
Seems that mypy already produces an error for this, but it doesn't trigger with a Generic:
python/mypy#16113
@@ -357,7 +358,7 @@ def inner(body: Callable) -> Task[T]: | |||
return _task | |||
|
|||
# update_wrapper(inner, klass) | |||
return inner | |||
return cast('Task["T"]', inner) |
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.
Maybe this'll be fixed by the above comment, but if not, it'd be better to type ignore than cast here, given that it is literally not a Task being returned.
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.
This is following the recommendation provided by mypy documentation: https://mypy.readthedocs.io/en/stable/generics.html#declaring-decorators
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.
My point was that this is not a Task. The docs you point to are accepting a function and returning a function, the cast is to the function type. This is returning a function and then you're casting it as a Task.
docs:
F = TypeVar('F', bound=Callable[..., Any])
def printing_decorator(func: F) -> F:
def wrapper(*args, **kwds):
...
return cast(F, wrapper) # wrapper is the same as F as it is a function which passes through the call.
here:
def task(*args: Any, **kwargs: Any) -> Task[T]:
def inner(body: Callable) -> Task[T]:
...
return cast(Task[T], inner) # inner is clearly not a Task
Would love to see this merged. Per https://bitprophet.org/projects
So maybe that will happen soon 🤞 |
This comment was marked as resolved.
This comment was marked as resolved.
@bitprophet do you have time to look at this patch? |
No description provided.