Skip to content

Conditional expression in "with" statement inferred as 'object', lacking __enter__ and __exit__ #5512

Closed
@chkno

Description

@chkno
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

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions