From 7c4910fe30cdc31b335f890e83c72efeb7682cb7 Mon Sep 17 00:00:00 2001 From: elazar Date: Tue, 4 Apr 2017 02:03:57 +0300 Subject: [PATCH 1/4] Support underscore vars --- mypy/checker.py | 8 +++++--- mypy/semanal.py | 3 ++- test-data/unit/check-basic.test | 7 +++++++ 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/mypy/checker.py b/mypy/checker.py index 431d2d38aabe..4f2de7f894b9 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -1566,12 +1566,14 @@ def check_lvalue(self, lvalue: Lvalue) -> Tuple[Type, IndexExpr, Var]: elif isinstance(lvalue, IndexExpr): index_lvalue = lvalue elif isinstance(lvalue, MemberExpr): - lvalue_type = self.expr_checker.analyze_ordinary_member_access(lvalue, - True) + lvalue_type = self.expr_checker.analyze_ordinary_member_access(lvalue, True) self.store_type(lvalue, lvalue_type) elif isinstance(lvalue, NameExpr): lvalue_type = self.expr_checker.analyze_ref_expr(lvalue, lvalue=True) - self.store_type(lvalue, lvalue_type) + if lvalue.name == '_': + lvalue_type = AnyType() + else: + self.store_type(lvalue, lvalue_type) elif isinstance(lvalue, TupleExpr) or isinstance(lvalue, ListExpr): types = [self.check_lvalue(sub_expr)[0] for sub_expr in lvalue.items] lvalue_type = TupleType(types, self.named_type('builtins.tuple')) diff --git a/mypy/semanal.py b/mypy/semanal.py index 8f285c135242..afe395ff5cfa 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -3294,7 +3294,8 @@ def name_not_defined(self, name: str, ctx: Context) -> None: self.fail(message, ctx) def name_already_defined(self, name: str, ctx: Context) -> None: - self.fail("Name '{}' already defined".format(name), ctx) + if name != '_': + self.fail("Name '{}' already defined".format(name), ctx) def fail(self, msg: str, ctx: Context, serious: bool = False, *, blocker: bool = False) -> None: diff --git a/test-data/unit/check-basic.test b/test-data/unit/check-basic.test index 05fa1a954cc2..b7d2efd66603 100644 --- a/test-data/unit/check-basic.test +++ b/test-data/unit/check-basic.test @@ -261,6 +261,13 @@ main:3: error: Incompatible types in assignment (expression has type "B", variab main:7: error: Incompatible types in assignment (expression has type "A", variable has type "B") main:9: error: Incompatible types in assignment (expression has type "B", variable has type "A") +[case testUnderscoreVariableIsFresh] +_ = 1 +_ = "" +_ = "" # type: int +(_, _) = ("", 1.0 + "") # E: Unsupported left operand type for + ("float") +(_, _) = (1.0, "") + [case testGlobalDefinedInBlockWithType] class A: pass From 88a04371ac815df51c68341b409ed4099272b7a8 Mon Sep 17 00:00:00 2001 From: elazar Date: Tue, 4 Apr 2017 02:16:29 +0300 Subject: [PATCH 2/4] Support underscore parameters --- mypy/fastparse.py | 2 ++ mypy/fastparse2.py | 2 ++ test-data/unit/check-basic.test | 3 +++ 3 files changed, 7 insertions(+) diff --git a/mypy/fastparse.py b/mypy/fastparse.py index 1699f351f4f0..faa2b4a6724e 100644 --- a/mypy/fastparse.py +++ b/mypy/fastparse.py @@ -447,6 +447,8 @@ def make_argument(arg: ast3.arg, default: Optional[ast3.expr], kind: int) -> Arg seen_names = set() # type: Set[str] for name in names: if name.arg in seen_names: + if name.arg == '_': + continue self.fail("duplicate argument '{}' in function definition".format(name.arg), name.lineno, name.col_offset) break diff --git a/mypy/fastparse2.py b/mypy/fastparse2.py index a8039766384d..7ec332bd4ac1 100644 --- a/mypy/fastparse2.py +++ b/mypy/fastparse2.py @@ -442,6 +442,8 @@ def get_type(i: int) -> Optional[Type]: seen_names = set() # type: Set[str] for name in names: if name in seen_names: + if name.arg == '_': + continue self.fail("duplicate argument '{}' in function definition".format(name), line, 0) break seen_names.add(name) diff --git a/test-data/unit/check-basic.test b/test-data/unit/check-basic.test index b7d2efd66603..1899332c0a69 100644 --- a/test-data/unit/check-basic.test +++ b/test-data/unit/check-basic.test @@ -267,6 +267,9 @@ _ = "" _ = "" # type: int (_, _) = ("", 1.0 + "") # E: Unsupported left operand type for + ("float") (_, _) = (1.0, "") +for (_, _) in ((1, "a"), (2, "b")): pass + +def f(_: int, _: str) -> None: pass [case testGlobalDefinedInBlockWithType] From 243094be691c582d672f728fe0e27b91944f52c6 Mon Sep 17 00:00:00 2001 From: elazar Date: Tue, 4 Apr 2017 02:22:48 +0300 Subject: [PATCH 3/4] fix Python2 strangeness --- mypy/fastparse2.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypy/fastparse2.py b/mypy/fastparse2.py index 7ec332bd4ac1..f332ba25f314 100644 --- a/mypy/fastparse2.py +++ b/mypy/fastparse2.py @@ -442,7 +442,7 @@ def get_type(i: int) -> Optional[Type]: seen_names = set() # type: Set[str] for name in names: if name in seen_names: - if name.arg == '_': + if name == '_': continue self.fail("duplicate argument '{}' in function definition".format(name), line, 0) break From a7b3d857eb945635ddac5f3f909cb8c9538306ba Mon Sep 17 00:00:00 2001 From: elazar Date: Tue, 4 Apr 2017 13:02:22 +0300 Subject: [PATCH 4/4] disallow multiple underscore params; test with and parameters --- mypy/fastparse.py | 2 -- mypy/fastparse2.py | 2 -- test-data/unit/check-basic.test | 12 +++++++++++- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/mypy/fastparse.py b/mypy/fastparse.py index faa2b4a6724e..1699f351f4f0 100644 --- a/mypy/fastparse.py +++ b/mypy/fastparse.py @@ -447,8 +447,6 @@ def make_argument(arg: ast3.arg, default: Optional[ast3.expr], kind: int) -> Arg seen_names = set() # type: Set[str] for name in names: if name.arg in seen_names: - if name.arg == '_': - continue self.fail("duplicate argument '{}' in function definition".format(name.arg), name.lineno, name.col_offset) break diff --git a/mypy/fastparse2.py b/mypy/fastparse2.py index f332ba25f314..a8039766384d 100644 --- a/mypy/fastparse2.py +++ b/mypy/fastparse2.py @@ -442,8 +442,6 @@ def get_type(i: int) -> Optional[Type]: seen_names = set() # type: Set[str] for name in names: if name in seen_names: - if name == '_': - continue self.fail("duplicate argument '{}' in function definition".format(name), line, 0) break seen_names.add(name) diff --git a/test-data/unit/check-basic.test b/test-data/unit/check-basic.test index 1899332c0a69..9c7b63dfe80f 100644 --- a/test-data/unit/check-basic.test +++ b/test-data/unit/check-basic.test @@ -262,14 +262,24 @@ main:7: error: Incompatible types in assignment (expression has type "A", variab main:9: error: Incompatible types in assignment (expression has type "B", variable has type "A") [case testUnderscoreVariableIsFresh] +from typing import Tuple _ = 1 _ = "" _ = "" # type: int (_, _) = ("", 1.0 + "") # E: Unsupported left operand type for + ("float") (_, _) = (1.0, "") for (_, _) in ((1, "a"), (2, "b")): pass +(None for (_, _) in ((1, "a"), (2, "b"))) -def f(_: int, _: str) -> None: pass +class A: + def __enter__(self) -> Tuple[int, str]: ... + def __exit__(self, *_) -> None: ... + +with A() as (_, _): pass + +def f(_: int) -> None: + _ = "" + _, _ = (1.0, b"") [case testGlobalDefinedInBlockWithType]