Closed
Description
Bug Report
Consider the following snippet, adapted from argparse.FileType:
import sys
def opener(path: str, mode: str = "r") -> None:
if path and path != "-":
fh = open(path, mode)
else:
if "r" in mode:
fh = sys.stdin.buffer if 'b' in mode else sys.stdin
elif any(c in mode for c in 'wax'):
fh = sys.stdout.buffer if 'b' in mode else sys.stdout
else:
# intentionally not using custom exception
raise ValueError(f"Tried to open '-' (stdin/stdout) with mode {mode!r}")
...
mypy
gives errors for line 8 and 10 (the fh
assignments using sys.stdin
and sys.stdout
):
error: Incompatible types in assignment (expression has type "object", variable has type "IO[Any]") [assignment]
error: Incompatible types in assignment (expression has type "object", variable has type "IO[Any]") [assignment]
How come the expressions sys.stdin.buffer if 'b' in mode else sys.stdin
and sys.stdout.buffer if 'b' in mode else sys.stdout
has type evaluated as object
? Both sys.stdin
and sys.stdout
are strictly IO[str]
, and their buffers are IO[bytes]
, hence I expected both expressions to actually be IO[Any]
, matching the inferred type of open()
.
If I break the x = a if y else b
into proper if/else
statements, mypy does not complain:
if "r" in mode:
if 'b' in mode:
fh = sys.stdin.buffer
else:
fh = sys.stdin
else:
if 'b' in mode:
fh = sys.stdout,buffer
else:
fh = sys.stdout
Your Environment
Python 3.8 from apt repository and pip-installed mypy 1.4.1 (compiled: yes)
in a venv in Ubuntu 18.04