You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Conditional expression in "with" statement inferred as 'object', lacking __enter__ and __exit__ #5512
from tempfile import TemporaryDirectory, TemporaryFile
import sys
use_file = 'directory' not in sys.argv
with (TemporaryFile() if use_file else TemporaryDirectory()) as thing:
print(thing)
Mypy infers the type of the conditional expression as object rather than Union[IO,TemporaryDirectory]
$ mypy multi_with.py
multi_with.py:6: error: "object" has no attribute "__enter__"
multi_with.py:6: error: "object" has no attribute "__exit__"
Explicitly typing the result of the conditional expression makes the error messages go away:
named_intermediate: Union[IO, TemporaryDirectory] = (TemporaryFile() if use_file else TemporaryDirectory())
with named_intermediate as thing:
print(thing)
I observe this in both mypy versions I tried: 0.600 and 0.620
These past issues and pull requests look relevant: #3487 Type of conditional expression is join instead of union #5041 Fix type of conditional statement to Union and not Join. #5095 Don't always infer unions for conditional expressions
Yes, one option is to infer a union for conditional expression. Another option however is to still use join, but fix #3830 (at leat for the situation where we have a protocol context, like ContextManager in this case, which should be pretty straightforward)
Activity
ilevkivskyi commentedon Aug 23, 2018
Yes, one option is to infer a union for conditional expression. Another option however is to still use join, but fix #3830 (at leat for the situation where we have a protocol context, like
ContextManagerin this case, which should be pretty straightforward)indigoviolet commentedon Mar 21, 2021
This bug still seems to be open in mypy 0.812: https://mypy-play.net/?mypy=latest&python=3.9&gist=35daf188cbaa119b95c77522250a6081
I don't quite understand why
ContextManager[None]doesn't suffice/workifblock instead of theif elseexpression is differentAnyway, @ilevkivskyi's #5512 (comment) doesn't seem to be relevant any longer.
MattiasMartens commentedon May 3, 2022
Still open as of 0.942.
For reference of contemporary Googlers, the specific error message has changed:
ilevkivskyi commentedon Jul 14, 2024
The original example now works on master.
ar4hc commentedon Jan 15, 2026
Variation that still fails, with mypy 1.19.1:
has to be
ilevkivskyi commentedon Jan 16, 2026
@ar4hc I can't reproduce this with mypy 1.19.1. I just tried
and I am getting
which is what I would expect.