From acf76d88d52f6af3e0f2bd7098a331d85fa17c5c Mon Sep 17 00:00:00 2001 From: cmp0xff Date: Tue, 21 Oct 2025 17:29:32 +0200 Subject: [PATCH 1/6] ANN001 in tests --- .pre-commit-config.yaml | 2 +- pyproject.toml | 4 +- tests/extension/decimal/array.py | 90 ++++++++++++++++++++++---------- 3 files changed, 66 insertions(+), 30 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index da68018d0..b44edb1f3 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -3,7 +3,7 @@ ci: autofix_prs: false repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.14.0 + rev: v0.14.1 hooks: - id: ruff-check args: [--exit-non-zero-on-fix] diff --git a/pyproject.toml b/pyproject.toml index f1223bc0b..54216819b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -172,7 +172,7 @@ skip_glob = "env" [tool.ruff] target-version = "py310" -fix = true +fix = false [tool.ruff.lint] @@ -221,7 +221,7 @@ ignore = [ "A001", # https://docs.astral.sh/ruff/rules/builtin-variable-shadowing/ "PYI042", # https://docs.astral.sh/ruff/rules/snake-case-type-alias/ "SLF001", # https://docs.astral.sh/ruff/rules/private-member-access/ - "ANN001", "ANN201", "ANN204", "ANN206", "ANN401", "ARG", "ERA", "RUF", "SIM", "TRY", "PT", "NPY", "N", "DTZ", "PLR", "TC", "PGH", "S311", "C901" + "ANN201", "ANN204", "ANN206", "ANN401", "ARG", "ERA", "RUF", "SIM", "TRY", "PT", "NPY", "N", "DTZ", "PLR", "TC", "PGH", "S311", "C901" ] "tests/test_io.py" = [ # The following rules are ignored permanently for good reasons diff --git a/tests/extension/decimal/array.py b/tests/extension/decimal/array.py index 4a180fc0b..5887d1b4b 100644 --- a/tests/extension/decimal/array.py +++ b/tests/extension/decimal/array.py @@ -1,7 +1,10 @@ from __future__ import annotations from builtins import type as type_t -from collections.abc import Callable +from collections.abc import ( + Callable, + Iterable, +) import decimal import numbers import sys @@ -27,11 +30,18 @@ ExtensionScalarOpsMixin, ) from pandas.core.indexers import check_array_indexer +from pandas.core.series import Series +from typing_extensions import Self from pandas._typing import ( ArrayLike, AstypeArg, + Dtype, + ScalarIndexer, + SequenceIndexer, + SequenceNotStr, TakeIndexer, + np_1darray, ) from pandas.core.dtypes.base import ExtensionDtype @@ -41,8 +51,6 @@ pandas_dtype, ) -from tests import np_1darray - @register_extension_dtype class DecimalDtype(ExtensionDtype): @@ -82,9 +90,9 @@ class DecimalArray(OpsMixin, ExtensionScalarOpsMixin, ExtensionArray): def __init__( self, values: list[decimal.Decimal | float] | np.ndarray, - dtype=None, - copy=False, - context=None, + dtype: DecimalDtype | None = None, + copy: bool = False, + context: decimal.Context | None = None, ) -> None: for i, val in enumerate(values): if is_float(val): @@ -111,25 +119,37 @@ def dtype(self) -> DecimalDtype: return self._dtype @classmethod - def _from_sequence(cls, scalars, dtype=None, copy=False): + def _from_sequence( + cls, + scalars: list[decimal.Decimal | float] | np.ndarray, + dtype: DecimalDtype | None = None, + copy: bool = False, + ) -> Self: return cls(scalars) @classmethod - def _from_sequence_of_strings(cls, strings, dtype=None, copy=False): + def _from_sequence_of_strings( + cls, + strings: SequenceNotStr[str], + dtype: DecimalDtype | None = None, + copy: bool = False, + ) -> Self: return cls._from_sequence([decimal.Decimal(x) for x in strings], dtype, copy) @classmethod - def _from_factorized(cls, values, original): + def _from_factorized( + cls, values: list[decimal.Decimal | float] | np.ndarray, original: Any + ) -> Self: return cls(values) _HANDLED_TYPES = (decimal.Decimal, numbers.Number, np.ndarray) def to_numpy( self, - dtype=None, + dtype: np.typing.DTypeLike | None = None, copy: bool = False, na_value: object = no_default, - decimals=None, + decimals: int | None = None, ) -> np.ndarray: result = np.asarray(self, dtype=dtype) if decimals is not None: @@ -138,7 +158,7 @@ def to_numpy( def __array_ufunc__( self, ufunc: np.ufunc, method: str, *inputs: Any, **kwargs: Any - ): + ) -> arraylike.dispatch_ufunc_with_out: # type: ignore[name-defined] # pyright: ignore[reportAttributeAccessIssue] # if not all( isinstance(t, self._HANDLED_TYPES + (DecimalArray,)) for t in inputs @@ -160,7 +180,14 @@ def __array_ufunc__( if result is not NotImplemented: return result - def reconstruct(x) -> decimal.Decimal | numbers.Number | DecimalArray: + def reconstruct( + x: ( + decimal.Decimal + | numbers.Number + | list[decimal.Decimal | float] + | np.ndarray + ), + ) -> decimal.Decimal | numbers.Number | DecimalArray: if isinstance(x, (decimal.Decimal, numbers.Number)): return x return DecimalArray._from_sequence(x) @@ -169,15 +196,17 @@ def reconstruct(x) -> decimal.Decimal | numbers.Number | DecimalArray: return tuple(reconstruct(x) for x in result) return reconstruct(result) - def __getitem__(self, item): + def __getitem__(self, item: ScalarIndexer | SequenceIndexer) -> Any: if isinstance(item, numbers.Integral): return self._data[item] # array, slice. - item = check_array_indexer(self, item) + item = check_array_indexer( + self, item # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + ) return type(self)(self._data[item]) def take( - self, indexer: TakeIndexer, *, allow_fill: bool = False, fill_value=None + self, indexer: TakeIndexer, *, allow_fill: bool = False, fill_value: Any = None ) -> DecimalArray: from pandas.api.extensions import take @@ -208,21 +237,26 @@ def astype(self, dtype, copy=True): return super().astype(dtype, copy=copy) - def __setitem__(self, key, value) -> None: + def __setitem__(self, key: object, value: decimal._DecimalNew) -> None: if is_list_like(value): if is_scalar(key): raise ValueError("setting an array element with a sequence.") - value = [decimal.Decimal(v) for v in value] + value = [ # type: ignore[assignment] + decimal.Decimal(v) # type: ignore[arg-type] + for v in value # type: ignore[union-attr] # pyright: ignore[reportAssignmentType,reportGeneralTypeIssues] + ] else: value = decimal.Decimal(value) - key = check_array_indexer(self, key) - self._data[key] = value + key = check_array_indexer( # type: ignore[call-overload] + self, key # pyright: ignore[reportArgumentType,reportCallIssue] + ) + self._data[key] = value # type: ignore[call-overload] # pyright: ignore[reportArgumentType,reportCallIssue] def __len__(self) -> int: return len(self._data) - def __contains__(self, item) -> bool | np.bool_: + def __contains__(self, item: Any) -> bool | np.bool_: if not isinstance(item, decimal.Decimal): return False if item.is_nan(): @@ -236,20 +270,20 @@ def nbytes(self) -> int: return n * sys.getsizeof(self[0]) return 0 - def isna(self): + def isna(self) -> np_1darray[np.bool_]: return np.array([x.is_nan() for x in self._data], dtype=bool) @property def _na_value(self) -> decimal.Decimal: return decimal.Decimal("NaN") - def _formatter(self, boxed=False) -> Callable[..., str]: + def _formatter(self, boxed: bool = False) -> Callable[..., str]: if boxed: return "Decimal: {}".format return repr @classmethod - def _concat_same_type(cls, to_concat): + def _concat_same_type(cls, to_concat: Iterable[Self]) -> Self: return cls(np.concatenate([x._data for x in to_concat])) def _reduce(self, name: str, *, skipna: bool = True, **kwargs: Any) -> Any: @@ -271,9 +305,11 @@ def _reduce(self, name: str, *, skipna: bool = True, **kwargs: Any) -> Any: ) from err return op(axis=0) - def _cmp_method(self, other, op) -> np.ndarray[tuple[int], np.dtype[np.bool_]]: + def _cmp_method( + self, other: Any, op: Callable[[Self, ExtensionArray | list[Any]], bool] + ) -> np_1darray[np.bool_]: # For use with OpsMixin - def convert_values(param) -> ExtensionArray | list[Any]: + def convert_values(param: Any) -> ExtensionArray | list[Any]: if isinstance(param, ExtensionArray) or is_list_like(param): ovalues = param else: @@ -292,7 +328,7 @@ def convert_values(param) -> ExtensionArray | list[Any]: np.ndarray[tuple[int], np.dtype[np.bool_]], np.asarray(res, dtype=bool) ) - def value_counts(self, dropna: bool = True): + def value_counts(self, dropna: bool = True) -> Series: from pandas.core.algorithms import value_counts return value_counts(self.to_numpy(), dropna=dropna) From 78874599ed018c3956531762ec24f865818d2c64 Mon Sep 17 00:00:00 2001 From: cmp0xff Date: Tue, 21 Oct 2025 17:35:22 +0200 Subject: [PATCH 2/6] all ANN in tests --- pyproject.toml | 6 ++++-- tests/extension/decimal/array.py | 1 - 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 54216819b..f53e1ab8c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -192,6 +192,7 @@ ignore = [ "*.pyi" = [ # The following rules are ignored permanently for good reasons "A002", # https://docs.astral.sh/ruff/rules/builtin-argument-shadowing/ + "ANN401", # https://docs.astral.sh/ruff/rules/any-type/ "FIX002", # https://docs.astral.sh/ruff/rules/line-contains-todo/ "N", # https://docs.astral.sh/ruff/rules/#pep8-naming-n "TD002", # https://docs.astral.sh/ruff/rules/missing-todo-author/ @@ -200,7 +201,7 @@ ignore = [ "A004", # https://docs.astral.sh/ruff/rules/builtin-import-shadowing/ "PYI001", # https://docs.astral.sh/ruff/rules/unprefixed-type-param/ "PYI042", # https://docs.astral.sh/ruff/rules/snake-case-type-alias/ - "ERA001", "ANN001", "ANN201", "ANN204", "ANN206", "ANN401", "PLR0402", "PLC0105" + "ERA001", "ANN001", "ANN201", "ANN204", "ANN206", "PLR0402", "PLC0105" ] "scripts/*" = [ # The following rules are ignored permanently for good reasons @@ -209,6 +210,7 @@ ignore = [ ] "tests/*" = [ # The following rules are ignored permanently for good reasons + "ANN401", # https://docs.astral.sh/ruff/rules/any-type/ "B905", # https://docs.astral.sh/ruff/rules/zip-without-explicit-strict/ "E731", # https://docs.astral.sh/ruff/rules/lambda-assignment/ "EM", # https://docs.astral.sh/ruff/rules/#flake8-errmsg-em @@ -221,7 +223,7 @@ ignore = [ "A001", # https://docs.astral.sh/ruff/rules/builtin-variable-shadowing/ "PYI042", # https://docs.astral.sh/ruff/rules/snake-case-type-alias/ "SLF001", # https://docs.astral.sh/ruff/rules/private-member-access/ - "ANN201", "ANN204", "ANN206", "ANN401", "ARG", "ERA", "RUF", "SIM", "TRY", "PT", "NPY", "N", "DTZ", "PLR", "TC", "PGH", "S311", "C901" + "ARG", "ERA", "RUF", "SIM", "TRY", "PT", "NPY", "N", "DTZ", "PLR", "TC", "PGH", "S311", "C901" ] "tests/test_io.py" = [ # The following rules are ignored permanently for good reasons diff --git a/tests/extension/decimal/array.py b/tests/extension/decimal/array.py index 5887d1b4b..a36bb64d6 100644 --- a/tests/extension/decimal/array.py +++ b/tests/extension/decimal/array.py @@ -36,7 +36,6 @@ from pandas._typing import ( ArrayLike, AstypeArg, - Dtype, ScalarIndexer, SequenceIndexer, SequenceNotStr, From e00822b486ee6cffa8b33f99160fd1422626fd1d Mon Sep 17 00:00:00 2001 From: cmp0xff Date: Tue, 21 Oct 2025 17:40:36 +0200 Subject: [PATCH 3/6] ignore ARG --- pyproject.toml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index f53e1ab8c..52fdaf470 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -211,6 +211,7 @@ ignore = [ "tests/*" = [ # The following rules are ignored permanently for good reasons "ANN401", # https://docs.astral.sh/ruff/rules/any-type/ + "ARG", # https://docs.astral.sh/ruff/rules/#flake8-unused-arguments-arg "B905", # https://docs.astral.sh/ruff/rules/zip-without-explicit-strict/ "E731", # https://docs.astral.sh/ruff/rules/lambda-assignment/ "EM", # https://docs.astral.sh/ruff/rules/#flake8-errmsg-em @@ -223,7 +224,7 @@ ignore = [ "A001", # https://docs.astral.sh/ruff/rules/builtin-variable-shadowing/ "PYI042", # https://docs.astral.sh/ruff/rules/snake-case-type-alias/ "SLF001", # https://docs.astral.sh/ruff/rules/private-member-access/ - "ARG", "ERA", "RUF", "SIM", "TRY", "PT", "NPY", "N", "DTZ", "PLR", "TC", "PGH", "S311", "C901" + "ERA", "RUF", "SIM", "TRY", "PT", "NPY", "N", "DTZ", "PLR", "TC", "PGH", "S311", "C901" ] "tests/test_io.py" = [ # The following rules are ignored permanently for good reasons From cbe97dd654c29a893dbe883ef13dc89bb08201d8 Mon Sep 17 00:00:00 2001 From: cmp0xff Date: Tue, 21 Oct 2025 17:45:25 +0200 Subject: [PATCH 4/6] ANN206 for pyi --- pandas-stubs/core/arrays/interval.pyi | 14 ++++++-------- pandas-stubs/core/arrays/sparse/accessor.pyi | 5 +++-- pandas-stubs/core/arrays/sparse/array.pyi | 2 +- pandas-stubs/core/indexes/range.pyi | 3 ++- pyproject.toml | 2 +- 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/pandas-stubs/core/arrays/interval.pyi b/pandas-stubs/core/arrays/interval.pyi index 8f6728c5f..52d23ac51 100644 --- a/pandas-stubs/core/arrays/interval.pyi +++ b/pandas-stubs/core/arrays/interval.pyi @@ -5,11 +5,9 @@ from typing import ( ) import numpy as np -from pandas import ( - Index, - Series, -) from pandas.core.arrays.base import ExtensionArray as ExtensionArray +from pandas.core.indexes.base import Index +from pandas.core.series import Series from typing_extensions import Self from pandas._libs.interval import ( @@ -32,7 +30,7 @@ class IntervalArray(IntervalMixin, ExtensionArray): can_hold_na: bool = ... def __new__( cls, data, closed=..., dtype=..., copy: bool = ..., verify_integrity: bool = ... - ): ... + ) -> Self: ... @classmethod def from_breaks( cls, @@ -40,7 +38,7 @@ class IntervalArray(IntervalMixin, ExtensionArray): closed: str = "right", copy: bool = False, dtype=None, - ): ... + ) -> Self: ... @classmethod def from_arrays( cls, @@ -49,7 +47,7 @@ class IntervalArray(IntervalMixin, ExtensionArray): closed: str = "right", copy: bool = False, dtype=..., - ): ... + ) -> Self: ... @classmethod def from_tuples( cls, @@ -57,7 +55,7 @@ class IntervalArray(IntervalMixin, ExtensionArray): closed: str = "right", copy: bool = False, dtype=None, - ): ... + ) -> Self: ... def __array__( self, dtype: NpDtype | None = None, copy: bool | None = None ) -> np_1darray: ... diff --git a/pandas-stubs/core/arrays/sparse/accessor.pyi b/pandas-stubs/core/arrays/sparse/accessor.pyi index 76499cb1a..c99a2558b 100644 --- a/pandas-stubs/core/arrays/sparse/accessor.pyi +++ b/pandas-stubs/core/arrays/sparse/accessor.pyi @@ -1,5 +1,6 @@ -from pandas import Series from pandas.core.accessor import PandasDelegate +from pandas.core.series import Series +from typing_extensions import Self class BaseAccessor: def __init__(self, data=...) -> None: ... @@ -12,7 +13,7 @@ class SparseAccessor(BaseAccessor, PandasDelegate): class SparseFrameAccessor(BaseAccessor, PandasDelegate): @classmethod - def from_spmatrix(cls, data, index=..., columns=...): ... + def from_spmatrix(cls, data, index=..., columns=...) -> Self: ... def to_dense(self): ... def to_coo(self): ... @property diff --git a/pandas-stubs/core/arrays/sparse/array.pyi b/pandas-stubs/core/arrays/sparse/array.pyi index acc7aee24..780d1786e 100644 --- a/pandas-stubs/core/arrays/sparse/array.pyi +++ b/pandas-stubs/core/arrays/sparse/array.pyi @@ -33,7 +33,7 @@ class SparseArray(ExtensionArray, ExtensionOpsMixin): copy: bool = ..., ) -> None: ... @classmethod - def from_spmatrix(cls, data): ... + def from_spmatrix(cls, data) -> Self: ... def __array__( self, dtype: NpDtype | None = None, copy: bool | None = None ) -> np_1darray: ... diff --git a/pandas-stubs/core/indexes/range.pyi b/pandas-stubs/core/indexes/range.pyi index 9b200d026..781123313 100644 --- a/pandas-stubs/core/indexes/range.pyi +++ b/pandas-stubs/core/indexes/range.pyi @@ -13,6 +13,7 @@ from pandas.core.indexes.base import ( Index, _IndexSubclassBase, ) +from typing_extensions import Self from pandas._typing import ( HashableT, @@ -32,7 +33,7 @@ class RangeIndex(_IndexSubclassBase[int, np.int64]): name: Hashable = ..., ): ... @classmethod - def from_range(cls, data, name: Hashable = ..., dtype=...): ... + def from_range(cls, data, name: Hashable = ..., dtype=...) -> Self: ... def __reduce__(self): ... @property def start(self) -> int: ... diff --git a/pyproject.toml b/pyproject.toml index 52fdaf470..11d4644ca 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -201,7 +201,7 @@ ignore = [ "A004", # https://docs.astral.sh/ruff/rules/builtin-import-shadowing/ "PYI001", # https://docs.astral.sh/ruff/rules/unprefixed-type-param/ "PYI042", # https://docs.astral.sh/ruff/rules/snake-case-type-alias/ - "ERA001", "ANN001", "ANN201", "ANN204", "ANN206", "PLR0402", "PLC0105" + "ERA001", "ANN001", "ANN201", "ANN204", "PLR0402", "PLC0105" ] "scripts/*" = [ # The following rules are ignored permanently for good reasons From b685e3f3c8839282ed096a981f6be82d8c769a01 Mon Sep 17 00:00:00 2001 From: cmp0xff Date: Tue, 21 Oct 2025 17:50:15 +0200 Subject: [PATCH 5/6] PLC0105 --- pandas-stubs/_typing.pyi | 6 ++- pandas-stubs/core/frame.pyi | 12 +++--- pandas-stubs/core/indexes/base.pyi | 23 ++++++----- pandas-stubs/core/series.pyi | 62 ++++++++++++++++++------------ pyproject.toml | 4 +- 5 files changed, 65 insertions(+), 42 deletions(-) diff --git a/pandas-stubs/_typing.pyi b/pandas-stubs/_typing.pyi index 3f74a9b5d..f1e2bf606 100644 --- a/pandas-stubs/_typing.pyi +++ b/pandas-stubs/_typing.pyi @@ -911,8 +911,10 @@ SeriesDType: TypeAlias = ( S1 = TypeVar("S1", bound=SeriesDType, default=Any) # Like S1, but without `default=Any`. S2 = TypeVar("S2", bound=SeriesDType) -S2_CT = TypeVar("S2_CT", bound=SeriesDType, contravariant=True) -S2_CT_NDT = TypeVar("S2_CT_NDT", bound=SeriesDTypeNoDateTime, contravariant=True) +S2_contra = TypeVar("S2_contra", bound=SeriesDType, contravariant=True) +S2_NDT_contra = TypeVar( + "S2_NDT_contra", bound=SeriesDTypeNoDateTime, contravariant=True +) S2_NSDT = TypeVar("S2_NSDT", bound=SeriesDTypeNoStrDateTime) S3 = TypeVar("S3", bound=SeriesDType) diff --git a/pandas-stubs/core/frame.pyi b/pandas-stubs/core/frame.pyi index 7e4f5c2ff..23ed27b72 100644 --- a/pandas-stubs/core/frame.pyi +++ b/pandas-stubs/core/frame.pyi @@ -169,7 +169,9 @@ from pandas._typing import ( from pandas.io.formats.style import Styler from pandas.plotting import PlotAccessor -_T_MUTABLE_MAPPING = TypeVar("_T_MUTABLE_MAPPING", bound=MutableMapping, covariant=True) +_T_MUTABLE_MAPPING_co = TypeVar( + "_T_MUTABLE_MAPPING_co", bound=MutableMapping, covariant=True +) class _iLocIndexerFrame(_iLocIndexer, Generic[_T]): @overload @@ -463,9 +465,9 @@ class DataFrame(NDFrame, OpsMixin, _GetItemHack): self, orient: Literal["records"], *, - into: _T_MUTABLE_MAPPING | type[_T_MUTABLE_MAPPING], + into: _T_MUTABLE_MAPPING_co | type[_T_MUTABLE_MAPPING_co], index: Literal[True] = ..., - ) -> list[_T_MUTABLE_MAPPING]: ... + ) -> list[_T_MUTABLE_MAPPING_co]: ... @overload def to_dict( self, @@ -511,9 +513,9 @@ class DataFrame(NDFrame, OpsMixin, _GetItemHack): self, orient: Literal["dict", "list", "series"] = ..., *, - into: _T_MUTABLE_MAPPING | type[_T_MUTABLE_MAPPING], + into: _T_MUTABLE_MAPPING_co | type[_T_MUTABLE_MAPPING_co], index: Literal[True] = ..., - ) -> _T_MUTABLE_MAPPING: ... + ) -> _T_MUTABLE_MAPPING_co: ... @overload def to_dict( self, diff --git a/pandas-stubs/core/indexes/base.pyi b/pandas-stubs/core/indexes/base.pyi index 3ff4db49a..40129638a 100644 --- a/pandas-stubs/core/indexes/base.pyi +++ b/pandas-stubs/core/indexes/base.pyi @@ -63,7 +63,6 @@ from pandas._typing import ( C2, S1, S2, - S2_CT, S2_NSDT, T_COMPLEX, AnyAll, @@ -85,6 +84,7 @@ from pandas._typing import ( MaskType, NaPosition, ReindexMethod, + S2_contra, Scalar, SequenceNotStr, SliceType, @@ -520,8 +520,8 @@ class Index(IndexOpsMixin[S1], ElementOpsMixin[S1]): ) -> Index[S2]: ... @overload def __add__( - self: Index[S2_CT], - other: SupportsRAdd[S2_CT, S2] | Sequence[SupportsRAdd[S2_CT, S2]], + self: Index[S2_contra], + other: SupportsRAdd[S2_contra, S2] | Sequence[SupportsRAdd[S2_contra, S2]], ) -> Index[S2]: ... @overload def __add__( @@ -573,8 +573,8 @@ class Index(IndexOpsMixin[S1], ElementOpsMixin[S1]): ) -> Index[S2]: ... @overload def __radd__( - self: Index[S2_CT], - other: SupportsAdd[S2_CT, S2] | Sequence[SupportsAdd[S2_CT, S2]], + self: Index[S2_contra], + other: SupportsAdd[S2_contra, S2] | Sequence[SupportsAdd[S2_contra, S2]], ) -> Index[S2]: ... @overload def __radd__( @@ -789,8 +789,11 @@ class Index(IndexOpsMixin[S1], ElementOpsMixin[S1]): ) -> Index[S2]: ... @overload def __mul__( - self: Index[S2_CT], - other: SupportsRMul[S2_CT, S2_NSDT] | Sequence[SupportsRMul[S2_CT, S2_NSDT]], + self: Index[S2_contra], + other: ( + SupportsRMul[S2_contra, S2_NSDT] + | Sequence[SupportsRMul[S2_contra, S2_NSDT]] + ), ) -> Index[S2_NSDT]: ... @overload def __mul__( @@ -853,8 +856,10 @@ class Index(IndexOpsMixin[S1], ElementOpsMixin[S1]): ) -> Index[S2]: ... @overload def __rmul__( - self: Index[S2_CT], - other: SupportsMul[S2_CT, S2_NSDT] | Sequence[SupportsMul[S2_CT, S2_NSDT]], + self: Index[S2_contra], + other: ( + SupportsMul[S2_contra, S2_NSDT] | Sequence[SupportsMul[S2_contra, S2_NSDT]] + ), ) -> Index[S2_NSDT]: ... @overload def __rmul__( diff --git a/pandas-stubs/core/series.pyi b/pandas-stubs/core/series.pyi index 8e8321830..30f9722b7 100644 --- a/pandas-stubs/core/series.pyi +++ b/pandas-stubs/core/series.pyi @@ -120,8 +120,6 @@ from pandas._libs.tslibs.nattype import NaTType from pandas._typing import ( S1, S2, - S2_CT, - S2_CT_NDT, S2_NSDT, T_COMPLEX, AggFuncTypeBase, @@ -180,6 +178,8 @@ from pandas._typing import ( ReindexMethod, Renamer, ReplaceValue, + S2_contra, + S2_NDT_contra, Scalar, ScalarT, SequenceNotStr, @@ -1725,14 +1725,16 @@ class Series(IndexOpsMixin[S1], ElementOpsMixin[S1], NDFrame): ) -> Series[Timedelta]: ... @overload def __add__( - self: Supports_ProtoAdd[S2_CT, S2], other: S2_CT | Sequence[S2_CT] + self: Supports_ProtoAdd[S2_contra, S2], other: S2_contra | Sequence[S2_contra] ) -> Series[S2]: ... @overload - def __add__(self: Series[S2_CT], other: SupportsRAdd[S2_CT, S2]) -> Series[S2]: ... + def __add__( + self: Series[S2_contra], other: SupportsRAdd[S2_contra, S2] + ) -> Series[S2]: ... # pandas-dev/pandas#62353 @overload def __add__( - self: Series[S2_CT_NDT], other: Sequence[SupportsRAdd[S2_CT_NDT, S2]] + self: Series[S2_NDT_contra], other: Sequence[SupportsRAdd[S2_NDT_contra, S2]] ) -> Series[S2]: ... @overload def __add__( @@ -1835,16 +1837,16 @@ class Series(IndexOpsMixin[S1], ElementOpsMixin[S1], NDFrame): ) -> Series[Timedelta]: ... @overload def add( - self: Supports_ProtoAdd[S2_CT, S2], - other: S2_CT | Sequence[S2_CT], + self: Supports_ProtoAdd[S2_contra, S2], + other: S2_contra | Sequence[S2_contra], level: Level | None = None, fill_value: float | None = None, axis: int = 0, ) -> Series[S2]: ... @overload def add( - self: Series[S2_CT], - other: SupportsRAdd[S2_CT, S2] | Sequence[SupportsRAdd[S2_CT, S2]], + self: Series[S2_contra], + other: SupportsRAdd[S2_contra, S2] | Sequence[SupportsRAdd[S2_contra, S2]], level: Level | None = None, fill_value: float | None = None, axis: int = 0, @@ -1952,14 +1954,16 @@ class Series(IndexOpsMixin[S1], ElementOpsMixin[S1], NDFrame): # pyright is unhappy without the above 3 overloads @overload def __radd__( - self: Supports_ProtoRAdd[S2_CT, S2], other: S2_CT | Sequence[S2_CT] + self: Supports_ProtoRAdd[S2_contra, S2], other: S2_contra | Sequence[S2_contra] ) -> Series[S2]: ... @overload - def __radd__(self: Series[S2_CT], other: SupportsAdd[S2_CT, S2]) -> Series[S2]: ... + def __radd__( + self: Series[S2_contra], other: SupportsAdd[S2_contra, S2] + ) -> Series[S2]: ... # pandas-dev/pandas#62353 @overload def __radd__( - self: Series[S2_CT_NDT], other: Sequence[SupportsAdd[S2_CT_NDT, S2]] + self: Series[S2_NDT_contra], other: Sequence[SupportsAdd[S2_NDT_contra, S2]] ) -> Series[S2]: ... @overload def __radd__( @@ -2066,16 +2070,16 @@ class Series(IndexOpsMixin[S1], ElementOpsMixin[S1], NDFrame): ) -> Series[Timedelta]: ... @overload def radd( - self: Supports_ProtoRAdd[S2_CT, S2], - other: S2_CT | Sequence[S2_CT], + self: Supports_ProtoRAdd[S2_contra, S2], + other: S2_contra | Sequence[S2_contra], level: Level | None = None, fill_value: float | None = None, axis: int = 0, ) -> Series[S2]: ... @overload def radd( - self: Series[S2_CT], - other: SupportsAdd[S2_CT, S2] | Sequence[SupportsAdd[S2_CT, S2]], + self: Series[S2_contra], + other: SupportsAdd[S2_contra, S2] | Sequence[SupportsAdd[S2_contra, S2]], level: Level | None = None, fill_value: float | None = None, axis: int = 0, @@ -2532,8 +2536,11 @@ class Series(IndexOpsMixin[S1], ElementOpsMixin[S1], NDFrame): ) -> Series[S2]: ... @overload def __mul__( - self: Series[S2_CT], - other: SupportsRMul[S2_CT, S2_NSDT] | Sequence[SupportsRMul[S2_CT, S2_NSDT]], + self: Series[S2_contra], + other: ( + SupportsRMul[S2_contra, S2_NSDT] + | Sequence[SupportsRMul[S2_contra, S2_NSDT]] + ), ) -> Series[S2_NSDT]: ... @overload def __mul__( @@ -2625,8 +2632,11 @@ class Series(IndexOpsMixin[S1], ElementOpsMixin[S1], NDFrame): ) -> Series[S2]: ... @overload def mul( - self: Series[S2_CT], - other: SupportsRMul[S2_CT, S2_NSDT] | Sequence[SupportsRMul[S2_CT, S2_NSDT]], + self: Series[S2_contra], + other: ( + SupportsRMul[S2_contra, S2_NSDT] + | Sequence[SupportsRMul[S2_contra, S2_NSDT]] + ), level: Level | None = None, fill_value: float | None = None, axis: int = 0, @@ -2742,8 +2752,10 @@ class Series(IndexOpsMixin[S1], ElementOpsMixin[S1], NDFrame): ) -> Series[S2]: ... @overload def __rmul__( - self: Series[S2_CT], - other: SupportsMul[S2_CT, S2_NSDT] | Sequence[SupportsMul[S2_CT, S2_NSDT]], + self: Series[S2_contra], + other: ( + SupportsMul[S2_contra, S2_NSDT] | Sequence[SupportsMul[S2_contra, S2_NSDT]] + ), ) -> Series[S2_NSDT]: ... @overload def __rmul__( @@ -2835,8 +2847,10 @@ class Series(IndexOpsMixin[S1], ElementOpsMixin[S1], NDFrame): ) -> Series[S2]: ... @overload def rmul( - self: Series[S2_CT], - other: SupportsMul[S2_CT, S2_NSDT] | Sequence[SupportsMul[S2_CT, S2_NSDT]], + self: Series[S2_contra], + other: ( + SupportsMul[S2_contra, S2_NSDT] | Sequence[SupportsMul[S2_contra, S2_NSDT]] + ), level: Level | None = None, fill_value: float | None = None, axis: int = 0, diff --git a/pyproject.toml b/pyproject.toml index 11d4644ca..6d7859cc5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -172,7 +172,7 @@ skip_glob = "env" [tool.ruff] target-version = "py310" -fix = false +fix = true [tool.ruff.lint] @@ -201,7 +201,7 @@ ignore = [ "A004", # https://docs.astral.sh/ruff/rules/builtin-import-shadowing/ "PYI001", # https://docs.astral.sh/ruff/rules/unprefixed-type-param/ "PYI042", # https://docs.astral.sh/ruff/rules/snake-case-type-alias/ - "ERA001", "ANN001", "ANN201", "ANN204", "PLR0402", "PLC0105" + "ERA001", "ANN001", "ANN201", "ANN204", "PLR0402", ] "scripts/*" = [ # The following rules are ignored permanently for good reasons From d8cb890b3680b1021d7367f5edaf62511cfce895 Mon Sep 17 00:00:00 2001 From: cmp0xff Date: Thu, 23 Oct 2025 15:25:39 +0200 Subject: [PATCH 6/6] fix: mypy and pytest --- tests/extension/decimal/array.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/tests/extension/decimal/array.py b/tests/extension/decimal/array.py index a36bb64d6..c77436d2b 100644 --- a/tests/extension/decimal/array.py +++ b/tests/extension/decimal/array.py @@ -9,6 +9,7 @@ import numbers import sys from typing import ( + TYPE_CHECKING, Any, cast, overload, @@ -40,7 +41,6 @@ SequenceIndexer, SequenceNotStr, TakeIndexer, - np_1darray, ) from pandas.core.dtypes.base import ExtensionDtype @@ -50,6 +50,9 @@ pandas_dtype, ) +if TYPE_CHECKING: + from pandas._typing import np_1darray + @register_extension_dtype class DecimalDtype(ExtensionDtype): @@ -200,7 +203,8 @@ def __getitem__(self, item: ScalarIndexer | SequenceIndexer) -> Any: return self._data[item] # array, slice. item = check_array_indexer( - self, item # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] + self, + item, # type: ignore[arg-type] # pyright: ignore[reportArgumentType,reportCallIssue] ) return type(self)(self._data[item]) @@ -270,7 +274,9 @@ def nbytes(self) -> int: return 0 def isna(self) -> np_1darray[np.bool_]: - return np.array([x.is_nan() for x in self._data], dtype=bool) + if sys.version_info < (3, 11): + return np.array([x.is_nan() for x in self._data], bool) # type: ignore[return-value] # pyright: ignore[reportReturnType] + return np.array([x.is_nan() for x in self._data], bool) @property def _na_value(self) -> decimal.Decimal: