mirror of
https://github.com/astral-sh/ruff
synced 2026-01-05 05:34:03 -05:00
Refs https://github.com/astral-sh/ty/issues/544 ## Summary Takes a more incremental approach to PEP 613 type alias support (vs https://github.com/astral-sh/ruff/pull/20107). Instead of eagerly inferring the RHS of a PEP 613 type alias as a type expression, infer it as a value expression, just like we do for implicit type aliases, taking advantage of the same support for e.g. unions and other type special forms. The main reason I'm following this path instead of the one in https://github.com/astral-sh/ruff/pull/20107 is that we've realized that people do sometimes use PEP 613 type aliases as values, not just as types (because they are just a normal runtime assignment, unlike PEP 695 type aliases which create an opaque `TypeAliasType`). This PR doesn't yet provide full support for recursive type aliases (they don't panic, but they just fall back to `Unknown` at the recursion point). This is future work. ## Test Plan Added mdtests. Many new ecosystem diagnostics, mostly because we understand new types in lots of places. Conformance suite changes are correct. Performance regression is due to understanding lots of new types; nothing we do in this PR is inherently expensive.
1.8 KiB
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: BufferedReader[_BufferedReaderStream]
with open("foo.pickle", "rb") as f:
x = pickle.load(f) # fine
def _(mode: str):
reveal_type(open("", mode)) # revealed: IO[Any]
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: BufferedReader[_BufferedReaderStream]
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: TextIOWrapper[_WrappedBuffer]
reveal_type(Path("").open("r")) # revealed: TextIOWrapper[_WrappedBuffer]
reveal_type(Path("").open("rb")) # revealed: BufferedReader[_BufferedReaderStream]
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: _TemporaryFileWrapper[bytes]
with NamedTemporaryFile("rb") as f:
x = pickle.load(f) # fine