diff --git a/mypy/semanal.py b/mypy/semanal.py index 729ed84bcc19..aa062094dd84 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -817,6 +817,12 @@ def analyze_namedtuple_classdef(self, defn: ClassDef) -> bool: items, types, default_items = self.check_namedtuple_classdef(defn) node.node = self.build_namedtuple_typeinfo( defn.name, items, types, default_items) + # We only really need the assignments in the body to be type checked later; + # attempting to type check methods may lead to crashes because NamedTuples + # do not have a fully functional TypeInfo. + # TODO remove this hack and add full support for NamedTuple methods + defn.defs.body = [stmt for stmt in defn.defs.body + if isinstance(stmt, AssignmentStmt)] return True return False diff --git a/test-data/unit/check-class-namedtuple.test b/test-data/unit/check-class-namedtuple.test index 46cb87d9a018..9deec11ec9fb 100644 --- a/test-data/unit/check-class-namedtuple.test +++ b/test-data/unit/check-class-namedtuple.test @@ -482,3 +482,15 @@ Y(y=1, x='1').method() class CallsBaseInit(X): def __init__(self, x: str) -> None: super().__init__(x) + +[case testNewNamedTupleClassMethod] +from typing import NamedTuple + +class HasClassMethod(NamedTuple): + x: str + + @classmethod # E: Invalid statement in NamedTuple definition; expected "field_name: field_type" + def new(cls, f: str) -> 'HasClassMethod': + pass + +[builtins fixtures/classmethod.pyi] diff --git a/test-data/unit/fixtures/classmethod.pyi b/test-data/unit/fixtures/classmethod.pyi index 282839dcef28..6d7f71bd52ff 100644 --- a/test-data/unit/fixtures/classmethod.pyi +++ b/test-data/unit/fixtures/classmethod.pyi @@ -1,5 +1,7 @@ import typing +_T = typing.TypeVar('_T') + class object: def __init__(self) -> None: pass @@ -20,3 +22,5 @@ class int: class str: pass class bytes: pass class bool: pass + +class tuple(typing.Generic[_T]): pass