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

1""" 

2Shared methods for Index subclasses backed by ExtensionArray. 

3""" 

4from __future__ import annotations 

5 

6from typing import ( 

7 TYPE_CHECKING, 

8 Callable, 

9 TypeVar, 

10) 

11 

12import numpy as np 

13 

14from pandas._typing import ( 

15 ArrayLike, 

16 npt, 

17) 

18from pandas.util._decorators import ( 

19 cache_readonly, 

20 doc, 

21) 

22 

23from pandas.core.dtypes.generic import ABCDataFrame 

24 

25from pandas.core.indexes.base import Index 

26 

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 

30 

31_T = TypeVar("_T", bound="NDArrayBackedExtensionIndex") 

32_ExtensionIndexT = TypeVar("_ExtensionIndexT", bound="ExtensionIndex") 

33 

34 

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. 

40 

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. 

50 

51 Returns 

52 ------- 

53 attribute, method, property, or cache_readonly 

54 """ 

55 attr = getattr(delegate, name) 

56 

57 if isinstance(attr, property) or type(attr).__name__ == "getset_descriptor": 

58 # getset_descriptor i.e. property defined in cython class 

59 if cache: 

60 

61 def cached(self): 

62 return getattr(self._data, name) 

63 

64 cached.__name__ = name 

65 cached.__doc__ = attr.__doc__ 

66 method = cache_readonly(cached) 

67 

68 else: 

69 

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 

79 

80 def fset(self, value): 

81 setattr(self._data, name, value) 

82 

83 fget.__name__ = name 

84 fget.__doc__ = attr.__doc__ 

85 

86 method = property(fget, fset) 

87 

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 

91 

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 

106 

107 # error: "property" has no attribute "__name__" 

108 method.__name__ = name # type: ignore[attr-defined] 

109 method.__doc__ = attr.__doc__ 

110 return method 

111 

112 

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. 

118 

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 """ 

127 

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) 

132 

133 return cls 

134 

135 return wrapper 

136 

137 

138class ExtensionIndex(Index): 

139 """ 

140 Index subclass for indexes backed by ExtensionArray. 

141 """ 

142 

143 # The base class already passes through to _data: 

144 # size, __len__, dtype 

145 

146 _data: IntervalArray | NDArrayBackedExtensionArray 

147 

148 # --------------------------------------------------------------------- 

149 

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) 

155 

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) 

162 

163 # Try to use this result if we can 

164 if isinstance(result, np.ndarray): 

165 result = Index(result) 

166 

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) 

172 

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] 

178 

179 

180class NDArrayBackedExtensionIndex(ExtensionIndex): 

181 """ 

182 Index subclass for indexes backed by NDArrayBackedExtensionArray. 

183 """ 

184 

185 _data: NDArrayBackedExtensionArray 

186 

187 def _get_engine_target(self) -> np.ndarray: 

188 return self._data._ndarray 

189 

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)