From a8e77640ff0992f3972b37f92b0e3afb83efc73a Mon Sep 17 00:00:00 2001 From: cmp0xff Date: Thu, 16 Oct 2025 20:29:42 +0200 Subject: [PATCH 1/8] PTH --- .pre-commit-config.yaml | 2 +- pyproject.toml | 3 +-- tests/test_frame.py | 2 +- tests/test_io.py | 23 +++++++++++------------ tests/test_styler.py | 5 ++--- tests/test_testing.py | 4 ++-- 6 files changed, 18 insertions(+), 21 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 1f45d60ed..da68018d0 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.13.3 + rev: v0.14.0 hooks: - id: ruff-check args: [--exit-non-zero-on-fix] diff --git a/pyproject.toml b/pyproject.toml index 78eaf0552..c967f795d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -220,10 +220,9 @@ 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", "PTH", "S311", "C901" + "ANN001", "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 "S301", # https://docs.astral.sh/ruff/rules/suspicious-pickle-usage/ ] diff --git a/tests/test_frame.py b/tests/test_frame.py index 168592665..5ebed2bc2 100644 --- a/tests/test_frame.py +++ b/tests/test_frame.py @@ -1992,7 +1992,7 @@ def test_types_to_feather() -> None: # See https://pandas.pydata.org/docs/whatsnew/v1.0.0.html # Docstring and type were updated in 1.2.0. # https://github.com/pandas-dev/pandas/pull/35408 - with open(path, mode="wb") as file: + with Path(path).open("wb") as file: df.to_feather(file) diff --git a/tests/test_io.py b/tests/test_io.py index 513055531..ff5bb5850 100644 --- a/tests/test_io.py +++ b/tests/test_io.py @@ -3,7 +3,6 @@ import csv from functools import partial import io -import os.path import pathlib from pathlib import Path import sqlite3 @@ -65,7 +64,7 @@ from pandas.io.stata import StataReader DF = DataFrame({"a": [1, 2, 3], "b": [0.0, 0.0, 0.0]}) -CWD = os.path.split(os.path.abspath(__file__))[0] +CWD = Path(__file__).parent.resolve() @pytest.mark.skipif(WINDOWS, reason="ORC not available on windows") @@ -86,10 +85,10 @@ def test_orc_path() -> None: @pytest.mark.skipif(WINDOWS, reason="ORC not available on windows") def test_orc_buffer() -> None: with ensure_clean() as path: - with open(path, "wb") as file_w: + with Path(path).open("wb") as file_w: check(assert_type(DF.to_orc(file_w), None), type(None)) - with open(path, "rb") as file_r: + with Path(path).open("rb") as file_r: check(assert_type(read_orc(file_r), DataFrame), DataFrame) @@ -109,7 +108,7 @@ def test_xml() -> None: with ensure_clean() as path: check(assert_type(DF.to_xml(path), None), type(None)) check(assert_type(read_xml(path), DataFrame), DataFrame) - with open(path, "rb") as f: + with Path(path).open("rb") as f: check(assert_type(read_xml(f), DataFrame), DataFrame) @@ -128,7 +127,7 @@ def test_pickle() -> None: def test_pickle_file_handle() -> None: with ensure_clean() as path: check(assert_type(DF.to_pickle(path), None), type(None)) - with open(path, "rb") as file: + with Path(path).open("rb") as file: check(assert_type(read_pickle(file), Any), DataFrame) @@ -562,9 +561,9 @@ def test_read_csv() -> None: with ensure_clean() as path: check(assert_type(DF.to_csv(path), None), type(None)) check(assert_type(read_csv(path), DataFrame), DataFrame) - with open(path) as csv_file: + with Path(path).open() as csv_file: check(assert_type(read_csv(csv_file), DataFrame), DataFrame) - with open(path) as csv_file: + with Path(path).open() as csv_file: sio = io.StringIO(csv_file.read()) check(assert_type(read_csv(sio), DataFrame), DataFrame) check(assert_type(read_csv(path, iterator=False), DataFrame), DataFrame) @@ -917,15 +916,15 @@ def test_btest_read_fwf() -> None: check(assert_type(read_fwf(path), DataFrame), DataFrame) check(assert_type(read_fwf(pathlib.Path(path)), DataFrame), DataFrame) - with open(path) as fwf_file: + with Path(path).open() as fwf_file: check( assert_type(read_fwf(fwf_file), DataFrame), DataFrame, ) - with open(path) as fwf_file: + with Path(path).open() as fwf_file: sio = io.StringIO(fwf_file.read()) check(assert_type(read_fwf(sio), DataFrame), DataFrame) - with open(path, "rb") as fwf_file: + with Path(path).open("rb") as fwf_file: bio = io.BytesIO(fwf_file.read()) check(assert_type(read_fwf(bio), DataFrame), DataFrame) with read_fwf(path, iterator=True) as fwf_iterator: @@ -1228,7 +1227,7 @@ def test_to_string() -> None: with ensure_clean() as path: check(assert_type(DF.to_string(path), None), type(None)) check(assert_type(DF.to_string(pathlib.Path(path)), None), type(None)) - with open(path, "w") as df_string: + with Path(path).open("w") as df_string: check(assert_type(DF.to_string(df_string), None), type(None)) sio = io.StringIO() check(assert_type(DF.to_string(sio), None), type(None)) diff --git a/tests/test_styler.py b/tests/test_styler.py index 1de209a43..16f839020 100644 --- a/tests/test_styler.py +++ b/tests/test_styler.py @@ -1,7 +1,6 @@ from __future__ import annotations -import os -import pathlib +from pathlib import Path from typing import TYPE_CHECKING from jinja2.environment import ( @@ -31,7 +30,7 @@ DF = DataFrame({"a": [1, 2, 3], "b": [3.14, 2.72, 1.61]}) -PWD = pathlib.Path(os.path.split(os.path.abspath(__file__))[0]) +PWD = Path(__file__).parent.resolve() if TYPE_CHECKING: from pandas.io.formats.style_render import StyleExportDict diff --git a/tests/test_testing.py b/tests/test_testing.py index afb127ae5..6170d0aa5 100644 --- a/tests/test_testing.py +++ b/tests/test_testing.py @@ -1,6 +1,6 @@ from __future__ import annotations -import os.path +from pathlib import Path import pandas as pd from pandas.testing import ( @@ -62,4 +62,4 @@ def test_ensure_clean() -> None: with ensure_clean() as path: check(assert_type(path, str), str) pd.DataFrame({"x": [1, 2, 3]}).to_csv(path) - assert not os.path.exists(path) + assert not Path(path).exists() From 5f317fadbee85646234179b169c43819da91f366 Mon Sep 17 00:00:00 2001 From: cmp0xff Date: Thu, 16 Oct 2025 23:11:12 +0200 Subject: [PATCH 2/8] TD003 --- pandas-stubs/_libs/tslibs/timedeltas.pyi | 2 +- pandas-stubs/_libs/tslibs/timestamps.pyi | 6 +++--- pandas-stubs/io/orc.pyi | 2 +- pyproject.toml | 1 - 4 files changed, 5 insertions(+), 6 deletions(-) diff --git a/pandas-stubs/_libs/tslibs/timedeltas.pyi b/pandas-stubs/_libs/tslibs/timedeltas.pyi index 4b98f70aa..886cd06f6 100644 --- a/pandas-stubs/_libs/tslibs/timedeltas.pyi +++ b/pandas-stubs/_libs/tslibs/timedeltas.pyi @@ -131,7 +131,7 @@ class Timedelta(timedelta): def to_timedelta64(self) -> np.timedelta64: ... @property def asm8(self) -> np.timedelta64: ... - # TODO: round/floor/ceil could return NaT? + # TODO: pandas-dev/pandas-stubs#1432 round/floor/ceil could return NaT? def round(self, freq: Frequency) -> Self: ... def floor(self, freq: Frequency) -> Self: ... def ceil(self, freq: Frequency) -> Self: ... diff --git a/pandas-stubs/_libs/tslibs/timestamps.pyi b/pandas-stubs/_libs/tslibs/timestamps.pyi index 09599b36e..49c7463e3 100644 --- a/pandas-stubs/_libs/tslibs/timestamps.pyi +++ b/pandas-stubs/_libs/tslibs/timestamps.pyi @@ -231,7 +231,7 @@ class Timestamp(datetime, SupportsIndex): def __radd__( self, other: np_ndarray[ShapeT, np.timedelta64] ) -> np_ndarray[ShapeT, np.datetime64]: ... - # TODO: test dt64 + # TODO: pandas-dev/pandas-stubs#1432 test dt64 @overload # type: ignore[override] def __sub__(self, other: datetime | np.datetime64) -> Timedelta: ... @overload @@ -287,7 +287,7 @@ class Timestamp(datetime, SupportsIndex): @property def asm8(self) -> np.datetime64: ... def tz_convert(self, tz: TimeZones) -> Self: ... - # TODO: could return NaT? + # TODO: pandas-dev/pandas-stubs#1432 could return NaT? def tz_localize( self, tz: TimeZones, @@ -295,7 +295,7 @@ class Timestamp(datetime, SupportsIndex): nonexistent: TimestampNonexistent = "raise", ) -> Self: ... def normalize(self) -> Self: ... - # TODO: round/floor/ceil could return NaT? + # TODO: pandas-dev/pandas-stubs#1432 round/floor/ceil could return NaT? def round( self, freq: str, diff --git a/pandas-stubs/io/orc.pyi b/pandas-stubs/io/orc.pyi index 489ef433e..3bcda0499 100644 --- a/pandas-stubs/io/orc.pyi +++ b/pandas-stubs/io/orc.pyi @@ -14,7 +14,7 @@ def read_orc( path: FilePath | ReadBuffer[bytes], columns: list[HashableT] | None = None, dtype_backend: DtypeBackend | _NoDefaultDoNotUse = "numpy_nullable", - # TODO: type with the correct pyarrow types + # TODO: pandas-dev/pandas-stubs#1432 type with the correct pyarrow types # filesystem: pyarrow.fs.FileSystem | fsspec.spec.AbstractFileSystem filesystem: Any | None = None, **kwargs: Any, diff --git a/pyproject.toml b/pyproject.toml index c967f795d..6fb59dfce 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -199,7 +199,6 @@ 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/ - "TD003", # https://docs.astral.sh/ruff/rules/missing-todo-link/ "ERA001", "ANN001", "ANN201", "ANN204", "ANN206", "ANN401", "PLR0402", "PLC0105" ] "scripts/*" = [ From 25d4a71138f1d34456ed1b0b041499f0c06c8490 Mon Sep 17 00:00:00 2001 From: cmp0xff Date: Sat, 18 Oct 2025 11:45:29 +0200 Subject: [PATCH 3/8] mypy happiness --- pandas-stubs/_libs/tslibs/period.pyi | 18 ++++---- pandas-stubs/_libs/tslibs/timedeltas.pyi | 53 ++++++++++-------------- pandas-stubs/_libs/tslibs/timestamps.pyi | 12 +++--- 3 files changed, 36 insertions(+), 47 deletions(-) diff --git a/pandas-stubs/_libs/tslibs/period.pyi b/pandas-stubs/_libs/tslibs/period.pyi index 38df197eb..759694c39 100644 --- a/pandas-stubs/_libs/tslibs/period.pyi +++ b/pandas-stubs/_libs/tslibs/period.pyi @@ -6,19 +6,15 @@ from typing import ( ) import numpy as np -from pandas import ( - Index, - PeriodIndex, - Series, - Timedelta, - TimedeltaIndex, -) +from pandas.core.indexes.base import Index +from pandas.core.indexes.period import PeriodIndex +from pandas.core.indexes.timedeltas import TimedeltaIndex +from pandas.core.series import Series from typing_extensions import Self from pandas._libs.tslibs import NaTType -from pandas._libs.tslibs.offsets import ( - BaseOffset, -) +from pandas._libs.tslibs.offsets import BaseOffset +from pandas._libs.tslibs.timedeltas import Timedelta from pandas._libs.tslibs.timestamps import Timestamp from pandas._typing import ( PeriodFrequency, @@ -99,7 +95,7 @@ class Period(PeriodMixin): # Ignored due to indecipherable error from mypy: # Forward operator "__add__" is not callable [misc] @overload - def __radd__(self, other: _PeriodAddSub) -> Self: ... # type: ignore[misc] + def __radd__(self, other: _PeriodAddSub) -> Self: ... @overload def __radd__(self, other: NaTType) -> NaTType: ... # Real signature is -> PeriodIndex, but conflicts with Index.__add__ diff --git a/pandas-stubs/_libs/tslibs/timedeltas.pyi b/pandas-stubs/_libs/tslibs/timedeltas.pyi index 886cd06f6..3cea147f9 100644 --- a/pandas-stubs/_libs/tslibs/timedeltas.pyi +++ b/pandas-stubs/_libs/tslibs/timedeltas.pyi @@ -13,19 +13,14 @@ from typing import ( ) import numpy as np -import pandas as pd -from pandas import ( - DatetimeIndex, - Index, - PeriodIndex, - Series, - TimedeltaIndex, -) +from pandas.core.indexes.base import Index +from pandas.core.indexes.datetimes import DatetimeIndex +from pandas.core.indexes.period import PeriodIndex +from pandas.core.indexes.timedeltas import TimedeltaIndex +from pandas.core.series import Series from typing_extensions import Self -from pandas._libs.tslibs import ( - NaTType, -) +from pandas._libs.tslibs import NaTType from pandas._libs.tslibs.period import Period from pandas._libs.tslibs.timestamps import Timestamp from pandas._typing import ( @@ -174,7 +169,7 @@ class Timedelta(timedelta): ) -> np_ndarray[ShapeT, np.datetime64]: ... # Override due to more types supported than timedelta @overload # type: ignore[override] - def __sub__(self, other: timedelta | Timedelta | np.timedelta64) -> Self: ... + def __sub__(self, other: timedelta | np.timedelta64 | Self) -> Self: ... @overload def __sub__(self, other: NaTType) -> NaTType: ... @overload @@ -182,9 +177,9 @@ class Timedelta(timedelta): self, other: np_ndarray[ShapeT, np.timedelta64] ) -> np_ndarray[ShapeT, np.timedelta64]: ... @overload - def __sub__(self, other: pd.TimedeltaIndex) -> TimedeltaIndex: ... + def __sub__(self, other: TimedeltaIndex) -> TimedeltaIndex: ... @overload - def __rsub__(self, other: timedelta | Timedelta | np.timedelta64) -> Self: ... + def __rsub__(self, other: timedelta | np.timedelta64 | Self) -> Self: ... @overload def __rsub__(self, other: datetime | Timestamp | np.datetime64) -> Timestamp: ... # type: ignore[misc] @overload @@ -204,7 +199,7 @@ class Timedelta(timedelta): self, other: np_ndarray[ShapeT, np.timedelta64] ) -> np_ndarray[ShapeT, np.timedelta64]: ... @overload - def __rsub__(self, other: pd.TimedeltaIndex) -> pd.TimedeltaIndex: ... + def __rsub__(self, other: TimedeltaIndex) -> TimedeltaIndex: ... def __neg__(self) -> Self: ... def __pos__(self) -> Self: ... def __abs__(self) -> Self: ... @@ -224,7 +219,7 @@ class Timedelta(timedelta): # Override due to more types supported than timedelta # error: Signature of "__floordiv__" incompatible with supertype "timedelta" @overload # type: ignore[override] - def __floordiv__(self, other: timedelta | Timedelta | np.timedelta64) -> int: ... + def __floordiv__(self, other: timedelta | np.timedelta64 | Self) -> int: ... @overload def __floordiv__(self, other: float) -> Self: ... @overload @@ -273,9 +268,9 @@ class Timedelta(timedelta): def __rtruediv__(self, other: timedelta | Timedelta | NaTType) -> float: ... # Override due to more types supported than timedelta @overload - def __eq__(self, other: timedelta | Timedelta | np.timedelta64) -> bool: ... # type: ignore[overload-overlap] # pyright: ignore[reportOverlappingOverload] + def __eq__(self, other: timedelta | np.timedelta64 | Self) -> bool: ... # type: ignore[overload-overlap] # pyright: ignore[reportOverlappingOverload] @overload - def __eq__(self, other: Series[pd.Timedelta]) -> Series[bool]: ... # type: ignore[overload-overlap] + def __eq__(self, other: Series[Timedelta]) -> Series[bool]: ... # type: ignore[overload-overlap] @overload def __eq__(self, other: Index) -> np_1darray[np.bool]: ... # type: ignore[overload-overlap] @overload @@ -286,9 +281,9 @@ class Timedelta(timedelta): def __eq__(self, other: object) -> Literal[False]: ... # Override due to more types supported than timedelta @overload - def __ne__(self, other: timedelta | Timedelta | np.timedelta64) -> bool: ... # type: ignore[overload-overlap] # pyright: ignore[reportOverlappingOverload] + def __ne__(self, other: timedelta | np.timedelta64 | Self) -> bool: ... # type: ignore[overload-overlap] # pyright: ignore[reportOverlappingOverload] @overload - def __ne__(self, other: Series[pd.Timedelta]) -> Series[bool]: ... # type: ignore[overload-overlap] + def __ne__(self, other: Series[Timedelta]) -> Series[bool]: ... # type: ignore[overload-overlap] @overload def __ne__(self, other: Index) -> np_1darray[np.bool]: ... # type: ignore[overload-overlap] @overload @@ -315,11 +310,9 @@ class Timedelta(timedelta): self, other: Series[int] | Series[float] | Series[Timedelta] ) -> Series[Timedelta]: ... def __divmod__(self, other: timedelta) -> tuple[int, Timedelta]: ... - # Mypy complains Forward operator "" is not callable, so ignore misc - # for le, lt ge and gt # Override due to more types supported than timedelta @overload # type: ignore[override] - def __le__(self, other: timedelta | Timedelta | np.timedelta64) -> bool: ... # type: ignore[misc] + def __le__(self, other: timedelta | np.timedelta64 | Self) -> bool: ... @overload def __le__(self, other: TimedeltaIndex) -> np_1darray[np.bool]: ... @overload @@ -327,10 +320,10 @@ class Timedelta(timedelta): self, other: np_ndarray[ShapeT, np.timedelta64] ) -> np_ndarray[ShapeT, np.bool_]: ... @overload - def __le__(self, other: Series[pd.Timedelta]) -> Series[bool]: ... + def __le__(self, other: Series[Timedelta]) -> Series[bool]: ... # Override due to more types supported than timedelta @overload # type: ignore[override] - def __lt__(self, other: timedelta | Timedelta | np.timedelta64) -> bool: ... # type: ignore[misc] + def __lt__(self, other: timedelta | np.timedelta64 | Self) -> bool: ... @overload def __lt__(self, other: TimedeltaIndex) -> np_1darray[np.bool]: ... @overload @@ -338,10 +331,10 @@ class Timedelta(timedelta): self, other: np_ndarray[ShapeT, np.timedelta64] ) -> np_ndarray[ShapeT, np.bool_]: ... @overload - def __lt__(self, other: Series[pd.Timedelta]) -> Series[bool]: ... + def __lt__(self, other: Series[Timedelta]) -> Series[bool]: ... # Override due to more types supported than timedelta @overload # type: ignore[override] - def __ge__(self, other: timedelta | Timedelta | np.timedelta64) -> bool: ... # type: ignore[misc] + def __ge__(self, other: timedelta | np.timedelta64 | Self) -> bool: ... @overload def __ge__(self, other: TimedeltaIndex) -> np_1darray[np.bool]: ... @overload @@ -349,10 +342,10 @@ class Timedelta(timedelta): self, other: np_ndarray[ShapeT, np.timedelta64] ) -> np_ndarray[ShapeT, np.bool_]: ... @overload - def __ge__(self, other: Series[pd.Timedelta]) -> Series[bool]: ... + def __ge__(self, other: Series[Timedelta]) -> Series[bool]: ... # Override due to more types supported than timedelta @overload # type: ignore[override] - def __gt__(self, other: timedelta | Timedelta | np.timedelta64) -> bool: ... # type: ignore[misc] + def __gt__(self, other: timedelta | np.timedelta64 | Self) -> bool: ... @overload def __gt__(self, other: TimedeltaIndex) -> np_1darray[np.bool]: ... @overload @@ -360,7 +353,7 @@ class Timedelta(timedelta): self, other: np_ndarray[ShapeT, np.timedelta64] ) -> np_ndarray[ShapeT, np.bool_]: ... @overload - def __gt__(self, other: Series[pd.Timedelta]) -> Series[bool]: ... + def __gt__(self, other: Series[Timedelta]) -> Series[bool]: ... def __hash__(self) -> int: ... def isoformat(self) -> str: ... def to_numpy(self) -> np.timedelta64: ... diff --git a/pandas-stubs/_libs/tslibs/timestamps.pyi b/pandas-stubs/_libs/tslibs/timestamps.pyi index 49c7463e3..213607f44 100644 --- a/pandas-stubs/_libs/tslibs/timestamps.pyi +++ b/pandas-stubs/_libs/tslibs/timestamps.pyi @@ -175,7 +175,7 @@ class Timestamp(datetime, SupportsIndex): # Mypy complains Forward operator "" is not callable, so ignore misc # for le, lt ge and gt @overload # type: ignore[override] - def __le__(self, other: Timestamp | datetime | np.datetime64) -> bool: ... # type: ignore[misc] + def __le__(self, other: datetime | np.datetime64 | Self) -> bool: ... @overload def __le__(self, other: DatetimeIndex) -> np_1darray[np.bool]: ... @overload @@ -185,7 +185,7 @@ class Timestamp(datetime, SupportsIndex): @overload def __le__(self, other: Series[Timestamp]) -> Series[bool]: ... @overload # type: ignore[override] - def __lt__(self, other: Timestamp | datetime | np.datetime64) -> bool: ... # type: ignore[misc] + def __lt__(self, other: datetime | np.datetime64 | Self) -> bool: ... @overload def __lt__(self, other: DatetimeIndex) -> np_1darray[np.bool]: ... @overload @@ -195,7 +195,7 @@ class Timestamp(datetime, SupportsIndex): @overload def __lt__(self, other: Series[Timestamp]) -> Series[bool]: ... @overload # type: ignore[override] - def __ge__(self, other: Timestamp | datetime | np.datetime64) -> bool: ... # type: ignore[misc] + def __ge__(self, other: datetime | np.datetime64 | Self) -> bool: ... @overload def __ge__(self, other: DatetimeIndex) -> np_1darray[np.bool]: ... @overload @@ -205,7 +205,7 @@ class Timestamp(datetime, SupportsIndex): @overload def __ge__(self, other: Series[Timestamp]) -> Series[bool]: ... @overload # type: ignore[override] - def __gt__(self, other: Timestamp | datetime | np.datetime64) -> bool: ... # type: ignore[misc] + def __gt__(self, other: datetime | np.datetime64 | Self) -> bool: ... @overload def __gt__(self, other: DatetimeIndex) -> np_1darray[np.bool]: ... @overload @@ -243,7 +243,7 @@ class Timestamp(datetime, SupportsIndex): self, other: np_ndarray[ShapeT, np.timedelta64] ) -> np_ndarray[ShapeT, np.datetime64]: ... @overload - def __eq__(self, other: Timestamp | datetime | np.datetime64) -> bool: ... # type: ignore[overload-overlap] # pyright: ignore[reportOverlappingOverload] + def __eq__(self, other: datetime | np.datetime64 | Self) -> bool: ... # type: ignore[overload-overlap] # pyright: ignore[reportOverlappingOverload] @overload def __eq__(self, other: Series[Timestamp]) -> Series[bool]: ... # type: ignore[overload-overlap] @overload @@ -253,7 +253,7 @@ class Timestamp(datetime, SupportsIndex): @overload def __eq__(self, other: object) -> Literal[False]: ... @overload - def __ne__(self, other: Timestamp | datetime | np.datetime64) -> bool: ... # type: ignore[overload-overlap] # pyright: ignore[reportOverlappingOverload] + def __ne__(self, other: datetime | np.datetime64 | Self) -> bool: ... # type: ignore[overload-overlap] # pyright: ignore[reportOverlappingOverload] @overload def __ne__(self, other: Series[Timestamp]) -> Series[bool]: ... # type: ignore[overload-overlap] @overload From 7fd2f70e09ccbf1eab7ba39cb0517b64e210e0c2 Mon Sep 17 00:00:00 2001 From: cmp0xff Date: Sat, 18 Oct 2025 11:54:40 +0200 Subject: [PATCH 4/8] mypy happiness --- pandas-stubs/_libs/tslibs/period.pyi | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/pandas-stubs/_libs/tslibs/period.pyi b/pandas-stubs/_libs/tslibs/period.pyi index 759694c39..2763efafd 100644 --- a/pandas-stubs/_libs/tslibs/period.pyi +++ b/pandas-stubs/_libs/tslibs/period.pyi @@ -75,7 +75,7 @@ class Period(PeriodMixin): @overload def __sub__(self, other: _PeriodAddSub) -> Period: ... @overload - def __sub__(self, other: Period) -> BaseOffset: ... + def __sub__(self, other: Self) -> BaseOffset: ... @overload def __sub__(self, other: NaTType) -> NaTType: ... @overload @@ -107,7 +107,7 @@ class Period(PeriodMixin): # ignore[misc] here because we know all other comparisons # are False, so we use Literal[False] @overload - def __eq__(self, other: Period) -> bool: ... # type: ignore[overload-overlap] # pyright: ignore[reportOverlappingOverload] + def __eq__(self, other: Self) -> bool: ... # type: ignore[overload-overlap] # pyright: ignore[reportOverlappingOverload] @overload def __eq__(self, other: Index) -> np_1darray[np.bool]: ... # type: ignore[overload-overlap] @overload @@ -117,7 +117,7 @@ class Period(PeriodMixin): @overload def __eq__(self, other: object) -> Literal[False]: ... @overload - def __ge__(self, other: Period) -> bool: ... + def __ge__(self, other: Self) -> bool: ... @overload def __ge__(self, other: PeriodIndex) -> np_1darray[np.bool]: ... @overload @@ -129,7 +129,7 @@ class Period(PeriodMixin): self, other: np_ndarray[ShapeT, np.object_] ) -> np_ndarray[ShapeT, np.bool]: ... @overload - def __gt__(self, other: Period) -> bool: ... + def __gt__(self, other: Self) -> bool: ... @overload def __gt__(self, other: PeriodIndex) -> np_1darray[np.bool]: ... @overload @@ -141,7 +141,7 @@ class Period(PeriodMixin): self, other: np_ndarray[ShapeT, np.object_] ) -> np_ndarray[ShapeT, np.bool]: ... @overload - def __le__(self, other: Period) -> bool: ... + def __le__(self, other: Self) -> bool: ... @overload def __le__(self, other: PeriodIndex) -> np_1darray[np.bool]: ... @overload @@ -153,7 +153,7 @@ class Period(PeriodMixin): self, other: np_ndarray[ShapeT, np.object_] ) -> np_ndarray[ShapeT, np.bool]: ... @overload - def __lt__(self, other: Period) -> bool: ... + def __lt__(self, other: Self) -> bool: ... @overload def __lt__(self, other: PeriodIndex) -> np_1darray[np.bool]: ... @overload @@ -167,7 +167,7 @@ class Period(PeriodMixin): # ignore[misc] here because we know all other comparisons # are False, so we use Literal[False] @overload - def __ne__(self, other: Period) -> bool: ... # type: ignore[overload-overlap] # pyright: ignore[reportOverlappingOverload] + def __ne__(self, other: Self) -> bool: ... # type: ignore[overload-overlap] # pyright: ignore[reportOverlappingOverload] @overload def __ne__(self, other: Index) -> np_1darray[np.bool]: ... # type: ignore[overload-overlap] @overload From 9af8c9e8eb9e7425fef38baa83971d7f85f05eda Mon Sep 17 00:00:00 2001 From: cmp0xff Date: Sun, 19 Oct 2025 14:10:02 +0200 Subject: [PATCH 5/8] mypy happiness --- pandas-stubs/_libs/tslibs/period.pyi | 10 ---------- pandas-stubs/core/indexes/base.pyi | 4 ++++ 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/pandas-stubs/_libs/tslibs/period.pyi b/pandas-stubs/_libs/tslibs/period.pyi index 2763efafd..bfa517fb3 100644 --- a/pandas-stubs/_libs/tslibs/period.pyi +++ b/pandas-stubs/_libs/tslibs/period.pyi @@ -91,19 +91,9 @@ class Period(PeriodMixin): @overload def __add__(self, other: NaTType) -> NaTType: ... @overload - def __add__(self, other: Index) -> PeriodIndex: ... - # Ignored due to indecipherable error from mypy: - # Forward operator "__add__" is not callable [misc] - @overload def __radd__(self, other: _PeriodAddSub) -> Self: ... @overload def __radd__(self, other: NaTType) -> NaTType: ... - # Real signature is -> PeriodIndex, but conflicts with Index.__add__ - # Changing Index is very hard due to Index inheritance - # Signatures of "__radd__" of "Period" and "__add__" of "Index" - # are unsafely overlapping - @overload - def __radd__(self, other: Index) -> PeriodIndex: ... # ignore[misc] here because we know all other comparisons # are False, so we use Literal[False] @overload diff --git a/pandas-stubs/core/indexes/base.pyi b/pandas-stubs/core/indexes/base.pyi index 600061e4b..c87f33bf3 100644 --- a/pandas-stubs/core/indexes/base.pyi +++ b/pandas-stubs/core/indexes/base.pyi @@ -510,6 +510,8 @@ class Index(IndexOpsMixin[S1], ElementOpsMixin[S1]): @overload def __add__(self, other: Index[Never]) -> Index: ... @overload + def __add__(self: Index[Never], other: Period) -> PeriodIndex: ... + @overload def __add__( self: Supports_ProtoAdd[_T_contra, S2], other: _T_contra | Sequence[_T_contra] ) -> Index[S2]: ... @@ -558,6 +560,8 @@ class Index(IndexOpsMixin[S1], ElementOpsMixin[S1]): @overload def __radd__(self: Index[Never], other: complex | _ListLike | Index) -> Index: ... @overload + def __radd__(self: Index[Never], other: Period) -> PeriodIndex: ... + @overload def __radd__( self: Supports_ProtoRAdd[_T_contra, S2], other: _T_contra | Sequence[_T_contra], From b99f779ebe3b2c4f01041fe55d4732300f93e84f Mon Sep 17 00:00:00 2001 From: cmp0xff Date: Sun, 19 Oct 2025 22:58:29 +0200 Subject: [PATCH 6/8] Revert "mypy happiness" This reverts commit 9af8c9e8eb9e7425fef38baa83971d7f85f05eda. --- pandas-stubs/_libs/tslibs/period.pyi | 10 ++++++++++ pandas-stubs/core/indexes/base.pyi | 4 ---- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/pandas-stubs/_libs/tslibs/period.pyi b/pandas-stubs/_libs/tslibs/period.pyi index bfa517fb3..2763efafd 100644 --- a/pandas-stubs/_libs/tslibs/period.pyi +++ b/pandas-stubs/_libs/tslibs/period.pyi @@ -91,9 +91,19 @@ class Period(PeriodMixin): @overload def __add__(self, other: NaTType) -> NaTType: ... @overload + def __add__(self, other: Index) -> PeriodIndex: ... + # Ignored due to indecipherable error from mypy: + # Forward operator "__add__" is not callable [misc] + @overload def __radd__(self, other: _PeriodAddSub) -> Self: ... @overload def __radd__(self, other: NaTType) -> NaTType: ... + # Real signature is -> PeriodIndex, but conflicts with Index.__add__ + # Changing Index is very hard due to Index inheritance + # Signatures of "__radd__" of "Period" and "__add__" of "Index" + # are unsafely overlapping + @overload + def __radd__(self, other: Index) -> PeriodIndex: ... # ignore[misc] here because we know all other comparisons # are False, so we use Literal[False] @overload diff --git a/pandas-stubs/core/indexes/base.pyi b/pandas-stubs/core/indexes/base.pyi index c87f33bf3..600061e4b 100644 --- a/pandas-stubs/core/indexes/base.pyi +++ b/pandas-stubs/core/indexes/base.pyi @@ -510,8 +510,6 @@ class Index(IndexOpsMixin[S1], ElementOpsMixin[S1]): @overload def __add__(self, other: Index[Never]) -> Index: ... @overload - def __add__(self: Index[Never], other: Period) -> PeriodIndex: ... - @overload def __add__( self: Supports_ProtoAdd[_T_contra, S2], other: _T_contra | Sequence[_T_contra] ) -> Index[S2]: ... @@ -560,8 +558,6 @@ class Index(IndexOpsMixin[S1], ElementOpsMixin[S1]): @overload def __radd__(self: Index[Never], other: complex | _ListLike | Index) -> Index: ... @overload - def __radd__(self: Index[Never], other: Period) -> PeriodIndex: ... - @overload def __radd__( self: Supports_ProtoRAdd[_T_contra, S2], other: _T_contra | Sequence[_T_contra], From 84006462db0bfafabeaaafb71d355eff7baea7fa Mon Sep 17 00:00:00 2001 From: cmp0xff Date: Sun, 19 Oct 2025 23:00:48 +0200 Subject: [PATCH 7/8] mypy happiness --- pandas-stubs/_libs/tslibs/period.pyi | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/pandas-stubs/_libs/tslibs/period.pyi b/pandas-stubs/_libs/tslibs/period.pyi index 2763efafd..38ca48a2e 100644 --- a/pandas-stubs/_libs/tslibs/period.pyi +++ b/pandas-stubs/_libs/tslibs/period.pyi @@ -1,4 +1,5 @@ import datetime +import sys from typing import ( Literal, TypeAlias, @@ -94,8 +95,13 @@ class Period(PeriodMixin): def __add__(self, other: Index) -> PeriodIndex: ... # Ignored due to indecipherable error from mypy: # Forward operator "__add__" is not callable [misc] - @overload - def __radd__(self, other: _PeriodAddSub) -> Self: ... + if sys.version_info >= (3, 11): + @overload + def __radd__(self, other: _PeriodAddSub) -> Self: ... + else: + @overload + def __radd__(self, other: _PeriodAddSub) -> Self: ... # type: ignore[misc] + @overload def __radd__(self, other: NaTType) -> NaTType: ... # Real signature is -> PeriodIndex, but conflicts with Index.__add__ From afd143aec060092a911d393e0ac2e8c81f0d7028 Mon Sep 17 00:00:00 2001 From: cmp0xff Date: Mon, 20 Oct 2025 09:25:18 +0200 Subject: [PATCH 8/8] fix(comment): https://github.com/pandas-dev/pandas-stubs/pull/1433/files#r2443621649 --- pyproject.toml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pyproject.toml b/pyproject.toml index 6fb59dfce..f1223bc0b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -178,6 +178,7 @@ fix = true [tool.ruff.lint] extend-select = ["ALL"] ignore = [ + # The following rules are ignored permanently for good reasons "COM", # https://docs.astral.sh/ruff/rules/#flake8-commas-com "D", # https://docs.astral.sh/ruff/rules/#pydocstyle-d "E501", # handled by black https://docs.astral.sh/ruff/rules/line-too-long/ @@ -202,6 +203,7 @@ ignore = [ "ERA001", "ANN001", "ANN201", "ANN204", "ANN206", "ANN401", "PLR0402", "PLC0105" ] "scripts/*" = [ + # The following rules are ignored permanently for good reasons "EM", # https://docs.astral.sh/ruff/rules/#flake8-errmsg-em "S603", # https://docs.astral.sh/ruff/rules/subprocess-without-shell-equals-true/ ] @@ -222,6 +224,7 @@ ignore = [ "ANN001", "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 "S301", # https://docs.astral.sh/ruff/rules/suspicious-pickle-usage/ ]