Skip to content

Commit b75f886

Browse files
committed
Respond to code review; partially disable heuristics when strict-optional is disabled
1 parent 24ad85f commit b75f886

File tree

4 files changed

+208
-83
lines changed

4 files changed

+208
-83
lines changed

mypy/checker.py

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3312,14 +3312,30 @@ def visit_with_stmt(self, s: WithStmt) -> None:
33123312
exit_ret_type = self.check_async_with_item(expr, target, s.unanalyzed_type is None)
33133313
else:
33143314
exit_ret_type = self.check_with_item(expr, target, s.unanalyzed_type is None)
3315+
3316+
# Based on the return type, determine if this context manager 'swallows'
3317+
# exceptions or not. We determine this using a heuristic based on the
3318+
# return type of the __exit__ method -- see the discussion in
3319+
# https://github.com/python/mypy/issues/7214 and the section about context managers
3320+
# in https://github.com/python/typeshed/blob/master/CONTRIBUTING.md#conventions
3321+
# for more details.
3322+
3323+
exit_ret_type = get_proper_type(exit_ret_type)
33153324
if is_literal_type(exit_ret_type, "builtins.bool", False):
33163325
continue
3317-
if is_literal_type(exit_ret_type, "builtins.bool", True):
3318-
exceptions_maybe_suppressed = True
3319-
elif (isinstance(exit_ret_type, Instance)
3320-
and exit_ret_type.type.fullname() == 'builtins.bool'):
3326+
3327+
if (is_literal_type(exit_ret_type, "builtins.bool", True)
3328+
or (isinstance(exit_ret_type, Instance)
3329+
and exit_ret_type.type.fullname() == 'builtins.bool'
3330+
and state.strict_optional)):
3331+
# Note: if strict-optional is disabled, this bool instance
3332+
# could actually be an Optional[bool].
33213333
exceptions_maybe_suppressed = True
3334+
33223335
if exceptions_maybe_suppressed:
3336+
# Treat this 'with' block in the same way we'd treat a 'try: BODY; except: pass'
3337+
# block. This means control flow can continue after the 'with' even if the 'with'
3338+
# block immediately returns.
33233339
with self.binder.frame_context(can_skip=True, try_frame=True):
33243340
self.accept(s.body)
33253341
else:

mypy/types.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2405,10 +2405,8 @@ def remove_optional(typ: Type) -> ProperType:
24052405
return typ
24062406

24072407

2408-
def is_literal_type(typ: Type, fallback_fullname: str, value: LiteralValue) -> bool:
2409-
"""Returns 'true' if this type is a LiteralType with the given value
2410-
and underlying base fallback type.
2411-
"""
2408+
def is_literal_type(typ: ProperType, fallback_fullname: str, value: LiteralValue) -> bool:
2409+
"""Check if this type is a LiteralType with the given fallback type and value."""
24122410
if isinstance(typ, Instance) and typ.last_known_value:
24132411
typ = typ.last_known_value
24142412
if not isinstance(typ, LiteralType):

0 commit comments

Comments
 (0)