diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 6ed7dede571a..bf2fbc3f7488 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -22,7 +22,7 @@ repos: name: Run ruff on the test cases args: - "--exit-non-zero-on-fix" - - "--select=FA,I,RUF100" + - "--select=FA,I,ICN001,RUF100" - "--no-force-exclude" - "--unsafe-fixes" files: '.*test_cases/.+\.py$' diff --git a/pyproject.toml b/pyproject.toml index 63e187ac1dcd..5d6bd434156b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -83,6 +83,8 @@ select = [ "FURB169", # Compare the identities of `{object}` and None instead of their respective types "FURB177", # Prefer `Path.cwd()` over `Path().resolve()` for current-directory lookups "FURB187", # Use of assignment of `reversed` on list `{name}` + # Used for lint.flake8-import-conventions.aliases + "ICN001", # `{name}` should be imported as `{asname}` # Autofixable flake8-use-pathlib only "PTH201", # Do not pass the current directory explicitly to `Path` "PTH210", # Invalid suffix passed to `.with_suffix()` @@ -217,6 +219,8 @@ ignore = [ "PLC0414", # Import alias does not rename original package ] "*_pb2.pyi" = [ + # Special autogenerated typing --> typing_extensions aliases + "ICN001", # `{name}` should be imported as `{asname}` # Leave the docstrings as-is, matching source "D", # pydocstyle # See comment on black's force-exclude config above @@ -226,6 +230,11 @@ ignore = [ [tool.ruff.lint.pydocstyle] convention = "pep257" # https://docs.astral.sh/ruff/settings/#lint_pydocstyle_convention +[tool.ruff.lint.flake8-import-conventions.aliases] +# Prevent aliasing these, as it causes false-negatives for certain rules +typing_extensions = "typing_extensions" +typing = "typing" + [tool.ruff.lint.isort] split-on-trailing-comma = false combine-as-imports = true diff --git a/stdlib/@tests/test_cases/check_re.py b/stdlib/@tests/test_cases/check_re.py index b6ab2b0d59d2..dee87b474fe2 100644 --- a/stdlib/@tests/test_cases/check_re.py +++ b/stdlib/@tests/test_cases/check_re.py @@ -2,18 +2,18 @@ import mmap import re -import typing as t +from typing import AnyStr, Match, Optional from typing_extensions import assert_type def check_search(str_pat: re.Pattern[str], bytes_pat: re.Pattern[bytes]) -> None: - assert_type(str_pat.search("x"), t.Optional[t.Match[str]]) - assert_type(bytes_pat.search(b"x"), t.Optional[t.Match[bytes]]) - assert_type(bytes_pat.search(bytearray(b"x")), t.Optional[t.Match[bytes]]) - assert_type(bytes_pat.search(mmap.mmap(0, 10)), t.Optional[t.Match[bytes]]) + assert_type(str_pat.search("x"), Optional[Match[str]]) + assert_type(bytes_pat.search(b"x"), Optional[Match[bytes]]) + assert_type(bytes_pat.search(bytearray(b"x")), Optional[Match[bytes]]) + assert_type(bytes_pat.search(mmap.mmap(0, 10)), Optional[Match[bytes]]) -def check_search_with_AnyStr(pattern: re.Pattern[t.AnyStr], string: t.AnyStr) -> re.Match[t.AnyStr]: +def check_search_with_AnyStr(pattern: re.Pattern[AnyStr], string: AnyStr) -> re.Match[AnyStr]: """See issue #9591""" match = pattern.search(string) if match is None: diff --git a/stdlib/@tests/test_cases/typing/check_regression_issue_9296.py b/stdlib/@tests/test_cases/typing/check_regression_issue_9296.py index 34c5631aeb1a..23beaa87ae05 100644 --- a/stdlib/@tests/test_cases/typing/check_regression_issue_9296.py +++ b/stdlib/@tests/test_cases/typing/check_regression_issue_9296.py @@ -1,15 +1,15 @@ from __future__ import annotations -import typing as t +from typing import Any, KeysView, TypeVar -KT = t.TypeVar("KT") +KT = TypeVar("KT") -class MyKeysView(t.KeysView[KT]): +class MyKeysView(KeysView[KT]): pass -d: dict[t.Any, t.Any] = {} +d: dict[Any, Any] = {} dict_keys = type(d.keys()) # This should not cause an error like `Member "register" is unknown`: diff --git a/stdlib/_typeshed/__init__.pyi b/stdlib/_typeshed/__init__.pyi index 99d21b67360a..a503637998d0 100644 --- a/stdlib/_typeshed/__init__.pyi +++ b/stdlib/_typeshed/__init__.pyi @@ -3,7 +3,6 @@ # See the README.md file in this directory for more information. import sys -import typing_extensions from collections.abc import Awaitable, Callable, Iterable, Sequence, Set as AbstractSet, Sized from dataclasses import Field from os import PathLike @@ -23,7 +22,7 @@ from typing import ( final, overload, ) -from typing_extensions import Buffer, LiteralString, TypeAlias +from typing_extensions import Buffer, LiteralString, Self as _Self, TypeAlias _KT = TypeVar("_KT") _KT_co = TypeVar("_KT_co", covariant=True) @@ -329,9 +328,9 @@ class structseq(Generic[_T_co]): # The second parameter will accept a dict of any kind without raising an exception, # but only has any meaning if you supply it a dict where the keys are strings. # https://github.com/python/typeshed/pull/6560#discussion_r767149830 - def __new__(cls, sequence: Iterable[_T_co], dict: dict[str, Any] = ...) -> typing_extensions.Self: ... + def __new__(cls, sequence: Iterable[_T_co], dict: dict[str, Any] = ...) -> _Self: ... if sys.version_info >= (3, 13): - def __replace__(self, **kwargs: Any) -> typing_extensions.Self: ... + def __replace__(self, **kwargs: Any) -> _Self: ... # Superset of typing.AnyStr that also includes LiteralString AnyOrLiteralStr = TypeVar("AnyOrLiteralStr", str, bytes, LiteralString) # noqa: Y001 diff --git a/stdlib/typing_extensions.pyi b/stdlib/typing_extensions.pyi index 3799f4e666e9..bad5fae880c0 100644 --- a/stdlib/typing_extensions.pyi +++ b/stdlib/typing_extensions.pyi @@ -1,7 +1,6 @@ import abc import enum import sys -import typing from _collections_abc import dict_items, dict_keys, dict_values from _typeshed import IdentityFunction, Incomplete, Unused from collections.abc import ( @@ -57,6 +56,7 @@ from typing import ( # noqa: Y022,Y037,Y038,Y039,UP035 Tuple as Tuple, Type as Type, TypedDict as TypedDict, + TypeVar as _TypeVar, Union as Union, _Alias, cast as cast, @@ -195,10 +195,10 @@ __all__ = [ "CapsuleType", ] -_T = typing.TypeVar("_T") -_F = typing.TypeVar("_F", bound=Callable[..., Any]) -_TC = typing.TypeVar("_TC", bound=type[object]) -_T_co = typing.TypeVar("_T_co", covariant=True) # Any type covariant containers. +_T = _TypeVar("_T") +_F = _TypeVar("_F", bound=Callable[..., Any]) +_TC = _TypeVar("_TC", bound=type[object]) +_T_co = _TypeVar("_T_co", covariant=True) # Any type covariant containers. class _Final: ... # This should be imported from typing but that breaks pytype diff --git a/stubs/click-default-group/click_default_group.pyi b/stubs/click-default-group/click_default_group.pyi index 5c73c4dd8db4..83541f3cfbbf 100644 --- a/stubs/click-default-group/click_default_group.pyi +++ b/stubs/click-default-group/click_default_group.pyi @@ -1,5 +1,5 @@ -import typing as t from _typeshed import Incomplete +from collections.abc import Sequence import click @@ -23,7 +23,7 @@ class DefaultCommandFormatter: formatter: click.HelpFormatter mark: str def __init__(self, group: click.Group, formatter: click.HelpFormatter, mark: str = ...) -> None: ... - def write_dl(self, rows: t.Sequence[tuple[str, str]], col_max: int = 30, col_spacing: int = -2) -> None: ... + def write_dl(self, rows: Sequence[tuple[str, str]], col_max: int = 30, col_spacing: int = -2) -> None: ... def __getattr__(self, attr: str) -> Incomplete: ... # __getattr__ used to ala-derive from click.HelpFormatter: # indent_increment: int diff --git a/stubs/click-log/click_log/options.pyi b/stubs/click-log/click_log/options.pyi index e1310ab8ea44..f5fa67d96eac 100644 --- a/stubs/click-log/click_log/options.pyi +++ b/stubs/click-log/click_log/options.pyi @@ -1,12 +1,11 @@ import logging -import typing as t +from collections.abc import Callable +from typing import Any, TypeVar from typing_extensions import TypeAlias import click -_AnyCallable: TypeAlias = t.Callable[..., t.Any] -_FC = t.TypeVar("_FC", bound=_AnyCallable | click.Command) +_AnyCallable: TypeAlias = Callable[..., Any] +_FC = TypeVar("_FC", bound=_AnyCallable | click.Command) -def simple_verbosity_option( - logger: logging.Logger | str | None = None, *names: str, **kwargs: t.Any -) -> t.Callable[[_FC], _FC]: ... +def simple_verbosity_option(logger: logging.Logger | str | None = None, *names: str, **kwargs: Any) -> Callable[[_FC], _FC]: ... diff --git a/stubs/click-web/click_web/web_click_types.pyi b/stubs/click-web/click_web/web_click_types.pyi index b0e9e378fa5a..d3a0d9bcc116 100644 --- a/stubs/click-web/click_web/web_click_types.pyi +++ b/stubs/click-web/click_web/web_click_types.pyi @@ -1,17 +1,19 @@ import re -from typing import ClassVar +from typing import ClassVar, TypeVar import click +_T = TypeVar("_T") + class EmailParamType(click.ParamType): EMAIL_REGEX: ClassVar[re.Pattern[str]] - def convert(self, value: str, param: click.Parameter | None, ctx: click.Context | None) -> str | None: ... + def convert(self, value: str, param: click.Parameter | None, ctx: click.Context | None) -> str: ... class PasswordParamType(click.ParamType): - def convert(self, value: str, param: click.Parameter | None, ctx: click.Context | None) -> str | None: ... + def convert(self, value: _T, param: click.Parameter | None, ctx: click.Context | None) -> _T: ... class TextAreaParamType(click.ParamType): - def convert(self, value: str, param: click.Parameter | None, ctx: click.Context | None) -> str | None: ... + def convert(self, value: _T, param: click.Parameter | None, ctx: click.Context | None) -> _T: ... EMAIL_TYPE: EmailParamType PASSWORD_TYPE: PasswordParamType diff --git a/stubs/corus/corus/third/WikiExtractor.pyi b/stubs/corus/corus/third/WikiExtractor.pyi index b8ee370c8a26..bda32a5d62a1 100644 --- a/stubs/corus/corus/third/WikiExtractor.pyi +++ b/stubs/corus/corus/third/WikiExtractor.pyi @@ -1,4 +1,3 @@ -import typing from _typeshed import Incomplete from collections.abc import Generator from math import ( @@ -14,6 +13,7 @@ from math import ( tan as tan, trunc as trunc, ) +from typing import TypeVar PY2: Incomplete text_type = str @@ -52,7 +52,7 @@ quote_quote: Incomplete spaces: Incomplete dots: Incomplete -_T = typing.TypeVar("_T") +_T = TypeVar("_T") class Template(list[_T]): @classmethod