Improve open overloads when mode is a literal union (#7428)

As pointed out by @gvanrossum in https://github.com/python/typing/issues/1096

Improves type inference in cases when we know that mode is
OpenBinaryMode, but don't know anything more specific:
```
def my_open(name: str, write: bool):
    mode: Literal['rb', 'wb'] = 'wb' if write else 'rb'
    with open(name, mode) as f:
        reveal_type(f)  # previously typing.IO[Any], now typing.BinaryIO
```

You may be tempted into thinking this is some limitation of type
checkers. mypy does in fact have logic for detecting if we match
multiple overloads and union-ing up the return types of matched
overloads. The problem is the last overload interferes with this logic.
That is, if you remove the fallback overload (prior to this PR), you'd get
"Union[io.BufferedReader, io.BufferedWriter]" in the above example.

Co-authored-by: hauntsaninja <>
This commit is contained in:
Shantanu
2022-03-06 15:45:34 -08:00
committed by GitHub
parent b9909b121e
commit 9796b9ed69
5 changed files with 5 additions and 5 deletions

View File

@@ -147,7 +147,7 @@ class Path(PurePath):
# Buffering cannot be determined: fall back to BinaryIO
@overload
def open(
self, mode: OpenBinaryMode, buffering: int, encoding: None = ..., errors: None = ..., newline: None = ...
self, mode: OpenBinaryMode, buffering: int = ..., encoding: None = ..., errors: None = ..., newline: None = ...
) -> BinaryIO: ...
# Fallback if mode is not specified
@overload