-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
fix: type Markable
is reduced to Any
by mypy
#8674
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,6 +3,7 @@ | |
import warnings | ||
from typing import Any | ||
from typing import Callable | ||
from typing import cast | ||
from typing import Collection | ||
from typing import Iterable | ||
from typing import Iterator | ||
|
@@ -264,9 +265,9 @@ def combined_with(self, other: "Mark") -> "Mark": | |
|
||
|
||
# A generic parameter designating an object to which a Mark may | ||
# be applied -- a test function (callable) or class. | ||
# be applied -- a test function (callable) or class (also callable). | ||
# Note: a lambda is not allowed, but this can't be represented. | ||
Markable = TypeVar("Markable", bound=Union[Callable[..., object], type]) | ||
Markable = TypeVar("Markable", bound=Callable[..., Any]) | ||
|
||
|
||
@attr.s(init=False, auto_attribs=True) | ||
|
@@ -344,25 +345,22 @@ def with_args(self, *args: object, **kwargs: object) -> "MarkDecorator": | |
mark = Mark(self.name, args, kwargs, _ispytest=True) | ||
return MarkDecorator(self.mark.combined_with(mark), _ispytest=True) | ||
|
||
# Type ignored because the overloads overlap with an incompatible | ||
# return type. Not much we can do about that. Thankfully mypy picks | ||
# the first match so it works out even if we break the rules. | ||
@overload | ||
def __call__(self, arg: Markable) -> Markable: # type: ignore[misc] | ||
bluetech marked this conversation as resolved.
Show resolved
Hide resolved
|
||
def __call__(self, arg: Markable) -> Markable: | ||
pass | ||
|
||
@overload | ||
def __call__(self, *args: object, **kwargs: object) -> "MarkDecorator": | ||
def __call__(self, *args: Any, **kwargs: Any) -> "MarkDecorator": | ||
bluetech marked this conversation as resolved.
Show resolved
Hide resolved
|
||
pass | ||
|
||
def __call__(self, *args: object, **kwargs: object): | ||
def __call__(self, *args: Any, **kwargs: Any) -> Union[Markable, "MarkDecorator"]: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is it unbound? I figured mypy would use the overload, but I can adjust this so there is less overlap. I can force non keyword arguments but without knowing at least one required keyword argument I don't know how to tell mypy that at least one has to be provided. to force the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just to follow up on the last part of your comment... As you have it mypy (possibly any type checker) will read this as There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. When a function has overloads defined, the typing of the implementation function is only used for the implementation -- it is ignored in favor of the overloads everywhere else. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, that's correct, but shouldn't the function return be type checked so that future editors don't accidentally make a mistake? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think best we can do is add a comment. |
||
"""Call the MarkDecorator.""" | ||
if args and not kwargs: | ||
func = args[0] | ||
is_class = inspect.isclass(func) | ||
if len(args) == 1 and (istestfunc(func) or is_class): | ||
store_mark(func, self.mark) | ||
return func | ||
return cast(Markable, func) | ||
return self.with_args(*args, **kwargs) | ||
|
||
|
||
|
Uh oh!
There was an error while loading. Please reload this page.