-
-
Notifications
You must be signed in to change notification settings - Fork 3k
Description
This looks like a bug that is a combination of how NamedTuple
fields are created and how node types are determined.
If a Protocol
expects a field with type Callable
, passing a NamedTuple
that has a Callable
field won't work. A minimal reproduction is below. This behavior happens for me with Python 3.7.2
and mypy 0.680+dev.4e0a1583aeb00b248e187054980771f1897a1d31
using only the --strict
flag.
from typing import Callable, NamedTuple
from typing_extensions import Protocol
class A(NamedTuple):
my_func: Callable[[], str]
class WithFunc(Protocol):
# This is a property so it matches the read-only `my_func` in the NamedTuple
@property
def my_func(self) -> Callable[[], str]:
...
def call_func(with_func: WithFunc) -> None:
print(with_func.my_func())
a = A(lambda: "hi")
call_func(a) # <-- PROBLEM: This says that `A#my_func` has type `str`
MYPY = False
if MYPY:
reveal_type(a.my_func) # This correctly identifies `A#my_func` as a function
It looks like this is due to an interaction between the find_node_type
code that handles properties and the build_namedtuple_typeinfo
code which implicitly marks all NamedTuple
fields as properties. This causes the find_node_type
code to think that the field has the type of the Callable
's return type, rather than the whole Callable
.
I'm happy to submit a PR to try to fix this, but it's unclear to me if the right solution here is to no longer assume that all NamedTuple
are properties or to add an explicit check for NamedTuple
s to the property-resolving code in find_node_type
. Or something else entirely! If you have suggestions for the best way to resolve this I can submit a PR 🙂