Skip to content

Commit 3cd1e2c

Browse files
committed
Fix namedtuple crash in unannotated function (#12804)
Fixes #11121.
1 parent 18a5107 commit 3cd1e2c

File tree

3 files changed

+51
-3
lines changed

3 files changed

+51
-3
lines changed

mypy/semanal_namedtuple.py

+8-3
Original file line numberDiff line numberDiff line change
@@ -186,11 +186,16 @@ def check_namedtuple(self,
186186
# Error. Construct dummy return value.
187187
if var_name:
188188
name = var_name
189+
if is_func_scope:
190+
name += '@' + str(call.line)
189191
else:
190-
name = 'namedtuple@' + str(call.line)
192+
name = var_name = 'namedtuple@' + str(call.line)
191193
info = self.build_namedtuple_typeinfo(name, [], [], {}, node.line)
192-
self.store_namedtuple_info(info, name, call, is_typed)
193-
return name, info
194+
self.store_namedtuple_info(info, var_name, call, is_typed)
195+
if name != var_name or is_func_scope:
196+
# NOTE: we skip local namespaces since they are not serialized.
197+
self.api.add_symbol_skip_local(name, info)
198+
return var_name, info
194199
if not ok:
195200
# This is a valid named tuple but some types are not ready.
196201
return typename, None

test-data/unit/check-incremental.test

+29
Original file line numberDiff line numberDiff line change
@@ -5711,3 +5711,32 @@ class C:
57115711
[builtins fixtures/dict.pyi]
57125712
[out2]
57135713
tmp/a.py:2: error: "object" has no attribute "xyz"
5714+
5715+
[case testIncrementalInvalidNamedTupleInUnannotatedFunction]
5716+
import a
5717+
5718+
[file a.py]
5719+
import b
5720+
5721+
[file a.py.2]
5722+
import b # f
5723+
5724+
[file b.py]
5725+
from typing import NamedTuple
5726+
5727+
def toplevel(fields):
5728+
TupleType = NamedTuple("TupleType", fields)
5729+
class InheritFromTuple(TupleType):
5730+
pass
5731+
NT2 = NamedTuple("bad", [('x', int)])
5732+
nt2: NT2 = NT2(x=1)
5733+
5734+
class C:
5735+
def method(self, fields):
5736+
TupleType = NamedTuple("TupleType", fields)
5737+
class InheritFromTuple(TupleType):
5738+
pass
5739+
NT2 = NamedTuple("bad", [('x', int)])
5740+
nt2: NT2 = NT2(x=1)
5741+
5742+
[builtins fixtures/tuple.pyi]

test-data/unit/check-namedtuple.test

+14
Original file line numberDiff line numberDiff line change
@@ -1120,3 +1120,17 @@ def bar1(c: C1) -> None:
11201120
reveal_type(c) # N: Revealed type is "Tuple[builtins.int, fallback=__main__.C1]"
11211121
[builtins fixtures/tuple.pyi]
11221122
[typing fixtures/typing-namedtuple.pyi]
1123+
1124+
[case testInvalidNamedTupleWithinFunction]
1125+
from collections import namedtuple
1126+
1127+
def f(fields) -> None:
1128+
TupleType = namedtuple("TupleType", fields) \
1129+
# E: List or tuple literal expected as the second argument to "namedtuple()"
1130+
class InheritFromTuple(TupleType):
1131+
pass
1132+
t: TupleType
1133+
it: InheritFromTuple
1134+
NT2 = namedtuple("bad", "x") # E: First argument to namedtuple() should be "NT2", not "bad"
1135+
nt2: NT2 = NT2(x=1)
1136+
[builtins fixtures/tuple.pyi]

0 commit comments

Comments
 (0)