Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 10 additions & 4 deletions mypy/checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -5298,16 +5298,22 @@ def get_types_from_except_handler(self, typ: Type, n: Expression) -> list[Type]:
"""Helper for check_except_handler_test to retrieve handler types."""
typ = get_proper_type(typ)
if isinstance(typ, TupleType):
return typ.items
merged_type = make_simplified_union(typ.items)
if isinstance(merged_type, UnionType):
return merged_type.relevant_items()
return [merged_type]
elif is_named_instance(typ, "builtins.tuple"):
# variadic tuple
merged_type = make_simplified_union((typ.args[0],))
if isinstance(merged_type, UnionType):
return merged_type.relevant_items()
return [merged_type]
elif isinstance(typ, UnionType):
return [
union_typ
for item in typ.relevant_items()
for union_typ in self.get_types_from_except_handler(item, n)
]
elif is_named_instance(typ, "builtins.tuple"):
# variadic tuple
return [typ.args[0]]
else:
return [typ]

Expand Down
2 changes: 1 addition & 1 deletion mypy/fastparse.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import sys
import warnings
from collections.abc import Sequence
from typing import Any, Callable, Final, Literal, TypeVar, Union, cast, overload
from typing import Any, Callable, Final, Literal, TypeVar, cast, overload

from mypy import defaults, errorcodes as codes, message_registry
from mypy.errors import Errors
Expand Down
51 changes: 51 additions & 0 deletions test-data/unit/check-statements.test
Original file line number Diff line number Diff line change
Expand Up @@ -801,6 +801,57 @@ def error_in_variadic(exc: Tuple[int, ...]) -> None:

[builtins fixtures/tuple.pyi]

[case testExceptWithMultipleTypes5]
from typing import Tuple, Type, Union

class E1(BaseException): pass
class E2(BaseException): pass
class E3(BaseException): pass

def union_in_variadic(exc: Tuple[Union[Type[E1], Type[E2]], ...]) -> None:
try:
pass
except exc as e:
reveal_type(e) # N: Revealed type is "Union[__main__.E1, __main__.E2]"

def nested_union_in_variadic(exc: Tuple[Union[Type[E1], Union[Type[E2], Type[E3]]], ...]) -> None:
try:
pass
except exc as e:
reveal_type(e) # N: Revealed type is "Union[__main__.E1, __main__.E2, __main__.E3]"

def union_in_tuple(exc: Tuple[Union[Type[E1], Type[E2]], Type[E3]]) -> None:
try:
pass
except exc as e:
reveal_type(e) # N: Revealed type is "Union[__main__.E1, __main__.E2, __main__.E3]"

def error_in_variadic_union(exc: Tuple[Union[Type[E1], int], ...]) -> None:
try:
pass
except exc as e: # E: Exception type must be derived from BaseException (or be a tuple of exception classes)
pass

def error_in_variadic_nested_union(exc: Tuple[Union[Type[E1], Union[Type[E2], int]], ...]) -> None:
try:
pass
except exc as e: # E: Exception type must be derived from BaseException (or be a tuple of exception classes)
pass

def error_in_tuple_inside_variadic_nested_union(exc: Tuple[Union[Type[E1], Union[Type[E2], Tuple[Type[E3]]]], ...]) -> None:
try:
pass
except exc as e: # E: Exception type must be derived from BaseException (or be a tuple of exception classes)
pass

def error_in_tuple_union(exc: Tuple[Union[Type[E1], Type[E2]], Union[Type[E3], int]]) -> None:
try:
pass
except exc as e: # E: Exception type must be derived from BaseException (or be a tuple of exception classes)
pass

[builtins fixtures/tuple.pyi]

[case testExceptWithAnyTypes]
from typing import Any

Expand Down