From 9201687979b1c3cf9c4c904a629ac53f31264fea Mon Sep 17 00:00:00 2001 From: Avasam Date: Sat, 1 Mar 2025 21:53:30 -0500 Subject: [PATCH 1/6] Dropped flake8-noqa and remove workarounds to work with Ruff --- .flake8 | 5 +---- .pre-commit-config.yaml | 3 +-- CONTRIBUTING.md | 5 ++--- pyproject.toml | 4 ++-- stdlib/builtins.pyi | 7 +++++-- stdlib/typing_extensions.pyi | 5 ++--- stubs/boltons/boltons/dictutils.pyi | 4 +--- stubs/geopandas/geopandas/io/sql.pyi | 5 +---- stubs/six/six/moves/builtins.pyi | 1 - 9 files changed, 15 insertions(+), 24 deletions(-) diff --git a/.flake8 b/.flake8 index cf6578d7bb11..1b6c02c1b224 100644 --- a/.flake8 +++ b/.flake8 @@ -1,13 +1,10 @@ [flake8] -# NQA: Ruff won't warn about redundant `# noqa: Y` # Y: Flake8 is only used to run flake8-pyi, everything else is in Ruff # F821: Typeshed is a testing ground for flake8-pyi, which monkeypatches F821 -select = NQA, Y, F821 +select = Y, F821 # Ignore rules normally excluded by default extend-ignore = Y090 per-file-ignores = - # We should only need to noqa Y and F821 codes in .pyi files - *.py: NQA # Generated protobuf files: # Y021: Include docstrings # Y023: Alias typing as typing_extensions diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 66fd399115a8..ca5972135220 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -31,12 +31,11 @@ repos: hooks: - id: black - repo: https://github.com/pycqa/flake8 - rev: 7.1.1 + rev: 7.1.2 hooks: - id: flake8 language: python additional_dependencies: - - "flake8-noqa==1.4.0" - "flake8-pyi==24.9.0" types: [file] types_or: [python, pyi] diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b99fc46b7b9f..e4f95ca4ed1c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -28,7 +28,7 @@ it takes a bit longer. For more details, read below. Typeshed runs continuous integration (CI) on all pull requests. This means that if you file a pull request (PR), our full test suite --- including our linter, [Flake8](https://github.com/PyCQA/flake8) -- +-- including our linter, [`flake8-pyi`](https://github.com/pycqa/flake8-pyi) -- is run on your PR. It also means that bots will automatically apply changes to your PR (using [Black](https://github.com/psf/black) and [Ruff](https://github.com/astral-sh/ruff)) to fix any formatting issues. @@ -88,8 +88,7 @@ The code is formatted using [`Black`](https://github.com/psf/black). Various other autofixes and lint rules are also performed by [`Ruff`](https://github.com/astral-sh/ruff) and [`Flake8`](https://github.com/pycqa/flake8), -with plugins [`flake8-pyi`](https://github.com/pycqa/flake8-pyi), -and [`flake8-noqa`](https://github.com/plinss/flake8-noqa). +with plugin [`flake8-pyi`](https://github.com/pycqa/flake8-pyi). The repository is equipped with a [pre-commit.ci](https://pre-commit.ci/) configuration file. This means that you don't *need* to do anything yourself to diff --git a/pyproject.toml b/pyproject.toml index e6eb6cf3656d..3e2001595c3f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -33,9 +33,9 @@ exclude = [ # are invoked via separate runs of ruff in pre-commit: # see our .pre-commit-config.yaml file for details exclude = ["**/test_cases/**/*.py"] -# We still use flake8-pyi and flake8-noqa to check these (see .flake8 config file); +# We still use flake8-pyi to check these (see .flake8 config file); # tell ruff not to flag these as e.g. "unused noqa comments" -external = ["F821", "NQA", "Y"] +external = ["F821", "Y"] select = [ "ARG", # flake8-unused-arguments "B", # flake8-bugbear diff --git a/stdlib/builtins.pyi b/stdlib/builtins.pyi index 25144609d518..0da1776c4b79 100644 --- a/stdlib/builtins.pyi +++ b/stdlib/builtins.pyi @@ -1,4 +1,3 @@ -# ruff: noqa: PYI036 # This is the module declaring BaseException import _ast import _sitebuiltins import _typeshed @@ -870,7 +869,11 @@ class memoryview(Sequence[_I]): def __new__(cls, obj: ReadableBuffer) -> Self: ... def __enter__(self) -> Self: ... def __exit__( - self, exc_type: type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None, / + self, + exc_type: type[BaseException] | None, # noqa: PYI036 # This is the module declaring BaseException + exc_val: BaseException | None, + exc_tb: TracebackType | None, + /, ) -> None: ... @overload def cast(self, format: Literal["c", "@c"], shape: list[int] | tuple[int, ...] = ...) -> memoryview[bytes]: ... diff --git a/stdlib/typing_extensions.pyi b/stdlib/typing_extensions.pyi index 33af1a388aa5..bb256f4b70a2 100644 --- a/stdlib/typing_extensions.pyi +++ b/stdlib/typing_extensions.pyi @@ -1,5 +1,3 @@ -# Since this module defines "Self" it is not recognized by Ruff as typing_extensions.Self -# ruff: noqa: PYI034 import abc import sys import typing @@ -251,7 +249,8 @@ class _TypedDict(Mapping[str, object], metaclass=abc.ABCMeta): @overload def __ror__(self, value: dict[str, Any], /) -> dict[str, object]: ... # supposedly incompatible definitions of `__ior__` and `__or__`: - def __ior__(self, value: Self, /) -> Self: ... # type: ignore[misc] + # Since this module defines "Self" it is not recognized by Ruff as typing_extensions.Self + def __ior__(self, value: Self, /) -> Self: ... # type: ignore[misc] # ruff: PYI034 OrderedDict = _Alias() diff --git a/stubs/boltons/boltons/dictutils.pyi b/stubs/boltons/boltons/dictutils.pyi index 26c99bb70eb9..69cdc6270cc8 100644 --- a/stubs/boltons/boltons/dictutils.pyi +++ b/stubs/boltons/boltons/dictutils.pyi @@ -91,9 +91,7 @@ class FrozenDict(dict[_KT, _VT]): @classmethod def fromkeys(cls, keys: Iterable[_KT], value: _VT | None = None) -> Self: ... # type: ignore[override] def updated(self, *a, **kw) -> Self: ... - # Can't noqa because of https://github.com/plinss/flake8-noqa/pull/30 - # Signature conflicts with superclass, so let's just omit it - # def __ior__(self, *a, **kw) -> NoReturn: ... + def __ior__(self, *a, **kw) -> NoReturn: ... # type: ignore[misc] # noqa: PYI034 # Signature conflicts with superclass def __setitem__(self, *a, **kw) -> NoReturn: ... def __delitem__(self, *a, **kw) -> NoReturn: ... def update(self, *a, **kw) -> NoReturn: ... diff --git a/stubs/geopandas/geopandas/io/sql.pyi b/stubs/geopandas/geopandas/io/sql.pyi index c8f785cfc6a7..41076f87dc6d 100644 --- a/stubs/geopandas/geopandas/io/sql.pyi +++ b/stubs/geopandas/geopandas/io/sql.pyi @@ -10,9 +10,6 @@ from pandas._typing import Scalar from ..base import _ConvertibleToCRS from ..geodataframe import GeoDataFrame -# inline ruff noqa at _SqlalchemyConnectionLike.__enter__ confuses flake8 -# ruff: noqa: PYI034 - # Start SQLAlchemy hack # --------------------- # The code actually explicitly checks for SQLAlchemy's `Connection` and `Engine` with @@ -39,7 +36,7 @@ class _SqlalchemyConnectionLike(_SqlAlchemyEventTarget, Protocol): def closed(self) -> bool: ... @property def invalidated(self) -> bool: ... - def __enter__(self) -> _SqlalchemyConnectionLike: ... # noqa: Y034 + def __enter__(self) -> _SqlalchemyConnectionLike: ... # noqa: Y034, PYI034 def __exit__(self, type_, value, traceback, /) -> None: ... @property def info(self) -> dict[Any, Any]: ... diff --git a/stubs/six/six/moves/builtins.pyi b/stubs/six/six/moves/builtins.pyi index 1f3812602c5e..eee6b75c0554 100644 --- a/stubs/six/six/moves/builtins.pyi +++ b/stubs/six/six/moves/builtins.pyi @@ -1,4 +1,3 @@ -# flake8: noqa: NQA102 # https://github.com/plinss/flake8-noqa/issues/22 # six explicitly re-exports builtins. Normally this is something we'd want to avoid. # But this is specifically a compatibility package. from builtins import * # noqa: UP029 From a5b6cf4c922e8074da60667d5760f9988b82ac61 Mon Sep 17 00:00:00 2001 From: Avasam Date: Sat, 1 Mar 2025 22:04:21 -0500 Subject: [PATCH 2/6] typo --- stdlib/typing_extensions.pyi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/typing_extensions.pyi b/stdlib/typing_extensions.pyi index bb256f4b70a2..1fd50f7a293f 100644 --- a/stdlib/typing_extensions.pyi +++ b/stdlib/typing_extensions.pyi @@ -250,7 +250,7 @@ class _TypedDict(Mapping[str, object], metaclass=abc.ABCMeta): def __ror__(self, value: dict[str, Any], /) -> dict[str, object]: ... # supposedly incompatible definitions of `__ior__` and `__or__`: # Since this module defines "Self" it is not recognized by Ruff as typing_extensions.Self - def __ior__(self, value: Self, /) -> Self: ... # type: ignore[misc] # ruff: PYI034 + def __ior__(self, value: Self, /) -> Self: ... # type: ignore[misc] # noqa: PYI034 OrderedDict = _Alias() From cab00902382d9deac1fe2ef18fa0cc0a9aaf2bdc Mon Sep 17 00:00:00 2001 From: Avasam Date: Sat, 1 Mar 2025 22:12:27 -0500 Subject: [PATCH 3/6] Add missing noqa: Y034 --- stubs/boltons/boltons/dictutils.pyi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stubs/boltons/boltons/dictutils.pyi b/stubs/boltons/boltons/dictutils.pyi index 69cdc6270cc8..9b6261af8d12 100644 --- a/stubs/boltons/boltons/dictutils.pyi +++ b/stubs/boltons/boltons/dictutils.pyi @@ -91,7 +91,7 @@ class FrozenDict(dict[_KT, _VT]): @classmethod def fromkeys(cls, keys: Iterable[_KT], value: _VT | None = None) -> Self: ... # type: ignore[override] def updated(self, *a, **kw) -> Self: ... - def __ior__(self, *a, **kw) -> NoReturn: ... # type: ignore[misc] # noqa: PYI034 # Signature conflicts with superclass + def __ior__(self, *a, **kw) -> NoReturn: ... # type: ignore[misc] # noqa: Y034, PYI034 # Signature conflicts with superclass def __setitem__(self, *a, **kw) -> NoReturn: ... def __delitem__(self, *a, **kw) -> NoReturn: ... def update(self, *a, **kw) -> NoReturn: ... From 5db6ecbb0d0d0658e8e730e6a89e1d322ee5928d Mon Sep 17 00:00:00 2001 From: Avasam Date: Sat, 1 Mar 2025 22:27:53 -0500 Subject: [PATCH 4/6] Respect our own rule inclusion reasoning for PYI034 --- pyproject.toml | 1 - stdlib/typing_extensions.pyi | 2 +- stubs/boltons/boltons/dictutils.pyi | 2 +- stubs/geopandas/geopandas/io/sql.pyi | 2 +- 4 files changed, 3 insertions(+), 4 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 3e2001595c3f..6ca60929a7b6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -81,7 +81,6 @@ select = [ # "PYI026", Waiting for this mypy bug to be fixed: https://github.com/python/mypy/issues/16581 "PYI030", # Multiple literal members in a union. Use a single literal, e.g. `Literal[{}]` "PYI032", # Prefer `object` to `Any` for the second parameter to `{method_name}` - "PYI034", # `__new__` methods usually return self at runtime "PYI036", # Star-args in `{method_name}` should be annotated with `object` "PYI044", # `from __future__ import annotations` has no effect in stub files, since type checkers automatically treat stubs as having those semantics "PYI055", # Multiple `type[T]` usages in a union. Combine them into one, e.g., `type[{union_str}]`. diff --git a/stdlib/typing_extensions.pyi b/stdlib/typing_extensions.pyi index 1fd50f7a293f..fd98722b10a8 100644 --- a/stdlib/typing_extensions.pyi +++ b/stdlib/typing_extensions.pyi @@ -250,7 +250,7 @@ class _TypedDict(Mapping[str, object], metaclass=abc.ABCMeta): def __ror__(self, value: dict[str, Any], /) -> dict[str, object]: ... # supposedly incompatible definitions of `__ior__` and `__or__`: # Since this module defines "Self" it is not recognized by Ruff as typing_extensions.Self - def __ior__(self, value: Self, /) -> Self: ... # type: ignore[misc] # noqa: PYI034 + def __ior__(self, value: Self, /) -> Self: ... # type: ignore[misc] OrderedDict = _Alias() diff --git a/stubs/boltons/boltons/dictutils.pyi b/stubs/boltons/boltons/dictutils.pyi index 9b6261af8d12..6a6b851a9ffb 100644 --- a/stubs/boltons/boltons/dictutils.pyi +++ b/stubs/boltons/boltons/dictutils.pyi @@ -91,7 +91,7 @@ class FrozenDict(dict[_KT, _VT]): @classmethod def fromkeys(cls, keys: Iterable[_KT], value: _VT | None = None) -> Self: ... # type: ignore[override] def updated(self, *a, **kw) -> Self: ... - def __ior__(self, *a, **kw) -> NoReturn: ... # type: ignore[misc] # noqa: Y034, PYI034 # Signature conflicts with superclass + def __ior__(self, *a, **kw) -> NoReturn: ... # type: ignore[misc] # noqa: Y034 # Signature conflicts with superclass def __setitem__(self, *a, **kw) -> NoReturn: ... def __delitem__(self, *a, **kw) -> NoReturn: ... def update(self, *a, **kw) -> NoReturn: ... diff --git a/stubs/geopandas/geopandas/io/sql.pyi b/stubs/geopandas/geopandas/io/sql.pyi index 41076f87dc6d..743439f873b8 100644 --- a/stubs/geopandas/geopandas/io/sql.pyi +++ b/stubs/geopandas/geopandas/io/sql.pyi @@ -36,7 +36,7 @@ class _SqlalchemyConnectionLike(_SqlAlchemyEventTarget, Protocol): def closed(self) -> bool: ... @property def invalidated(self) -> bool: ... - def __enter__(self) -> _SqlalchemyConnectionLike: ... # noqa: Y034, PYI034 + def __enter__(self) -> _SqlalchemyConnectionLike: ... # noqa: Y034 def __exit__(self, type_, value, traceback, /) -> None: ... @property def info(self) -> dict[Any, Any]: ... From 870d1060368e20ef17ee8a56653810d8e15e84d1 Mon Sep 17 00:00:00 2001 From: Avasam Date: Sat, 1 Mar 2025 22:32:08 -0500 Subject: [PATCH 5/6] Remove plugin specific config --- .flake8 | 1 - 1 file changed, 1 deletion(-) diff --git a/.flake8 b/.flake8 index 1b6c02c1b224..3b99b881864f 100644 --- a/.flake8 +++ b/.flake8 @@ -13,4 +13,3 @@ per-file-ignores = stubs/*_pb2.pyi: Y021, Y023, Y026, Y053 exclude = .venv*,.git -noqa_require_code = true From 9fb15dc568fcc17f01ffa56b3a800ad221a33e64 Mon Sep 17 00:00:00 2001 From: Avasam Date: Sat, 1 Mar 2025 22:33:51 -0500 Subject: [PATCH 6/6] Forgot another comment --- pyproject.toml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 6ca60929a7b6..0fea45ba4ffb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -66,8 +66,7 @@ select = [ "FURB177", # Prefer `Path.cwd()` over `Path().resolve()` for current-directory lookups "FURB187", # Use of assignment of `reversed` on list `{name}` # PYI: only enable rules that have autofixes and that we always want to fix (even manually), - # avoids duplicate # noqa with flake8-pyi and flake8-noqa flagging `PYI` codes - # See https://github.com/plinss/flake8-noqa/issues/22 + # avoids duplicate # noqa with flake8-pyi "PYI009", # Empty body should contain `...`, not pass "PYI010", # Function body must contain only `...` "PYI012", # Class bodies must not contain `pass`