Skip to content

IO[Any] is not inferred as the supertype of IO[str] and IO[bytes] in condional expression v = iostr if x else iobytes #15808

Closed
@MestreLion

Description

@MestreLion

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugmypy got something wrongtopic-join-v-unionUsing join vs. using unions

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions