8000 Merge pull request #1277 from gvanrossum/master · python/mypy@2f89c79 · GitHub
[go: up one dir, main page]

Skip to content

Commit 2f89c79

Browse files
committed
Merge pull request #1277 from gvanrossum/master
Distinguish between namedtuple without items and errors.
2 parents e308f2f + d4f6f33 commit 2f89c79

File tree

2 files changed

+16
-9
lines changed

2 files changed

+16
-9
lines changed

mypy/semanal.py

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1351,8 +1351,8 @@ def check_namedtuple(self, node: Node) -> TypeInfo:
13511351
fullname = callee.fullname
13521352
if fullname not in ('collections.namedtuple', 'typing.NamedTuple'):
13531353
return None
1354-
items, types = self.parse_namedtuple_args(call, fullname)
1355-
if not items:
1354+
items, types, ok = self.parse_namedtuple_args(call, fullname)
1355+
if not ok:
13561356
# Error. Construct dummy return value.
13571357
return self.build_namedtuple_typeinfo('namedtuple', [], [])
13581358
else:
@@ -1362,7 +1362,7 @@ def check_namedtuple(self, node: Node) -> TypeInfo:
13621362
return info
13631363

13641364
def parse_namedtuple_args(self, call: CallExpr,
1365-
fullname: str) -> Tuple[List[str], List[Type]]:
1365+
fullname: str) -> Tuple[List[str], List[Type], bool]:
13661366
# TODO Share code with check_argument_count in checkexpr.py?
13671367
args = call.args
13681368
if len(args) < 2:
@@ -1375,6 +1375,7 @@ def parse_namedtuple_args(self, call: CallExpr,
13751375
return self.fail_namedtuple_arg(
13761376
"namedtuple() expects a string literal as the first argument", call)
13771377
types = [] # type: List[Type]
1378+
ok = True
13781379
if not isinstance(args[1], ListExpr):
13791380
if fullname == 'collections.namedtuple' and isinstance(args[1], StrExpr):
13801381
str_expr = cast(StrExpr, args[1])
@@ -1392,13 +1393,13 @@ def parse_namedtuple_args(self, call: CallExpr,
13921393
items = [cast(StrExpr, item).value for item in listexpr.items]
13931394
else:
13941395
# The fields argument contains (name, type) tuples.
1395-
items, types = self.parse_namedtuple_fields_with_types(listexpr.items, call)
1396+
items, types, ok = self.parse_namedtuple_fields_with_types(listexpr.items, call)
13961397
if not types:
13971398
types = [AnyType() for _ in items]
1398-
return items, types
1399+
return items, types, ok
13991400

14001401
def parse_namedtuple_fields_with_types(self, nodes: List[Node],
1401-
context: Context) -> Tuple[List[str], List[Type]]:
1402+
context: Context) -> Tuple[List[str], List[Type], bool]:
14021403
items = [] # type: List[str]
14031404
types = [] # type: List[Type]
14041405
for item in nodes:
@@ -1418,11 +1419,12 @@ def parse_namedtuple_fields_with_types(self, nodes: List[Node],
14181419
types.append(self.anal_type(type))
14191420
else:
14201421
return self.fail_namedtuple_arg("Tuple expected as NamedTuple() field", item)
1421-
return items, types
1422+
return items, types, True
14221423

1423-
def fail_namedtuple_arg(self, message: str, context: Context) -> Tuple[List[str], List[Type]]:
1424+
def fail_namedtuple_arg(self, message: str,
1425+
context: Context) -> Tuple[List[str], List[Type], bool]:
14241426
self.fail(message, context)
1425-
return [], []
1427+
return [], [], False
14261428

14271429
def build_namedtuple_typeinfo(self, name: str, items: List[str],
14281430
types: List[Type]) -> TypeInfo:

mypy/test/data/check-namedtuple.test

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,3 +168,8 @@ a = (1,) # E: Incompatible types in assignment (expression has type "Tuple[int]
168168
import collections
169169
MyNamedTuple = collections.namedtuple('MyNamedTuple', ['spam', 'eggs'])
170170
MyNamedTuple.x # E: "MyNamedTuple" has no attribute "x"
171+
172+
[case testNamedTupleEmptyItems]
173+
from typing import NamedTuple
174+
A = NamedTuple('A', [])
175+
[builtins fixtures/list.py]

0 commit comments

Comments
 (0)
0