-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
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
Cannot assign to field of Callable type #708
Comments
The mismatching types is probably because mypy thinks |
Hmm.. actually not sure what's the right thing to do here. Based on a quick experiment, the desired behavior seems to depend on what kind of a callable Consider this: class A:
f = None
def m(x):
return x + 1
print(m(1)) # 2
A.f = m
print(A().f(1)) # Error (2 args given, expects 1) But now look at this: class A:
f = None
class M:
def __call__(self, x):
return x + 1
m = M()
print(m(1) # 2
A.f = m
print(A().f(1)) # Okay => 2 |
Taking off priority label because the fix doesn't seem obvious. |
Before reporting it I also thought for a while that I could fix it quickly 😄. |
Is there any update? The issue is still present. For some real world example, it is used in the ctypes module (in the examples). from typing import Any, Callable
class A():
a = lambda: None # type: Callable[..., None]
def f() -> None: return None
A().a = f gives
Having |
I'm sorry, I don't have any further updates. |
Thanks for bumping this with the new repro! It's possible these two errors are different issues. The second looks like it may be a case of the The first error looks like the same thing as the original issue. |
@tharvik, would you also link more specifically to the bit in ctypes that refers to this? It's good to know about that use case, and it'd be interesting to see it more concretely. |
Seems that I'm unable to reproduce 'Incompatible types in assignment' on master with or without @gnprice in ctypes, when declaring a foreign function, one can redefine Example from the documentation def errcheck(result, func, args):
if not result:
raise WinError()
return args
GetWindowRect.errcheck = errcheck This way, we can load a library, in which, every attribute is a foreign function, then assign to some an For another example, here goes libLAS, where the library is loaded then it is assigned some checks. |
To be clear, the example still produces "Cannot assign to a method".
The problem seems to be that mypy disallows assigning to a method (which I
think is reasonable) but thinks that a class variable declared with a
Callable type (and initialized with a lambda) is also a method. The latter
is wrong, I think.
|
Just for the completeness of cases: same error with Python 3.6 variable annotations: MyFunction = Callable[[int], int]
class Thing:
function: MyFunction
def __init__(self, function: MyFunction) -> None:
self.function = function |
This affects basically every Django app that uses class FooAdmin(admin.ModelAdmin):
list_display = ("id", "custom")
def custom(self, obj):
return obj.bar
custom.short_description = "My Custom Field" # error in mypy |
I guess mypy needs to introduce a notion of a function object which is a
subclass of Callable that also supports other operations like `__getattr__`
and `__setattr__` (though we probably won't be able to type-check such
attributes).
|
Just an example I ran into today:
fails with When I changed typeshed to make |
To reiterate, assigning a callable to a class variable is fraught with problems in Python itself too. The reason is descriptors (things with a We should really teach mypy about all this (after all it now does know about descriptors!) but that would be a complicated change. |
Being a bit of a Python beginner and also ran into this which might or might not have more implications than I realise. My workaround (since all I wanted was a "selfless" function pointer as a member variable) was to put the Callable in a List like: |
That's not a mypy problem per se -- you can't initialize a class variable
to a "selfless" function pointer at runtime either (or rather, it will be
interpreted as a method and the first argument will be passed the
instance). Your workaround is valid.
|
Callables are receiving dynamic attributes, something that isn't "usual". See python/mypy#708 Signed-off-by: Mike Fiedler <[email protected]>
Callables are receiving dynamic attributes, something that isn't "usual". See python/mypy#708 Signed-off-by: Mike Fiedler <[email protected]>
* chore(deps): install mypy in lint.in Signed-off-by: Mike Fiedler <[email protected]> * chore(deps): include more types-* packages for mypy These were suggested from running mypy on the codebase. Signed-off-by: Mike Fiedler <[email protected]> * chore: configure mypy Set configuration for mypy. Exclude some of the subdirectories we are not interested in testing to speed up mypy execution. Ignore any 3rd party modules that we do not have types for yet. Added links that I could find to help track completion. Does **not** set `strict` mode yet, since that's a bigger lift. Signed-off-by: Mike Fiedler <[email protected]> * chore: add mypy runner script Eventually this command should fold into `bin/lint` and be removed. For now, it's a convenient execution wrapper. Signed-off-by: Mike Fiedler <[email protected]> * lint: ignore dynamic properties Callables are receiving dynamic attributes, something that isn't "usual". See python/mypy#708 Signed-off-by: Mike Fiedler <[email protected]> * lint: ignore lambdas See python/mypy#4226 Signed-off-by: Mike Fiedler <[email protected]> * lint: ignore hybrid_property repeat definitions Part of the SQLAlchemy extensions, which do not yet have reliable stubs/plugins. Signed-off-by: Mike Fiedler <[email protected]> * lint: ignore sqlalchemy declarative Should come along with sqlalchemy stubs. See: https://docs.sqlalchemy.org/en/14/orm/extensions/mypy.html#using-declared-attr-and-declarative-mixins Signed-off-by: Mike Fiedler <[email protected]> * lint: a few more ignores Signed-off-by: Mike Fiedler <[email protected]> * lint: interface methods shouldn't use self Surfaced via mypy, corrected! Signed-off-by: Mike Fiedler <[email protected]> * lint: correct subclass path Surfaced via mypy, corrected. Unclear why this wouldn't have been caught by other tools. Signed-off-by: Mike Fiedler <[email protected]> * lint: rename internal variable mypy detected this as a type mismatch, as the internal variable name was shadowing the externally-supplied one, and changing the type. Signed-off-by: Mike Fiedler <[email protected]> * lint: ignore flake8 line too long for ignored types Adding a `# type: ignore` comment to a couple of places triggered flake8's line too long check. Running `make reformat` did nothing for these - black has outstanding design issues with line length and comments. See psf/black#1713 for one example. Instead of changing the line structure to accommodate, ignore these two cases, at least until the types can be fixed and the comments removed. Signed-off-by: Mike Fiedler <[email protected]> * Revert "chore: add mypy runner script" This reverts commit fffeadb. * test: include mypy in lint execution Signed-off-by: Mike Fiedler <[email protected]> * chore(deps): include itsdangerous type stubs Until itsdangerous 2.0 is included, this types package is needed. Signed-off-by: Mike Fiedler <[email protected]>
This issue was recently discussed in-depth in python/typing#1113, where it was noted that mypy's behaviour differs from most other type-checkers |
It seems that hinting with a callable protocol instead of https://mypy-play.net/?mypy=latest&python=3.10&gist=389004dcf62cd710bec35920fdce4b68 import typing
class CallableProtocol(typing.Protocol):
def __call__(self) -> None:
pass
def a() -> None:
return
TypingCallable = typing.Callable[[], None]
class C:
f: TypingCallable
g: CallableProtocol
def __init__(self, f: TypingCallable, g: CallableProtocol) -> None:
self.f = f
self.g = g
def call(self) -> None:
self.f()
self.g()
|
* chore(deps): install mypy in lint.in Signed-off-by: Mike Fiedler <[email protected]> * chore(deps): include more types-* packages for mypy These were suggested from running mypy on the codebase. Signed-off-by: Mike Fiedler <[email protected]> * chore: configure mypy Set configuration for mypy. Exclude some of the subdirectories we are not interested in testing to speed up mypy execution. Ignore any 3rd party modules that we do not have types for yet. Added links that I could find to help track completion. Does **not** set `strict` mode yet, since that's a bigger lift. Signed-off-by: Mike Fiedler <[email protected]> * chore: add mypy runner script Eventually this command should fold into `bin/lint` and be removed. For now, it's a convenient execution wrapper. Signed-off-by: Mike Fiedler <[email protected]> * lint: ignore dynamic properties Callables are receiving dynamic attributes, something that isn't "usual". See python/mypy#708 Signed-off-by: Mike Fiedler <[email protected]> * lint: ignore lambdas See python/mypy#4226 Signed-off-by: Mike Fiedler <[email protected]> * lint: ignore hybrid_property repeat definitions Part of the SQLAlchemy extensions, which do not yet have reliable stubs/plugins. Signed-off-by: Mike Fiedler <[email protected]> * lint: ignore sqlalchemy declarative Should come along with sqlalchemy stubs. See: https://docs.sqlalchemy.org/en/14/orm/extensions/mypy.html#using-declared-attr-and-declarative-mixins Signed-off-by: Mike Fiedler <[email protected]> * lint: a few more ignores Signed-off-by: Mike Fiedler <[email protected]> * lint: interface methods shouldn't use self Surfaced via mypy, corrected! Signed-off-by: Mike Fiedler <[email protected]> * lint: correct subclass path Surfaced via mypy, corrected. Unclear why this wouldn't have been caught by other tools. Signed-off-by: Mike Fiedler <[email protected]> * lint: rename internal variable mypy detected this as a type mismatch, as the internal variable name was shadowing the externally-supplied one, and changing the type. Signed-off-by: Mike Fiedler <[email protected]> * lint: ignore flake8 line too long for ignored types Adding a `# type: ignore` comment to a couple of places triggered flake8's line too long check. Running `make reformat` did nothing for these - black has outstanding design issues with line length and comments. See psf/black#1713 for one example. Instead of changing the line structure to accommodate, ignore these two cases, at least until the types can be fixed and the comments removed. Signed-off-by: Mike Fiedler <[email protected]> * Revert "chore: add mypy runner script" This reverts commit fffeadb. * test: include mypy in lint execution Signed-off-by: Mike Fiedler <[email protected]> * chore(deps): include itsdangerous type stubs Until itsdangerous 2.0 is included, this types package is needed. Signed-off-by: Mike Fiedler <[email protected]>
ignore method assignment. Currently mypy cannot check this. Related upstream issues: - python/mypy#2427 - python/mypy#708
Fixes python#708 and Fixes python#5485 Prevent handling as bounded method of callable members declared as instance variables.
Fixes #708 Fixes #5485 This builds on the original proposal, but handles three important issues/edge cases: * This PR fixes serialization of `is_inferred` so that the distinction works correctly in incremental mode (I added a test) * Dunder operator methods are always considered class variables (this is a relatively common pattern and matches Python semantics; there is an existing tests that previously needed `ClassVar[...]`) * If we detect a `Too few arguments` error for a variable with callable type we give a note suggesting to try `ClassVar[...]` I also add a short doc paragraph on this. Co-authored-by: wyfo <[email protected]>
ignore method assignment. Currently mypy cannot check this. Related upstream issues: - python/mypy#2427 - python/mypy#708
ignore method assignment. Currently mypy cannot check this. Related upstream issues: - python/mypy#2427 - python/mypy#708
ignore method assignment. Currently mypy cannot check this. Related upstream issues: - python/mypy#2427 - python/mypy#708
ignore method assignment. Currently mypy cannot check this. Related upstream issues: - python/mypy#2427 - python/mypy#708
ignore method assignment. Currently mypy cannot check this. Related upstream issues: - python/mypy#2427 - python/mypy#708
There was issue #5062, which was closed as a duplicate in favor of this issue, which is shown as fixed. However, I am currently using Python 3.11.4 with mypy 1.4.1 and still getting the errors with ConfigParser, described in this comment - #5062 (comment). Is this expected, or duplicate issue was closed by mistake, and the error with ConfigParser is not fixed? |
Consider this example:
mypy reports:
while I'd expect this to work.
Note that there is a second error in the reporting of the type of the variable.
Also, this passes type checking (correctly):
The text was updated successfully, but these errors were encountered: