-
-
Notifications
You must be signed in to change notification settings - Fork 2.9k
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
Poor interactions with staticmethod and overload/union #15015
Comments
I was just going to report the same bug. I think the simplest reproduction is: def f(a: int) -> int:
return 7
@staticmethod
def g(a: int) -> int:
return 7
reveal_type(staticmethod(f)) # Revealed type is "builtins.staticmethod[builtins.int]"
reveal_type(g) # Revealed type is "def (a: builtins.int) -> builtins.int" |
@hoodmane That particular presentation is actually fixed on master/v1.2.0, I believe. It is roughly equivalent to the main.py:57: note: Revealed type is "builtins.staticmethod[[a: builtins.int], builtins.int]" It still has the wrapper shown in the revealed type, but it retains the type info for the proper signature. But staticmethod doesn't make semantic sense outside of a class, so that is probably where the wrapper is coming from. (mypy also errors on the staticmethod of The overload/union signatures are an extra wrinkle that isn't quite right still |
Well the behavior is the same with: def f(a: int) -> int:
return 7
class T:
f = staticmethod(f)
reveal_type(T.f) which is where it's actually useful. But even if mypy is mad about the use of |
Ah but I see it most definitely does work on mypy v1.2.0. I was testing against v1.1.1. Thanks! |
It appears as though the overload portions of this report have been addressed on master. The union portions do seem to remain (unfortunately that is what is causing problems for matplotlib) |
I bump into the same issue. Furthermore, I think you can add 'generic' to the list if incompatibilities -- if (Tested on |
Update here, things have improved to a degree but not fully resolved as of mypy 1.9.0:
|
I'm still having this issue with Here is a snippet to reproduce it.from typing import Callable
class Base:
def __init__(self, test: Callable[..., None] | None):
self.test = test
def test() -> None:
pass
class Good(Base):
test = staticmethod(test)
class Bad(Base):
@staticmethod
def test() -> None:
pass $ mypy --strict test.py
test.py:19: error: Signature of "test" incompatible with supertype "Base" [override]
test.py:19: note: Superclass:
test.py:19: note: Callable[..., None] | None
test.py:19: note: Subclass:
test.py:19: note: @staticmethod
test.py:19: note: def test() -> None
Found 1 error in 1 file (checked 1 source file) It forces me to uglify some child classes in a real application. |
Bug Report
Behavior changed in v1.2.0 regarding how staticmethods are handled when invoked by doing
foo = staticmethod(bar)
(i.e. not as the@decorator
syntax)A realworld example of this appeared in matplotlib, which is wrapping a third party method as a staticmethod of one of our classes (pyparsing)
Possibly related:
#14953 (most recent change to staticmethod handling)
#14902 (typeshed sync, mentions staticmethod
#7781 (original report of staticmethod behavior
A pure python example (and extension) is provided below.
To Reproduce
https://mypy-play.net/?mypy=latest&python=3.10&gist=c50c0fb3a6c10fbea317a31453b40e29
Expected Behavior
I would expect that the overload (or union) would carry forward to the decorated static method.
Actual Behavior
Prior to v1.2.0 (tested explicitly with v1.1.1:
All staticmethods constructed without
@decorator
syntax would simply getdef (*Any, **Any) -> Any
, which was at least not an error, though was throwing away type information.In the case of a single non-overloaded function defined outside of the class, it gets the return type but not the parameter type.
In v1.2.0:
In the case of an overloaded method defined outside of the class, only the first overloaded definition is kept, resulting in incorrect errors for alternate signatures.
In the case of a Union type (such as from a factory function), an error is thrown on the call to
staticmethod
, even if all branches of the union satisfy the typestaticmethod
expects.This was the actual case I saw with matplotlib.
In the case of a single non-overloaded function or an overload defined in the class (with
@staticmethod
on all overload branches) v1.2.0 behaves as expected.Your Environment
mypy.ini
(and other config files):N/AThe text was updated successfully, but these errors were encountered: