Repository: python/mypy

Issue:
Internal error with namedtuple+classmethod
Running off the latest master.

```
from typing import *

class Bar(NamedTuple):
    x: str

    @classmethod
    def new(cls, f: str) -> 'Bar':
        return Bar(x=f)
```

```
[mypy]
python_version = 3.6

check_untyped_defs = True
disallow_untyped_calls = True
follow_imports = True
incremental = True
strict_optional = True
warn_no_return = True
warn_return_any = True
warn_unused_ignores = True
```

```
foo.py:6: error: Invalid statement in NamedTuple definition; expected "field_name: field_type"
foo.py:6: error: INTERNAL ERROR -- please report a bug at https://github.com/python/mypy/issues version: 0.510-dev-09e7b124b82dae1207d9eac6805b64a98290015c
```

This might be fixed by #3081? I'm not sure how to install that to test

<details><summary>Stack trace is here</summary>

```
Traceback (most recent call last):
  File "/Users/daenyth/Curata/observer/.tox/mypy/bin/mypy", line 6, in <module>
    main(__file__)
  File "/Users/daenyth/Curata/observer/.tox/mypy/lib/python3.6/site-packages/mypy/main.py", line 46, in main
    res = type_check_only(sources, bin_dir, options)
  File "/Users/daenyth/Curata/observer/.tox/mypy/lib/python3.6/site-packages/mypy/main.py", line 93, in type_check_only
    options=options)
  File "/Users/daenyth/Curata/observer/.tox/mypy/lib/python3.6/site-packages/mypy/build.py", line 188, in build
    graph = dispatch(sources, manager)
  File "/Users/daenyth/Curata/observer/.tox/mypy/lib/python3.6/site-packages/mypy/build.py", line 1595, in dispatch
    process_graph(graph, manager)
  File "/Users/daenyth/Curata/observer/.tox/mypy/lib/python3.6/site-packages/mypy/build.py", line 1838, in process_graph
    process_stale_scc(graph, scc, manager)
  File "/Users/daenyth/Curata/observer/.tox/mypy/lib/python3.6/site-packages/mypy/build.py", line 1937, in process_stale_scc
    graph[id].type_check_first_pass()
  File "/Users/daenyth/Curata/observer/.tox/mypy/lib/python3.6/site-packages/mypy/build.py", line 1510, in type_check_first_pass
    self.type_checker.check_first_pass()
  File "/Users/daenyth/Curata/observer/.tox/mypy/lib/python3.6/site-packages/mypy/checker.py", line 177, in check_first_pass
    self.accept(d)
  File "/Users/daenyth/Curata/observer/.tox/mypy/lib/python3.6/site-packages/mypy/checker.py", line 264, in accept
    stmt.accept(self)
  File "/Users/daenyth/Curata/observer/.tox/mypy/lib/python3.6/site-packages/mypy/nodes.py", line 749, in accept
    return visitor.visit_class_def(self)
  File "/Users/daenyth/Curata/observer/.tox/mypy/lib/python3.6/site-packages/mypy/checker.py", line 1080, in visit_class_def
    self.accept(defn.defs)
  File "/Users/daenyth/Curata/observer/.tox/mypy/lib/python3.6/site-packages/mypy/checker.py", line 264, in accept
    stmt.accept(self)
  File "/Users/daenyth/Curata/observer/.tox/mypy/lib/python3.6/site-packages/mypy/nodes.py", line 810, in accept
    return visitor.visit_block(self)
  File "/Users/daenyth/Curata/observer/.tox/mypy/lib/python3.6/site-packages/mypy/checker.py", line 1173, in visit_block
    self.accept(s)
  File "/Users/daenyth/Curata/observer/.tox/mypy/lib/python3.6/site-packages/mypy/checker.py", line 264, in accept
    stmt.accept(self)
  File "/Users/daenyth/Curata/observer/.tox/mypy/lib/python3.6/site-packages/mypy/nodes.py", line 631, in accept
    return visitor.visit_decorator(self)
  File "/Users/daenyth/Curata/observer/.tox/mypy/lib/python3.6/site-packages/mypy/checker.py", line 2213, in visit_decorator
    e.func.accept(self)
  File "/Users/daenyth/Curata/observer/.tox/mypy/lib/python3.6/site-packages/mypy/nodes.py", line 564, in accept
    return visitor.visit_func_def(self)
  File "/Users/daenyth/Curata/observer/.tox/mypy/lib/python3.6/site-packages/mypy/checker.py", line 513, in visit_func_def
    self.check_method_override(defn)
  File "/Users/daenyth/Curata/observer/.tox/mypy/lib/python3.6/site-packages/mypy/checker.py", line 945, in check_method_override
    for base in defn.info.mro[1:]:
TypeError: 'NoneType' object is not subscriptable
```

</details>


Discussion:
I figured out how to install it (deps line in tox needs `git+git://github.com/JelleZijlstra/mypy.git@ntmethods`)

#3081 does fix the crash

I do still get `foo.py:6: error: Invalid statement in NamedTuple definition; expected "field_name: field_type [= default]"` though
Keeping this open until until #3081 has been merged.
@Daenyth By the way, do you still see the crash on master without ``incremental``?
I can repro without a config file and without incremental on master. Also verified that this doesn't happen on 0.501 so this is a regression and I'd like to get this fixed before release. Since we are in feature freeze, I'd rather have a specific fix for this issue instead of landing #3081. Anybody want to look at extracting the fix for this from #3081 (or implementing an independent fix)? 

^^ @JelleZijlstra @ilevkivskyi 
I have a (very hacky) quick fix; will send a pr shortly.

El El jue, may. 4, 2017 a las 9:04 AM, Jukka Lehtosalo <
notifications@github.com> escribió:

> I can repro without a config file and without incremental on master. Also
> verified that this doesn't happen on 0.501 so this is a regression and I'd
> like to get this fixed before release. Since we are in feature freeze, I'd
> rather have a specific fix for this issue instead of landing #3081
> <https://github.com/python/mypy/pull/3081>. Anybody want to look at
> extracting the fix for this from #3081
> <https://github.com/python/mypy/pull/3081> (or implementing an
> independent fix)?
>
> ^^ @JelleZijlstra <https://github.com/JelleZijlstra> @ilevkivskyi
> <https://github.com/ilevkivskyi>
>
> —
> You are receiving this because you were mentioned.
> Reply to this email directly, view it on GitHub
> <https://github.com/python/mypy/issues/3317#issuecomment-299231467>, or mute
> the thread
> <https://github.com/notifications/unsubscribe-auth/AA3VaE3zR9TLmS_OSHAtNc8a3NkNgz-4ks5r2fcTgaJpZM4NQk4O>
> .
>


Resolving patch:
diff --git a/mypy/semanal.py b/mypy/semanal.py
--- 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
 


Test patch:
diff --git a/test-data/unit/check-class-namedtuple.test b/test-data/unit/check-class-namedtuple.test
--- 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]