Coverage for /var/srv/projects/api.amasfac.comuna18.com/tmp/venv/lib/python3.9/site-packages/pandas/core/indexes/extension.py: 50%
83 statements
« prev ^ index » next coverage.py v6.4.4, created at 2023-07-17 14:22 -0600
« prev ^ index » next coverage.py v6.4.4, created at 2023-07-17 14:22 -0600
1"""
2Shared methods for Index subclasses backed by ExtensionArray.
3"""
4from __future__ import annotations
6from typing import (
7 TYPE_CHECKING,
8 Callable,
9 TypeVar,
10)
12import numpy as np
14from pandas._typing import (
15 ArrayLike,
16 npt,
17)
18from pandas.util._decorators import (
19 cache_readonly,
20 doc,
21)
23from pandas.core.dtypes.generic import ABCDataFrame
25from pandas.core.indexes.base import Index
27if TYPE_CHECKING: 27 ↛ 28line 27 didn't jump to line 28, because the condition on line 27 was never true
28 from pandas.core.arrays import IntervalArray
29 from pandas.core.arrays._mixins import NDArrayBackedExtensionArray
31_T = TypeVar("_T", bound="NDArrayBackedExtensionIndex")
32_ExtensionIndexT = TypeVar("_ExtensionIndexT", bound="ExtensionIndex")
35def _inherit_from_data(
36 name: str, delegate: type, cache: bool = False, wrap: bool = False
37):
38 """
39 Make an alias for a method of the underlying ExtensionArray.
41 Parameters
42 ----------
43 name : str
44 Name of an attribute the class should inherit from its EA parent.
45 delegate : class
46 cache : bool, default False
47 Whether to convert wrapped properties into cache_readonly
48 wrap : bool, default False
49 Whether to wrap the inherited result in an Index.
51 Returns
52 -------
53 attribute, method, property, or cache_readonly
54 """
55 attr = getattr(delegate, name)
57 if isinstance(attr, property) or type(attr).__name__ == "getset_descriptor":
58 # getset_descriptor i.e. property defined in cython class
59 if cache:
61 def cached(self):
62 return getattr(self._data, name)
64 cached.__name__ = name
65 cached.__doc__ = attr.__doc__
66 method = cache_readonly(cached)
68 else:
70 def fget(self):
71 result = getattr(self._data, name)
72 if wrap:
73 if isinstance(result, type(self._data)):
74 return type(self)._simple_new(result, name=self.name)
75 elif isinstance(result, ABCDataFrame):
76 return result.set_index(self)
77 return Index(result, name=self.name)
78 return result
80 def fset(self, value):
81 setattr(self._data, name, value)
83 fget.__name__ = name
84 fget.__doc__ = attr.__doc__
86 method = property(fget, fset)
88 elif not callable(attr): 88 ↛ 90line 88 didn't jump to line 90, because the condition on line 88 was never true
89 # just a normal attribute, no wrapping
90 method = attr
92 else:
93 # error: Incompatible redefinition (redefinition with type "Callable[[Any,
94 # VarArg(Any), KwArg(Any)], Any]", original type "property")
95 def method(self, *args, **kwargs): # type: ignore[misc]
96 if "inplace" in kwargs:
97 raise ValueError(f"cannot use inplace with {type(self).__name__}")
98 result = attr(self._data, *args, **kwargs)
99 if wrap:
100 if isinstance(result, type(self._data)):
101 return type(self)._simple_new(result, name=self.name)
102 elif isinstance(result, ABCDataFrame):
103 return result.set_index(self)
104 return Index(result, name=self.name)
105 return result
107 # error: "property" has no attribute "__name__"
108 method.__name__ = name # type: ignore[attr-defined]
109 method.__doc__ = attr.__doc__
110 return method
113def inherit_names(
114 names: list[str], delegate: type, cache: bool = False, wrap: bool = False
115) -> Callable[[type[_ExtensionIndexT]], type[_ExtensionIndexT]]:
116 """
117 Class decorator to pin attributes from an ExtensionArray to a Index subclass.
119 Parameters
120 ----------
121 names : List[str]
122 delegate : class
123 cache : bool, default False
124 wrap : bool, default False
125 Whether to wrap the inherited result in an Index.
126 """
128 def wrapper(cls: type[_ExtensionIndexT]) -> type[_ExtensionIndexT]:
129 for name in names:
130 meth = _inherit_from_data(name, delegate, cache=cache, wrap=wrap)
131 setattr(cls, name, meth)
133 return cls
135 return wrapper
138class ExtensionIndex(Index):
139 """
140 Index subclass for indexes backed by ExtensionArray.
141 """
143 # The base class already passes through to _data:
144 # size, __len__, dtype
146 _data: IntervalArray | NDArrayBackedExtensionArray
148 # ---------------------------------------------------------------------
150 def _validate_fill_value(self, value):
151 """
152 Convert value to be insertable to underlying array.
153 """
154 return self._data._validate_setitem_value(value)
156 @doc(Index.map)
157 def map(self, mapper, na_action=None):
158 # Try to run function on index first, and then on elements of index
159 # Especially important for group-by functionality
160 try:
161 result = mapper(self)
163 # Try to use this result if we can
164 if isinstance(result, np.ndarray):
165 result = Index(result)
167 if not isinstance(result, Index):
168 raise TypeError("The map function must return an Index object")
169 return result
170 except Exception:
171 return self.astype(object).map(mapper)
173 @cache_readonly
174 def _isnan(self) -> npt.NDArray[np.bool_]:
175 # error: Incompatible return value type (got "ExtensionArray", expected
176 # "ndarray")
177 return self._data.isna() # type: ignore[return-value]
180class NDArrayBackedExtensionIndex(ExtensionIndex):
181 """
182 Index subclass for indexes backed by NDArrayBackedExtensionArray.
183 """
185 _data: NDArrayBackedExtensionArray
187 def _get_engine_target(self) -> np.ndarray:
188 return self._data._ndarray
190 def _from_join_target(self, result: np.ndarray) -> ArrayLike:
191 assert result.dtype == self._data._ndarray.dtype
192 return self._data._from_backing_data(result)