[ty] Todo-types for os.fdopen, NamedTemporaryFile, and Path.open (#20549)

## Summary

This applies the trick that we use for `builtins.open` to similar
functions that have the same problem. The reason is that the problem
would otherwise become even more pronounced once we add understanding of
the implicit type of `self` parameters, because then something like
`(base_path / "test.bin").open("rb")` also leads to a wrong return type
and can result in false positives.

## Test Plan

New Markdown tests
This commit is contained in:
David Peter 2025-09-24 15:43:58 +02:00 committed by GitHub
parent eea87e24e3
commit fcc76bb7b2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 240 additions and 100 deletions

View file

@ -162,22 +162,3 @@ def _(x: A | B, y: list[int]):
reveal_type(x) # revealed: B & ~A
reveal_type(isinstance(x, B)) # revealed: Literal[True]
```
## Calls to `open()`
We do not fully understand typeshed's overloads for `open()` yet, due to missing support for PEP-613
type aliases. However, we also do not emit false-positive diagnostics on common calls to `open()`:
```py
import pickle
reveal_type(open("")) # revealed: TextIOWrapper[_WrappedBuffer]
reveal_type(open("", "r")) # revealed: TextIOWrapper[_WrappedBuffer]
reveal_type(open("", "rb")) # revealed: @Todo(`builtins.open` return type)
with open("foo.pickle", "rb") as f:
x = pickle.load(f) # fine
def _(mode: str):
reveal_type(open("", mode)) # revealed: @Todo(`builtins.open` return type)
```

View file

@ -0,0 +1,68 @@
# Calls to `open()`
## `builtins.open`
We do not fully understand typeshed's overloads for `open()` yet, due to missing support for PEP-613
type aliases. However, we also do not emit false-positive diagnostics on common calls to `open()`:
```py
import pickle
reveal_type(open("")) # revealed: TextIOWrapper[_WrappedBuffer]
reveal_type(open("", "r")) # revealed: TextIOWrapper[_WrappedBuffer]
reveal_type(open("", "rb")) # revealed: @Todo(`builtins.open` return type)
with open("foo.pickle", "rb") as f:
x = pickle.load(f) # fine
def _(mode: str):
reveal_type(open("", mode)) # revealed: @Todo(`builtins.open` return type)
```
## `os.fdopen`
The same is true for `os.fdopen()`:
```py
import pickle
import os
reveal_type(os.fdopen(0)) # revealed: TextIOWrapper[_WrappedBuffer]
reveal_type(os.fdopen(0, "r")) # revealed: TextIOWrapper[_WrappedBuffer]
reveal_type(os.fdopen(0, "rb")) # revealed: @Todo(`os.fdopen` return type)
with os.fdopen(0, "rb") as f:
x = pickle.load(f) # fine
```
## `Path.open`
And similarly for `Path.open()`:
```py
from pathlib import Path
import pickle
reveal_type(Path("").open()) # revealed: @Todo(`Path.open` return type)
reveal_type(Path("").open("r")) # revealed: @Todo(`Path.open` return type)
reveal_type(Path("").open("rb")) # revealed: @Todo(`Path.open` return type)
with Path("foo.pickle").open("rb") as f:
x = pickle.load(f) # fine
```
## `NamedTemporaryFile`
And similarly for `tempfile.NamedTemporaryFile()`:
```py
from tempfile import NamedTemporaryFile
import pickle
reveal_type(NamedTemporaryFile()) # revealed: _TemporaryFileWrapper[bytes]
reveal_type(NamedTemporaryFile("r")) # revealed: _TemporaryFileWrapper[str]
reveal_type(NamedTemporaryFile("rb")) # revealed: @Todo(`tempfile.NamedTemporaryFile` return type)
with NamedTemporaryFile("rb") as f:
x = pickle.load(f) # fine
```