Skip to content

Commit

Permalink
Fix namedtuple crash in unannotated function (#12804)
Browse files Browse the repository at this point in the history
Fixes #11121.
  • Loading branch information
JukkaL committed May 18, 2022
1 parent 18a5107 commit 3cd1e2c
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 3 deletions.
11 changes: 8 additions & 3 deletions mypy/semanal_namedtuple.py
Expand Up @@ -186,11 +186,16 @@ def check_namedtuple(self,
# Error. Construct dummy return value.
if var_name:
name = var_name
if is_func_scope:
name += '@' + str(call.line)
else:
name = 'namedtuple@' + str(call.line)
name = var_name = 'namedtuple@' + str(call.line)
info = self.build_namedtuple_typeinfo(name, [], [], {}, node.line)
self.store_namedtuple_info(info, name, call, is_typed)
return name, info
self.store_namedtuple_info(info, var_name, call, is_typed)
if name != var_name or is_func_scope:
# NOTE: we skip local namespaces since they are not serialized.
self.api.add_symbol_skip_local(name, info)
return var_name, info
if not ok:
# This is a valid named tuple but some types are not ready.
return typename, None
Expand Down
29 changes: 29 additions & 0 deletions test-data/unit/check-incremental.test
Expand Up @@ -5711,3 +5711,32 @@ class C:
[builtins fixtures/dict.pyi]
[out2]
tmp/a.py:2: error: "object" has no attribute "xyz"

[case testIncrementalInvalidNamedTupleInUnannotatedFunction]
import a

[file a.py]
import b

[file a.py.2]
import b # f

[file b.py]
from typing import NamedTuple

def toplevel(fields):
TupleType = NamedTuple("TupleType", fields)
class InheritFromTuple(TupleType):
pass
NT2 = NamedTuple("bad", [('x', int)])
nt2: NT2 = NT2(x=1)

class C:
def method(self, fields):
TupleType = NamedTuple("TupleType", fields)
class InheritFromTuple(TupleType):
pass
NT2 = NamedTuple("bad", [('x', int)])
nt2: NT2 = NT2(x=1)

[builtins fixtures/tuple.pyi]
14 changes: 14 additions & 0 deletions test-data/unit/check-namedtuple.test
Expand Up @@ -1120,3 +1120,17 @@ def bar1(c: C1) -> None:
reveal_type(c) # N: Revealed type is "Tuple[builtins.int, fallback=__main__.C1]"
[builtins fixtures/tuple.pyi]
[typing fixtures/typing-namedtuple.pyi]

[case testInvalidNamedTupleWithinFunction]
from collections import namedtuple

def f(fields) -> None:
TupleType = namedtuple("TupleType", fields) \
# E: List or tuple literal expected as the second argument to "namedtuple()"
class InheritFromTuple(TupleType):
pass
t: TupleType
it: InheritFromTuple
NT2 = namedtuple("bad", "x") # E: First argument to namedtuple() should be "NT2", not "bad"
nt2: NT2 = NT2(x=1)
[builtins fixtures/tuple.pyi]

0 comments on commit 3cd1e2c

Please sign in to comment.