Skip to content

Make IndexOpsMixin (and Index) generic #760

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 25 commits into from
Aug 14, 2023
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
4929ecb
interpolate method
twoertwein Aug 2, 2023
2775a58
WIP
twoertwein Aug 2, 2023
9e40ddf
mypy handles Never differently - at least asssert that the method nev…
twoertwein Aug 3, 2023
68abe4d
use Self
twoertwein Aug 3, 2023
2cfbdb0
a few more S1/Self
twoertwein Aug 3, 2023
ebcc389
fix tests
twoertwein Aug 3, 2023
24d42fa
more tests
twoertwein Aug 3, 2023
f3802d3
add an ignore to let mypy pass
twoertwein Aug 3, 2023
92eab41
compat with old python versions
twoertwein Aug 3, 2023
6e04d8e
fix CategoricalIndex; MultiIndex should probably be Index[tuple[S1, .…
twoertwein Aug 3, 2023
e7a2d3b
Revert "interpolate method"
twoertwein Aug 3, 2023
d12a72a
many more overloads for subclasses (I wish pandas would not handle su…
twoertwein Aug 4, 2023
87c62d0
remove PandasObject - it caused the pyright issues but it provides no…
twoertwein Aug 4, 2023
9ce5fc4
works (except for np.ndarray)
twoertwein Aug 4, 2023
05b9c15
Merge remote-tracking branch 'upstream/main' into iter_interpolate
twoertwein Aug 8, 2023
d32f534
address the easy-to-fix comments
twoertwein Aug 8, 2023
4f13109
overloads for numpy
twoertwein Aug 9, 2023
bd39625
did numexpr break the CI?
twoertwein Aug 9, 2023
8c48567
lie: df.columns -> Index[str]
twoertwein Aug 9, 2023
67f5e8d
new ruff has far more pyi rules
twoertwein Aug 9, 2023
566c918
Make it clear that both mypy&pyright infer Never; but only pyright de…
twoertwein Aug 10, 2023
ff5ee58
use type aliases instead of npt
twoertwein Aug 10, 2023
c8d2019
fix issue with floordiv for mypy
Dr-Irv Aug 13, 2023
585c93b
fix comment in arraylike
Dr-Irv Aug 13, 2023
7ac1ea5
Merge pull request #3 from Dr-Irv/pr760
twoertwein Aug 14, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ repos:
hooks:
- id: isort
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.0.282
rev: v0.0.283
hooks:
- id: ruff
args: [
Expand Down
45 changes: 15 additions & 30 deletions pandas-stubs/_typing.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ DtypeBackend: TypeAlias = Literal["pyarrow", "numpy_nullable"]

BooleanDtypeArg: TypeAlias = (
# Builtin bool type and its string alias
type[bool] # noqa: PYI030
type[bool] # noqa: PYI030,PYI055
| Literal["bool"]
# Pandas nullable boolean type and its string alias
| pd.BooleanDtype
Expand All @@ -105,7 +105,7 @@ BooleanDtypeArg: TypeAlias = (
)
IntDtypeArg: TypeAlias = (
# Builtin integer type and its string alias
type[int] # noqa: PYI030
type[int] # noqa: PYI030,PYI055
| Literal["int"]
# Pandas nullable integer types and their string aliases
| pd.Int8Dtype
Expand Down Expand Up @@ -137,7 +137,7 @@ IntDtypeArg: TypeAlias = (
)
UIntDtypeArg: TypeAlias = (
# Pandas nullable unsigned integer types and their string aliases
pd.UInt8Dtype # noqa: PYI030
pd.UInt8Dtype # noqa: PYI030,PYI055
| pd.UInt16Dtype
| pd.UInt32Dtype
| pd.UInt64Dtype
Expand Down Expand Up @@ -166,7 +166,7 @@ UIntDtypeArg: TypeAlias = (
)
FloatDtypeArg: TypeAlias = (
# Builtin float type and its string alias
type[float] # noqa: PYI030
type[float] # noqa: PYI030,PYI055
| Literal["float"]
# Pandas nullable float types and their string aliases
| pd.Float32Dtype
Expand Down Expand Up @@ -197,7 +197,7 @@ FloatDtypeArg: TypeAlias = (
)
ComplexDtypeArg: TypeAlias = (
# Builtin complex type and its string alias
type[complex] # noqa: PYI030
type[complex] # noqa: PYI030,PYI055
| Literal["complex"]
# Numpy complex types and their aliases
# https://numpy.org/doc/stable/reference/arrays.scalars.html#numpy.csingle
Expand Down Expand Up @@ -326,7 +326,7 @@ TimestampDtypeArg: TypeAlias = Literal[

StrDtypeArg: TypeAlias = (
# Builtin str type and its string alias
type[str] # noqa: PYI030
type[str] # noqa: PYI030,PYI055
| Literal["str"]
# Pandas nullable string type and its string alias
| pd.StringDtype
Expand All @@ -340,7 +340,7 @@ StrDtypeArg: TypeAlias = (
)
BytesDtypeArg: TypeAlias = (
# Builtin bytes type and its string alias
type[bytes] # noqa: PYI030
type[bytes] # noqa: PYI030,PYI055
| Literal["bytes"]
# Numpy bytes type and its string alias
# https://numpy.org/doc/stable/reference/arrays.scalars.html#numpy.bytes_
Expand All @@ -353,7 +353,7 @@ CategoryDtypeArg: TypeAlias = CategoricalDtype | Literal["category"]

ObjectDtypeArg: TypeAlias = (
# Builtin object type and its string alias
type[object] # noqa: PYI030
type[object] # noqa: PYI030,PYI055
| Literal["object"]
# Numpy object type and its string alias
# https://numpy.org/doc/stable/reference/arrays.scalars.html#numpy.object_
Expand Down Expand Up @@ -511,19 +511,12 @@ S1 = TypeVar(
| float
| complex
| Dtype
| Timestamp
| Timedelta
| datetime.datetime # includes pd.Timestamp
| datetime.timedelta # includes pd.Timedelta
| Period
| Interval[int]
| Interval[float]
| Interval[Timestamp]
| Interval[Timedelta]
| Interval[int | float | Timestamp | Timedelta]
| CategoricalDtype,
)
T1 = TypeVar(
"T1", str, int, np.int64, np.uint64, np.float64, float, np.dtype[np.generic]
)
T2 = TypeVar("T2", str, int)

IndexingInt: TypeAlias = (
int | np.int_ | np.integer | np.unsignedinteger | np.signedinteger | np.int8
Expand Down Expand Up @@ -601,14 +594,9 @@ ByT = TypeVar(
| int
| float
| complex
| Timestamp
| Timedelta
| Scalar
| Period
| Interval[int]
| Interval[float]
| Interval[Timestamp]
| Interval[Timedelta]
| Interval[int | float | Timestamp | Timedelta]
| tuple,
)
# Use a distinct SeriesByT when using groupby with Series of known dtype.
Expand All @@ -622,13 +610,10 @@ SeriesByT = TypeVar(
| int
| float
| complex
| Timestamp
| Timedelta
| datetime.datetime
| datetime.timedelta
| Period
| Interval[int]
| Interval[float]
| Interval[Timestamp]
| Interval[Timedelta],
| Interval[int | float | Timestamp | Timedelta],
)
GroupByObjectNonScalar: TypeAlias = (
tuple
Expand Down
2 changes: 1 addition & 1 deletion pandas-stubs/core/frame.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -1482,7 +1482,7 @@ class DataFrame(NDFrame, OpsMixin):
@property
def at(self): ... # Not sure what to do with this yet; look at source
@property
def columns(self) -> Index: ...
def columns(self) -> Index[str]: ...
@columns.setter # setter needs to be right next to getter; otherwise mypy complains
def columns(
self, cols: AnyArrayLike | list[HashableT] | tuple[HashableT, ...]
Expand Down
3 changes: 1 addition & 2 deletions pandas-stubs/core/indexes/accessors.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,7 @@ from pandas._typing import (
np_ndarray_bool,
)

class Properties(PandasDelegate, NoNewAttributesMixin):
def __init__(self, data: Series, orig) -> None: ...
class Properties(PandasDelegate, NoNewAttributesMixin): ...

_DTFieldOpsReturnType = TypeVar("_DTFieldOpsReturnType", Series[int], Index[int])

Expand Down
40 changes: 20 additions & 20 deletions pandas-stubs/core/indexes/base.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ from pandas._typing import (
np_ndarray_anyint,
np_ndarray_bool,
np_ndarray_int64,
npt,
type_t,
)

Expand All @@ -66,9 +67,9 @@ class Index(IndexOpsMixin[S1]):
@overload
def __new__( # type: ignore[misc]
cls,
data: Iterable[int | np.integer],
data: Sequence[int | np.integer] | IndexOpsMixin[int] | npt.NDArray[np.integer],
*,
dtype: Literal["int"] | type_t[int] | type_t[np.integer] = ...,
dtype: Literal["int"] | type_t[int | np.integer] = ...,
copy: bool = ...,
name=...,
tupleize_cols: bool = ...,
Expand All @@ -79,7 +80,7 @@ class Index(IndexOpsMixin[S1]):
cls,
data: Iterable,
*,
dtype: Literal["int"] | type_t[int] | type_t[np.integer],
dtype: Literal["int"] | type_t[int | np.integer],
copy: bool = ...,
name=...,
tupleize_cols: bool = ...,
Expand All @@ -88,12 +89,11 @@ class Index(IndexOpsMixin[S1]):
@overload
def __new__( # type: ignore[misc]
cls,
data: Iterable[float | np.float32 | np.float64],
data: Sequence[float | np.floating]
| IndexOpsMixin[float]
| npt.NDArray[np.floating],
*,
dtype: Literal["float"]
| type_t[float]
| type_t[np.float32]
| type_t[np.float64] = ...,
dtype: Literal["float"] | type_t[float | np.floating] = ...,
copy: bool = ...,
name=...,
tupleize_cols: bool = ...,
Expand All @@ -104,10 +104,7 @@ class Index(IndexOpsMixin[S1]):
cls,
data: Iterable,
*,
dtype: Literal["float"]
| type_t[float]
| type_t[np.float32]
| type_t[np.float64],
dtype: Literal["float"] | type_t[float | np.floating],
copy: bool = ...,
name=...,
tupleize_cols: bool = ...,
Expand All @@ -116,9 +113,11 @@ class Index(IndexOpsMixin[S1]):
@overload
def __new__( # type: ignore[misc]
cls,
data: Iterable[complex],
data: Sequence[complex | np.complexfloating]
| IndexOpsMixin[complex]
| npt.NDArray[np.complexfloating],
*,
dtype: Literal["complex"] | type_t[complex] = ...,
dtype: Literal["complex"] | type_t[complex | np.complexfloating] = ...,
copy: bool = ...,
name=...,
tupleize_cols: bool = ...,
Expand All @@ -129,7 +128,7 @@ class Index(IndexOpsMixin[S1]):
cls,
data: Iterable,
*,
dtype: Literal["complex"] | type_t[complex],
dtype: Literal["complex"] | type_t[complex | np.complexfloating],
copy: bool = ...,
name=...,
tupleize_cols: bool = ...,
Expand All @@ -139,7 +138,7 @@ class Index(IndexOpsMixin[S1]):
@overload
def __new__( # type: ignore[misc]
cls,
data: Iterable[np.datetime64 | datetime],
data: Sequence[np.datetime64 | datetime] | IndexOpsMixin[datetime],
*,
dtype: TimestampDtypeArg = ...,
copy: bool = ...,
Expand All @@ -161,7 +160,7 @@ class Index(IndexOpsMixin[S1]):
@overload
def __new__( # type: ignore[misc]
cls,
data: Iterable[Period],
data: Sequence[Period] | IndexOpsMixin[Period],
*,
dtype: PeriodDtype = ...,
copy: bool = ...,
Expand All @@ -183,7 +182,7 @@ class Index(IndexOpsMixin[S1]):
@overload
def __new__( # type: ignore[misc]
cls,
data: Iterable[np.timedelta64 | timedelta],
data: Sequence[np.timedelta64 | timedelta] | IndexOpsMixin[timedelta],
*,
dtype: TimedeltaDtypeArg = ...,
copy: bool = ...,
Expand All @@ -205,7 +204,8 @@ class Index(IndexOpsMixin[S1]):
@overload
def __new__( # type: ignore[misc]
cls,
data: Iterable[Interval[_OrderableT]],
data: Sequence[Interval[_OrderableT]] # type: ignore[type-var]
| IndexOpsMixin[Interval[_OrderableT]],
*,
dtype: Literal["Interval"] = ...,
copy: bool = ...,
Expand All @@ -228,7 +228,7 @@ class Index(IndexOpsMixin[S1]):
@overload
def __new__(
cls,
data: Iterable[S1] = ...,
data: Iterable[S1] | IndexOpsMixin[S1] = ...,
*,
dtype: type[S1] = ...,
copy: bool = ...,
Expand Down
3 changes: 1 addition & 2 deletions pandas-stubs/core/indexes/multi.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ from pandas.core.indexes.base import Index
from typing_extensions import Self

from pandas._typing import (
T1,
Dtype,
DtypeArg,
HashableT,
Expand Down Expand Up @@ -156,7 +155,7 @@ class MultiIndex(Index[Any]):
def union(self, other, sort=...): ...
def intersection(self, other, sort: bool = ...): ...
def difference(self, other, sort=...): ...
def astype(self, dtype: DtypeArg | T1, copy: bool = ...) -> Self: ...
def astype(self, dtype: DtypeArg, copy: bool = ...) -> Self: ...
def insert(self, loc, item): ...
def delete(self, loc): ...
def isin(self, values, level=...) -> np_ndarray_bool: ...
Expand Down
12 changes: 0 additions & 12 deletions pandas-stubs/core/indexes/timedeltas.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -32,18 +32,6 @@ from pandas._typing import (
)

class TimedeltaIndex(DatetimeTimedeltaMixin[Timedelta], TimedeltaIndexProperties):
def __init__(
self,
data: AnyArrayLike
| list[str]
| Sequence[dt.timedelta | Timedelta | np.timedelta64 | float] = ...,
unit: Literal["D", "h", "m", "s", "ms", "us", "ns"] = ...,
freq: str | BaseOffset = ...,
closed: object = ...,
dtype: Literal["<m8[ns]"] = ...,
copy: bool = ...,
name: str = ...,
) -> None: ...
def __new__(
cls,
data: AnyArrayLike
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ jinja2 = ">=3.1"
scipy = ">=1.9.1"
SQLAlchemy = ">=2.0.12"
types-python-dateutil = ">=2.8.19"
numexpr = "<2.8.5" # https://github.com/pandas-dev/pandas/issues/54449

[build-system]
requires = ["poetry-core>=1.0.0"]
Expand Down Expand Up @@ -195,7 +196,6 @@ reportPrivateUsage = false
# enable optional checks
reportMissingModuleSource = true
useLibraryCodeForTypes = false
defineConstant = { MYPY_CHECKING = false }

[tool.codespell]
ignore-words-list = "indext, mose, sav, ser"
5 changes: 2 additions & 3 deletions tests/test_frame.py
Original file line number Diff line number Diff line change
Expand Up @@ -1761,8 +1761,7 @@ def test_getmultiindex_columns() -> None:
[(i, s) for i in [1] for s in df.columns.get_level_values(1)]
]
res4: pd.DataFrame = df[[df.columns[0]]]
column: Scalar = df.columns[0]
check(assert_type(df[column], pd.Series), pd.Series)
check(assert_type(df[df.columns[0]], pd.Series), pd.Series)
check(assert_type(df[li[0]], pd.Series), pd.Series)


Expand Down Expand Up @@ -2592,7 +2591,7 @@ def test_in_columns() -> None:
# GH 532 (PR)
df = pd.DataFrame(np.random.random((3, 4)), columns=["cat", "dog", "rat", "pig"])
cols = [c for c in df.columns if "at" in c]
check(assert_type(cols, list), list, str)
check(assert_type(cols, "list[str]"), list, str)
check(assert_type(df.loc[:, cols], pd.DataFrame), pd.DataFrame)
check(assert_type(df[cols], pd.DataFrame), pd.DataFrame)
check(assert_type(df.groupby(by=cols).sum(), pd.DataFrame), pd.DataFrame)
Expand Down
12 changes: 4 additions & 8 deletions tests/test_indexes.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import datetime as dt
from typing import (
TYPE_CHECKING,
Tuple,
Union,
)
Expand All @@ -22,9 +21,6 @@
check,
)

if TYPE_CHECKING:
MYPY_CHECKING: bool = True


def test_index_unique() -> None:
df = pd.DataFrame({"x": [1, 2, 3, 4]}, index=pd.Index([1, 2, 3, 2]))
Expand Down Expand Up @@ -77,9 +73,9 @@ def test_column_getitem() -> None:
# https://github.com/microsoft/python-type-stubs/issues/199#issuecomment-1132806594
df = pd.DataFrame([[1, 2, 3]], columns=["a", "b", "c"])

columns: pd.Index[str] = df.columns
check(assert_type(columns[0], str), str)
check(assert_type(df[columns[0]], pd.Series), pd.Series, np.int64)
column = df.columns[0]
check(assert_type(column, str), str)
check(assert_type(df[column], pd.Series), pd.Series, np.int64)


def test_column_contains() -> None:
Expand All @@ -97,7 +93,7 @@ def test_column_sequence() -> None:
df = pd.DataFrame([1, 2, 3])
col_list = list(df.columns)
check(
assert_type(col_list, list),
assert_type(col_list, "list[str]"),
list,
int,
)
Expand Down
Loading