ruff/crates/ty_python_semantic/resources/mdtest/call/open.md
David Peter fcc76bb7b2
[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
2025-09-24 15:43:58 +02:00

1.8 KiB

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():

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():

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():

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():

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