Skip to content

Commit bb5134e

Browse files
committed
Tests all pass again after merge
1 parent 967bb5a commit bb5134e

File tree

7 files changed

+74
-63
lines changed

7 files changed

+74
-63
lines changed

mypy/exprtotype.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,8 @@ def expr_to_unanalyzed_type(expr: Expression) -> Type:
9292
types.append(expr_to_unanalyzed_type(it))
9393
names.append(None)
9494
kinds.append(ARG_POS)
95+
def fail(message, Expression):
96+
raise TypeTranslationError(message)
9597
return ArgumentList(types, names, kinds,
9698
line=expr.line, column=expr.column)
9799
elif isinstance(expr, (StrExpr, BytesExpr, UnicodeExpr)):

mypy/fastparse.py

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@
2020
StarExpr, YieldFromExpr, NonlocalDecl, DictionaryComprehension,
2121
SetComprehension, ComplexExpr, EllipsisExpr, YieldExpr, Argument,
2222
AwaitExpr, TempNode, Expression, Statement,
23-
ARG_POS, ARG_OPT, ARG_STAR, ARG_NAMED, ARG_NAMED_OPT, ARG_STAR2
23+
ARG_POS, ARG_OPT, ARG_STAR, ARG_NAMED, ARG_NAMED_OPT, ARG_STAR2,
24+
check_arg_names,
2425
)
2526
from mypy.types import (
2627
Type, CallableType, AnyType, UnboundType, TupleType, ArgumentList, EllipsisType,
@@ -152,6 +153,9 @@ def __init__(self,
152153
def fail(self, msg: str, line: int, column: int) -> None:
153154
self.errors.report(line, column, msg)
154155

156+
def fail_ast(self, msg: str, n: ast3.AST) -> None:
157+
self.fail(msg, n.lineno, n.col_offset)
158+
155159
def generic_visit(self, node: ast3.AST) -> None:
156160
raise RuntimeError('AST node not implemented: ' + str(type(node)))
157161

@@ -445,13 +449,7 @@ def make_argument(arg: ast3.arg, default: Optional[ast3.expr], kind: int) -> Arg
445449
new_args.append(make_argument(args.kwarg, None, ARG_STAR2))
446450
names.append(args.kwarg)
447451

448-
seen_names = set() # type: Set[str]
449-
for name in names:
450-
if name.arg in seen_names:
451-
self.fail("duplicate argument '{}' in function definition".format(name.arg),
452-
name.lineno, name.col_offset)
453-
break
454-
seen_names.add(name.arg)
452+
check_arg_names([name.arg for name in names], names, self.fail_ast)
455453

456454
return new_args
457455

@@ -1010,7 +1008,7 @@ def translate_argument_list(self, l: Sequence[ast3.AST]) -> ArgumentList:
10101008
typ = AnyType(implicit=True) # type: Type
10111009
for i, arg in enumerate(e.args):
10121010
if i == 0 and not star:
1013-
name = _extract_str(arg)
1011+
name = self._extract_str(arg)
10141012
elif i == 1 and not star or i == 0 and star:
10151013
typ = self.visit(arg)
10161014
else:
@@ -1019,7 +1017,7 @@ def translate_argument_list(self, l: Sequence[ast3.AST]) -> ArgumentList:
10191017
for k in e.keywords:
10201018
value = k.value
10211019
if k.arg == "name" and not star:
1022-
name = _extract_str(value)
1020+
name = self._extract_str(value)
10231021
elif k.arg == "typ":
10241022
typ = self.visit(value)
10251023
else:
@@ -1037,6 +1035,14 @@ def translate_argument_list(self, l: Sequence[ast3.AST]) -> ArgumentList:
10371035

10381036
return ArgumentList(types, names, kinds, line=self.line)
10391037

1038+
def _extract_str(self, n: ast3.AST) -> str:
1039+
if isinstance(n, ast3.Str):
1040+
return n.s.strip()
1041+
elif isinstance(n, ast3.NameConstant) and str(n.value) == 'None':
1042+
return None
1043+
self.fail('Expected string literal for argument name, got "{}"'.format(n), n.lineno, n.col_offset)
1044+
return None
1045+
10401046
def visit_Name(self, n: ast3.Name) -> Type:
10411047
return UnboundType(n.id, line=self.line)
10421048

@@ -1089,5 +1095,4 @@ def visit_Ellipsis(self, n: ast3.Ellipsis) -> Type:
10891095
# List(expr* elts, expr_context ctx)
10901096
def visit_List(self, n: ast3.List) -> Type:
10911097
l = len(n.elts)
1092-
return ArgumentList(
1093-
self.translate_expr_list(n.elts), [None]*l, [ARG_POS]*l, line=self.line)
1098+
return self.translate_argument_list(n.elts)

mypy/nodes.py

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from abc import abstractmethod
55

66
from typing import (
7-
Any, TypeVar, List, Tuple, cast, Set, Dict, Union, Optional
7+
Any, TypeVar, List, Tuple, cast, Set, Dict, Union, Optional, Callable,
88
)
99

1010
import mypy.strconv
@@ -2447,3 +2447,43 @@ def get_member_expr_fullname(expr: MemberExpr) -> str:
24472447
for key, obj in globals().items()
24482448
if isinstance(obj, type) and issubclass(obj, SymbolNode) and obj is not SymbolNode
24492449
}
2450+
2451+
def check_arg_kinds(arg_kinds: List[int], nodes: List[T], fail: Callable[[str, T], None]) -> None:
2452+
is_var_arg = False
2453+
is_kw_arg = False
2454+
seen_named = False
2455+
seen_opt = False
2456+
for kind, node in zip(arg_kinds, nodes):
2457+
if kind == ARG_POS:
2458+
if is_var_arg or is_kw_arg or seen_named or seen_opt:
2459+
fail("Required positional args may not appear "
2460+
"after default, named or star args",
2461+
node)
2462+
break
2463+
elif kind == ARG_OPT:
2464+
if is_var_arg or is_kw_arg or seen_named:
2465+
fail("Positional default args may not appear after named or star args", node)
2466+
break
2467+
seen_opt = True
2468+
elif kind == ARG_STAR:
2469+
if is_var_arg or is_kw_arg or seen_named:
2470+
fail("Star args may not appear after named or star args", node)
2471+
break
2472+
is_var_arg = True
2473+
elif kind == ARG_NAMED or kind == ARG_NAMED_OPT:
2474+
seen_named = True
2475+
elif kind == ARG_STAR2:
2476+
if is_kw_arg:
2477+
fail("You may only have one **kwargs argument", node)
2478+
break
2479+
is_kw_arg = True
2480+
2481+
2482+
def check_arg_names(names: List[str], nodes: List[T], fail: Callable[[str, T], None],
2483+
description: str = 'function definition') -> None:
2484+
seen_names = set() # type: Set[str]
2485+
for name, node in zip(names, nodes):
2486+
if name is not None and name in seen_names:
2487+
fail("duplicate argument '{}' in {}".format(name, description), node)
2488+
break
2489+
seen_names.add(name)

mypy/server/astdiff.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
from mypy.nodes import SymbolTable, SymbolTableNode, FuncBase, TypeInfo, Var
1313
from mypy.types import (
14-
Type, TypeVisitor, UnboundType, TypeList, AnyType, NoneTyp, UninhabitedType,
14+
Type, TypeVisitor, UnboundType, ArgumentList, AnyType, NoneTyp, UninhabitedType,
1515
ErasedType, DeletedType, Instance, TypeVarType, CallableType, TupleType, TypedDictType,
1616
UnionType, Overloaded, PartialType, TypeType
1717
)
@@ -137,7 +137,7 @@ def __init__(self, right: Type) -> None:
137137
def visit_unbound_type(self, left: UnboundType) -> bool:
138138
return False
139139

140-
def visit_type_list(self, t: TypeList) -> bool:
140+
def visit_type_list(self, t: ArgumentList) -> bool:
141141
assert False, 'Not supported'
142142

143143
def visit_any(self, left: AnyType) -> bool:

mypy/typeanal.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,11 @@
99
StarType, PartialType, EllipsisType, UninhabitedType, TypeType, get_typ_args, set_typ_args,
1010
ArgKindException, ArgNameException, get_type_vars, union_items
1111
)
12+
1213
from mypy.nodes import (
1314
BOUND_TVAR, UNBOUND_TVAR, TYPE_ALIAS, UNBOUND_IMPORTED,
1415
TypeInfo, Context, SymbolTableNode, Var, Expression,
15-
IndexExpr, RefExpr, nongen_builtins,
16+
IndexExpr, RefExpr, nongen_builtins, check_arg_names, check_arg_kinds,
1617
)
1718
from mypy.sametypes import is_same_type
1819
from mypy.exprtotype import expr_to_unanalyzed_type, TypeTranslationError
@@ -382,6 +383,8 @@ def analyze_callable_type(self, t: UnboundType) -> Type:
382383
# Callable[[ARG, ...], RET] (ordinary callable type)
383384
args = t.args[0].types
384385
try:
386+
check_arg_names(t.args[0].names, [t]*len(args), self.fail, "Callable")
387+
check_arg_kinds(t.args[0].kinds, [t]*len(args), self.fail)
385388
return CallableType(self.anal_array(args),
386389
t.args[0].kinds,
387390
t.args[0].names,

mypy/types.py

Lines changed: 2 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -585,13 +585,13 @@ def __init__(self,
585585
special_sig: Optional[str] = None,
586586
from_type_type: bool = False,
587587
) -> None:
588-
self._process_kinds_on_init(arg_kinds)
589-
self._process_names_on_init(arg_names)
590588
if variables is None:
591589
variables = []
592590
assert len(arg_types) == len(arg_kinds)
593591
self.arg_types = arg_types
594592
self.arg_kinds = arg_kinds
593+
self.is_var_arg = ARG_STAR in arg_kinds
594+
self.is_kw_arg = ARG_STAR2 in arg_kinds
595595
self.arg_names = arg_names
596596
self.min_args = arg_kinds.count(ARG_POS)
597597
self.ret_type = ret_type
@@ -607,41 +607,6 @@ def __init__(self,
607607
self.from_type_type = from_type_type
608608
super().__init__(line, column)
609609

610-
def _process_names_on_init(self, arg_names):
611-
seen = set() # type: Set[str]
612-
for name in arg_names:
613-
if name is None:
614-
continue
615-
if name in seen:
616-
raise ArgNameException('Duplicate argument name "{}"'.format(name))
617-
seen.add(name)
618-
619-
def _process_kinds_on_init(self, arg_kinds):
620-
self.is_var_arg = False
621-
self.is_kw_arg = False
622-
seen_named = False
623-
seen_opt = False
624-
for kind in arg_kinds:
625-
if kind == ARG_POS:
626-
if self.is_var_arg or self.is_kw_arg or seen_named or seen_opt:
627-
raise ArgKindException("Required positional args may not appear "
628-
"after default, named or star args")
629-
elif kind == ARG_OPT:
630-
if self.is_var_arg or self.is_kw_arg or seen_named:
631-
raise ArgKindException("Positional default args may not appear "
632-
"after named or star args")
633-
seen_opt = True
634-
elif kind == ARG_STAR:
635-
if self.is_var_arg or self.is_kw_arg or seen_named:
636-
raise ArgKindException("Star args may not appear after named or star args")
637-
self.is_var_arg = True
638-
elif kind == ARG_NAMED or kind == ARG_NAMED_OPT:
639-
seen_named = True
640-
elif kind == ARG_STAR2:
641-
if self.is_kw_arg:
642-
raise ArgKindException("You may only have one **kwargs argument")
643-
self.is_kw_arg = True
644-
645610
def copy_modified(self,
646611
arg_types: List[Type] = _dummy,
647612
arg_kinds: List[int] = _dummy,

test-data/unit/check-functions.test

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1474,13 +1474,13 @@ from mypy_extensions import Arg, StarArg, KwArg
14741474

14751475
def WrongArg(x, y): return y
14761476

1477-
def a(f: Callable[[WrongArg('x', int)], int]): pass # E: Parse error before (: Unknown argument constructor WrongArg # E: Parse error before end of line
1478-
def b(f: Callable[[Arg('x', 1)], int]): pass # E: Parse error before numeric literal # E: Parse error before end of line
1479-
def c(f: Callable[[StarArg('x', int)], int]): pass # E: Parse error before "int": Unexpected argument for argument constructor # E: Parse error before end of line
1477+
def a(f: Callable[[WrongArg('x', int)], int]): pass # E: Unknown argument constructor WrongArg
1478+
def b(f: Callable[[Arg('x', 1)], int]): pass # E: invalid type comment or annotation
1479+
def c(f: Callable[[StarArg('x', int)], int]): pass # E: Too many arguments for argument constructor
14801480
def d(f: Callable[[StarArg(int)], int]): pass # ok
14811481
def e(f: Callable[[StarArg(), KwArg()], int]): pass # ok
14821482
def g(f: Callable[[Arg(name='x', typ=int)], int]): pass # ok
1483-
def h(f: Callable[[Arg(gnome='x', typ=int)], int]): pass # E: Parse error before "gnome": Unexpected argument "gnome" for argument constructor # E: Parse error before end of line
1483+
def h(f: Callable[[Arg(gnome='x', typ=int)], int]): pass # E: Unexpected argument "gnome" for argument constructor
14841484
def i(f: Callable[[Arg(name=None, typ=int)], int]): pass # ok
14851485

14861486
[builtins fixtures/dict.pyi]
@@ -1493,21 +1493,18 @@ def a(f: Callable[[WrongArg('x', int)], int]): pass # E: Unknown argument constr
14931493
[builtins fixtures/dict.pyi]
14941494

14951495
[case testCallableFastParseWrongTypeType]
1496-
# flags: --fast-parser
14971496
from typing import Callable
14981497
from mypy_extensions import Arg
1499-
def b(f: Callable[[Arg('x', 1)], int]): pass # E: Bad type for callable argument
1498+
def b(f: Callable[[Arg('x', 1)], int]): pass # E: invalid type comment or annotation
15001499
[builtins fixtures/dict.pyi]
15011500

15021501
[case testCallableFastParseTooManyStarArg]
1503-
# flags: --fast-parser
15041502
from typing import Callable
15051503
from mypy_extensions import StarArg
15061504
def c(f: Callable[[StarArg('x', int)], int]): pass # E: Too many arguments for argument constructor
15071505
[builtins fixtures/dict.pyi]
15081506

15091507
[case testCallableFastParseGood]
1510-
# flags: --fast-parser
15111508
from typing import Callable
15121509
from mypy_extensions import StarArg, Arg
15131510
def d(f: Callable[[StarArg(int)], int]): pass # ok
@@ -1517,7 +1514,6 @@ def i(f: Callable[[Arg(name=None, typ=int)], int]): pass # ok
15171514
[builtins fixtures/dict.pyi]
15181515

15191516
[case testCallableFastParseBadArgArgName]
1520-
# flags: --fast-parser
15211517
from typing import Callable
15221518
from mypy_extensions import Arg
15231519
def h(f: Callable[[Arg(gnome='x', typ=int)], int]): pass # E: Unexpected argument "gnome" for argument constructor
@@ -1539,7 +1535,7 @@ def j(f: Callable[[NamedArg('x'), DefaultArg('y', int)], int]): pass # E: Positi
15391535
from typing import Callable
15401536
from mypy_extensions import Arg, StarArg, KwArg, DefaultArg
15411537

1542-
def f(f: Callable[[Arg('x', int), int, Arg('x', int)], int]): pass # E: Duplicate argument name "x"
1538+
def f(f: Callable[[Arg('x', int), int, Arg('x', int)], int]): pass # E: duplicate argument 'x' in Callable
15431539

15441540
[builtins fixtures/dict.pyi]
15451541

0 commit comments

Comments
 (0)