Skip to content

Commit 8ea1aa5

Browse files
JelleZijlstraJukkaL
authored andcommitted
Fix crash with NamedTuple classmethod (#3323)
Really hacky but this should work for now. I think the bug was introduced when we added support for NamedTuple classmethods. Fixes #3317
1 parent 129a0f4 commit 8ea1aa5

File tree

3 files changed

+22
-0
lines changed

3 files changed

+22
-0
lines changed

mypy/semanal.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -817,6 +817,12 @@ def analyze_namedtuple_classdef(self, defn: ClassDef) -> bool:
817817
items, types, default_items = self.check_namedtuple_classdef(defn)
818818
node.node = self.build_namedtuple_typeinfo(
819819
defn.name, items, types, default_items)
820+
# We only really need the assignments in the body to be type checked later;
821+
# attempting to type check methods may lead to crashes because NamedTuples
822+
# do not have a fully functional TypeInfo.
823+
# TODO remove this hack and add full support for NamedTuple methods
824+
defn.defs.body = [stmt for stmt in defn.defs.body
825+
if isinstance(stmt, AssignmentStmt)]
820826
return True
821827
return False
822828

test-data/unit/check-class-namedtuple.test

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -482,3 +482,15 @@ Y(y=1, x='1').method()
482482
class CallsBaseInit(X):
483483
def __init__(self, x: str) -> None:
484484
super().__init__(x)
485+
486+
[case testNewNamedTupleClassMethod]
487+
from typing import NamedTuple
488+
489+
class HasClassMethod(NamedTuple):
490+
x: str
491+
492+
@classmethod # E: Invalid statement in NamedTuple definition; expected "field_name: field_type"
493+
def new(cls, f: str) -> 'HasClassMethod':
494+
pass
495+
496+
[builtins fixtures/classmethod.pyi]

test-data/unit/fixtures/classmethod.pyi

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import typing
22

3+
_T = typing.TypeVar('_T')
4+
35
class object:
46
def __init__(self) -> None: pass
57

@@ -20,3 +22,5 @@ class int:
2022
class str: pass
2123
class bytes: pass
2224
class bool: pass
25+
26+
class tuple(typing.Generic[_T]): pass

0 commit comments

Comments
 (0)