1""" define generic base classes for pandas objects """
2from __future__ import annotations
3
4from typing import (
5 TYPE_CHECKING,
6 Type,
7 cast,
8)
9
10if TYPE_CHECKING:
11 from pandas import (
12 Categorical,
13 CategoricalIndex,
14 DataFrame,
15 DatetimeIndex,
16 Index,
17 IntervalIndex,
18 MultiIndex,
19 PeriodIndex,
20 RangeIndex,
21 Series,
22 TimedeltaIndex,
23 )
24 from pandas.core.arrays import (
25 DatetimeArray,
26 ExtensionArray,
27 PandasArray,
28 PeriodArray,
29 TimedeltaArray,
30 )
31 from pandas.core.generic import NDFrame
32
33
34# define abstract base classes to enable isinstance type checking on our
35# objects
36def create_pandas_abc_type(name, attr, comp):
37 def _check(inst) -> bool:
38 return getattr(inst, attr, "_typ") in comp
39
40 # https://github.com/python/mypy/issues/1006
41 # error: 'classmethod' used with a non-method
42 @classmethod # type: ignore[misc]
43 def _instancecheck(cls, inst) -> bool:
44 return _check(inst) and not isinstance(inst, type)
45
46 @classmethod # type: ignore[misc]
47 def _subclasscheck(cls, inst) -> bool:
48 # Raise instead of returning False
49 # This is consistent with default __subclasscheck__ behavior
50 if not isinstance(inst, type):
51 raise TypeError("issubclass() arg 1 must be a class")
52
53 return _check(inst)
54
55 dct = {"__instancecheck__": _instancecheck, "__subclasscheck__": _subclasscheck}
56 meta = type("ABCBase", (type,), dct)
57 return meta(name, (), dct)
58
59
60ABCRangeIndex = cast(
61 "Type[RangeIndex]",
62 create_pandas_abc_type("ABCRangeIndex", "_typ", ("rangeindex",)),
63)
64ABCMultiIndex = cast(
65 "Type[MultiIndex]",
66 create_pandas_abc_type("ABCMultiIndex", "_typ", ("multiindex",)),
67)
68ABCDatetimeIndex = cast(
69 "Type[DatetimeIndex]",
70 create_pandas_abc_type("ABCDatetimeIndex", "_typ", ("datetimeindex",)),
71)
72ABCTimedeltaIndex = cast(
73 "Type[TimedeltaIndex]",
74 create_pandas_abc_type("ABCTimedeltaIndex", "_typ", ("timedeltaindex",)),
75)
76ABCPeriodIndex = cast(
77 "Type[PeriodIndex]",
78 create_pandas_abc_type("ABCPeriodIndex", "_typ", ("periodindex",)),
79)
80ABCCategoricalIndex = cast(
81 "Type[CategoricalIndex]",
82 create_pandas_abc_type("ABCCategoricalIndex", "_typ", ("categoricalindex",)),
83)
84ABCIntervalIndex = cast(
85 "Type[IntervalIndex]",
86 create_pandas_abc_type("ABCIntervalIndex", "_typ", ("intervalindex",)),
87)
88ABCIndex = cast(
89 "Type[Index]",
90 create_pandas_abc_type(
91 "ABCIndex",
92 "_typ",
93 {
94 "index",
95 "rangeindex",
96 "multiindex",
97 "datetimeindex",
98 "timedeltaindex",
99 "periodindex",
100 "categoricalindex",
101 "intervalindex",
102 },
103 ),
104)
105
106
107ABCNDFrame = cast(
108 "Type[NDFrame]",
109 create_pandas_abc_type("ABCNDFrame", "_typ", ("series", "dataframe")),
110)
111ABCSeries = cast(
112 "Type[Series]",
113 create_pandas_abc_type("ABCSeries", "_typ", ("series",)),
114)
115ABCDataFrame = cast(
116 "Type[DataFrame]", create_pandas_abc_type("ABCDataFrame", "_typ", ("dataframe",))
117)
118
119ABCCategorical = cast(
120 "Type[Categorical]",
121 create_pandas_abc_type("ABCCategorical", "_typ", ("categorical")),
122)
123ABCDatetimeArray = cast(
124 "Type[DatetimeArray]",
125 create_pandas_abc_type("ABCDatetimeArray", "_typ", ("datetimearray")),
126)
127ABCTimedeltaArray = cast(
128 "Type[TimedeltaArray]",
129 create_pandas_abc_type("ABCTimedeltaArray", "_typ", ("timedeltaarray")),
130)
131ABCPeriodArray = cast(
132 "Type[PeriodArray]",
133 create_pandas_abc_type("ABCPeriodArray", "_typ", ("periodarray",)),
134)
135ABCExtensionArray = cast(
136 "Type[ExtensionArray]",
137 create_pandas_abc_type(
138 "ABCExtensionArray",
139 "_typ",
140 # Note: IntervalArray and SparseArray are included bc they have _typ="extension"
141 {"extension", "categorical", "periodarray", "datetimearray", "timedeltaarray"},
142 ),
143)
144ABCPandasArray = cast(
145 "Type[PandasArray]",
146 create_pandas_abc_type("ABCPandasArray", "_typ", ("npy_extension",)),
147)