Open asottile opened 4 years ago
I think we could take a PR to fix this, but I'm not entirely sure what the ground truth of allowable dunder overrides are for namedtuple. Perhaps we can allowlist those.
I don't think dunders are the issue. At runtime, only objects with type annotations are interpreted as NamedTuple fields, so mypy should mirror that logic.
The relevant code is in mypy.semanal_namedtuple
.
I agree that it would be better to match runtime semantics here, but it seems fairly low priority. A simple PR that fixes this would probably be fine.
Easy workaround:
from typing import NamedTuple, TYPE_CHECKING
class C(NamedTuple):
x: int
if not TYPE_CHECKING:
__hash__ = object.__hash__
that doesn't help, typed code which calls those methods will fail
that doesn't help, typed code which calls those methods will fail
Can't you just do this instead?
from typing import NamedTuple, TYPE_CHECKING
class C(NamedTuple):
x: int
if TYPE_CHECKING:
def __hash__(self) -> int: ...
else:
__hash__ = object.__hash__
that also doesn't help because the code outside of if TYPE_CHECKING
is not checked -- __hash__
is just a minimal example here -- for example utilizing a shared method definition being assigned to many namedtuple classes
similar to:
class HasParticularAttr(Protocol):
...
def f(self: HasParticularAttr) -> int:
return ...
class C(NamedTuple):
x: attr
f = f
class D(NamedTuple):
x: attr
f = f
To be clear, I agree that it would be great if mypy could support this feature. I was just trying to offer an alternative workaround in the meantime.
this currently works for non-namedtuple classes (both runtime and mypy-time):
and it works for
typing.NamedTuple
at runtime:but fails at type-checking time:
concrete usecase:
__hash__
is in the critical path (~13%) for some code I'm writing and the extra layer of function which calls intoobject.__hash__
's overhead is significant:I'd be happy to hack on this given some pointers :)