From d11b4bc934a510499ec0404a3294476ce03b6d82 Mon Sep 17 00:00:00 2001 From: Peter McCormick Date: Fri, 3 Jun 2016 18:33:21 -0400 Subject: [PATCH 1/4] Allow `Any` types for tuple except handler tests Fixes #1635. --- mypy/checker.py | 6 +++-- mypy/test/data/check-statements.test | 33 ++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/mypy/checker.py b/mypy/checker.py index ea9641ff1276..d2f8ebeb3093 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -1827,13 +1827,15 @@ def visit_try_stmt(self, s: TryStmt) -> Type: def visit_except_handler_test(self, n: Node) -> Type: """Type check an exception handler test clause.""" type = self.accept(n) - if isinstance(type, AnyType): - return type all_types = [] # type: List[Type] test_types = type.items if isinstance(type, TupleType) else [type] for ttype in test_types: + if isinstance(ttype, AnyType): + all_types.append(ttype) + continue + if not isinstance(ttype, FunctionLike): self.fail(messages.INVALID_EXCEPTION_TYPE, n) return AnyType() diff --git a/mypy/test/data/check-statements.test b/mypy/test/data/check-statements.test index f888689c7dfa..8a7e10ca5ea1 100644 --- a/mypy/test/data/check-statements.test +++ b/mypy/test/data/check-statements.test @@ -598,6 +598,39 @@ except (E1_1, E1_2) as e2: c = e2 # type: E1_2 # E: Incompatible types in assignment (expression has type "Union[E1_1, E1_2]", variable has type "E1_2") [builtins fixtures/exception.py] +[case testExceptWithAnyTypes] +from typing import Any + +E1 = None # type: Any +class E2(BaseException): pass +class NotBaseDerived: pass + +try: + pass +except BaseException as e1: + reveal_type(e1) # E: Revealed type is 'builtins.BaseException' +except (E1, BaseException) as e2: + reveal_type(e2) # E: Revealed type is 'Any' +except (E1, E2) as e3: + reveal_type(e3) # E: Revealed type is 'Any' +except (E1, E2, BaseException) as e4: + reveal_type(e4) # E: Revealed type is 'Any' + +try: pass +except E1 as e1: + reveal_type(e1) # E: Revealed type is 'Any' +except E2 as e2: + reveal_type(e2) # E: Revealed type is '__main__.E2' +except NotBaseDerived as e3: # E: Exception type must be derived from BaseException + pass +except (NotBaseDerived, E1) as e4: # E: Exception type must be derived from BaseException + pass +except (NotBaseDerived, E2) as e5: # E: Exception type must be derived from BaseException + pass +except (NotBaseDerived, E1, E2) as e6: # E: Exception type must be derived from BaseException + pass +[builtins fixtures/exception.py] + [case testReuseTryExceptionVariable] import typing class E1(BaseException): pass From 00faff4a5869dbd8e77ea3c7e64df257495fc79b Mon Sep 17 00:00:00 2001 From: Peter McCormick Date: Fri, 3 Jun 2016 18:52:42 -0400 Subject: [PATCH 2/4] If even just one test has `Any` type then the whole expression will be `Any` --- mypy/checker.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/mypy/checker.py b/mypy/checker.py index d2f8ebeb3093..aa5569d01b19 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -1833,8 +1833,7 @@ def visit_except_handler_test(self, n: Node) -> Type: for ttype in test_types: if isinstance(ttype, AnyType): - all_types.append(ttype) - continue + return AnyType() if not isinstance(ttype, FunctionLike): self.fail(messages.INVALID_EXCEPTION_TYPE, n) From 7b4d5c423eb9d6532dcc0604b9c33a0fc0e6a32e Mon Sep 17 00:00:00 2001 From: Peter McCormick Date: Fri, 3 Jun 2016 18:55:40 -0400 Subject: [PATCH 3/4] Revert "If even just one test has `Any` type then the whole expression will be `Any`" This reverts commit 00faff4a5869dbd8e77ea3c7e64df257495fc79b. --- mypy/checker.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mypy/checker.py b/mypy/checker.py index aa5569d01b19..d2f8ebeb3093 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -1833,7 +1833,8 @@ def visit_except_handler_test(self, n: Node) -> Type: for ttype in test_types: if isinstance(ttype, AnyType): - return AnyType() + all_types.append(ttype) + continue if not isinstance(ttype, FunctionLike): self.fail(messages.INVALID_EXCEPTION_TYPE, n) From 9ff26f699de49cae5598ba931ef4f817cc2ea9e9 Mon Sep 17 00:00:00 2001 From: Peter McCormick Date: Fri, 3 Jun 2016 18:56:28 -0400 Subject: [PATCH 4/4] Ensure all errors are reported, regardless of where the `Any` appears --- mypy/test/data/check-statements.test | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mypy/test/data/check-statements.test b/mypy/test/data/check-statements.test index 8a7e10ca5ea1..06a333735352 100644 --- a/mypy/test/data/check-statements.test +++ b/mypy/test/data/check-statements.test @@ -629,6 +629,8 @@ except (NotBaseDerived, E2) as e5: # E: Exception type must be derived from Bas pass except (NotBaseDerived, E1, E2) as e6: # E: Exception type must be derived from BaseException pass +except (E1, E2, NotBaseDerived) as e6: # E: Exception type must be derived from BaseException + pass [builtins fixtures/exception.py] [case testReuseTryExceptionVariable]