@@ -187,6 +187,31 @@ def wrapped(self, other, sort=False):
187
187
return wrapped
188
188
189
189
190
+ def _setop (op_name : str ):
191
+ """
192
+ Implement set operation.
193
+ """
194
+
195
+ def func (self , other , sort = None ):
196
+ # At this point we are assured
197
+ # isinstance(other, IntervalIndex)
198
+ # other.closed == self.closed
199
+
200
+ result = getattr (self ._multiindex , op_name )(other ._multiindex , sort = sort )
201
+ result_name = get_op_result_name (self , other )
202
+
203
+ # GH 19101: ensure empty results have correct dtype
204
+ if result .empty :
205
+ result = result ._values .astype (self .dtype .subtype )
206
+ else :
207
+ result = result ._values
208
+
209
+ return type (self ).from_tuples (result , closed = self .closed , name = result_name )
210
+
211
+ func .__name__ = op_name
212
+ return setop_check (func )
213
+
214
+
190
215
@Appender (
191
216
_interval_shared_docs ["class" ]
192
217
% {
@@ -218,19 +243,38 @@ def wrapped(self, other, sort=False):
218
243
}
219
244
)
220
245
@inherit_names (["set_closed" , "to_tuples" ], IntervalArray , wrap = True )
221
- @inherit_names (["__array__" , "overlaps" , "contains" ], IntervalArray )
246
+ @inherit_names (
247
+ [
248
+ "__array__" ,
249
+ "overlaps" ,
250
+ "contains" ,
251
+ "closed_left" ,
252
+ "closed_right" ,
253
+ "open_left" ,
254
+ "open_right" ,
255
+ "is_empty" ,
256
+ ],
257
+ IntervalArray ,
258
+ )
222
259
@inherit_names (["is_non_overlapping_monotonic" , "closed" ], IntervalArray , cache = True )
223
- class IntervalIndex (IntervalMixin , ExtensionIndex ):
260
+ class IntervalIndex (ExtensionIndex ):
224
261
_typ = "intervalindex"
225
262
_comparables = ["name" ]
226
263
_attributes = ["name" , "closed" ]
227
264
265
+ # annotate properties pinned via inherit_names
266
+ closed : str
267
+ is_non_overlapping_monotonic : bool
268
+ closed_left : bool
269
+ closed_right : bool
270
+
228
271
# we would like our indexing holder to defer to us
229
272
_defer_to_indexing = True
230
273
231
274
_data : IntervalArray
232
275
_values : IntervalArray
233
276
_can_hold_strings = False
277
+ _data_cls = IntervalArray
234
278
235
279
# --------------------------------------------------------------------
236
280
# Constructors
@@ -241,7 +285,7 @@ def __new__(
241
285
closed = None ,
242
286
dtype : Optional [Dtype ] = None ,
243
287
copy : bool = False ,
244
- name = None ,
288
+ name : Hashable = None ,
245
289
verify_integrity : bool = True ,
246
290
):
247
291
@@ -258,26 +302,6 @@ def __new__(
258
302
259
303
return cls ._simple_new (array , name )
260
304
261
- @classmethod
262
- def _simple_new (cls , array : IntervalArray , name : Hashable = None ):
263
- """
264
- Construct from an IntervalArray
265
-
266
- Parameters
267
- ----------
268
- array : IntervalArray
269
- name : Label, default None
270
- Attached as result.name
271
- """
272
- assert isinstance (array , IntervalArray ), type (array )
273
-
274
- result = IntervalMixin .__new__ (cls )
275
- result ._data = array
276
- result .name = name
277
- result ._cache = {}
278
- result ._reset_identity ()
279
- return result
280
-
281
305
@classmethod
282
306
@Appender (
283
307
_interval_shared_docs ["from_breaks" ]
@@ -605,7 +629,7 @@ def _searchsorted_monotonic(self, label, side: str = "left"):
605
629
"non-overlapping and all monotonic increasing or decreasing"
606
630
)
607
631
608
- if isinstance (label , IntervalMixin ):
632
+ if isinstance (label , ( IntervalMixin , IntervalIndex ) ):
609
633
raise NotImplementedError ("Interval objects are not currently supported" )
610
634
611
635
# GH 20921: "not is_monotonic_increasing" for the second condition
@@ -1012,26 +1036,6 @@ def _intersection_non_unique(self, other: IntervalIndex) -> IntervalIndex:
1012
1036
1013
1037
return self [mask ]
1014
1038
1015
- def _setop (op_name : str , sort = None ):
1016
- def func (self , other , sort = sort ):
1017
- # At this point we are assured
1018
- # isinstance(other, IntervalIndex)
1019
- # other.closed == self.closed
1020
-
1021
- result = getattr (self ._multiindex , op_name )(other ._multiindex , sort = sort )
1022
- result_name = get_op_result_name (self , other )
1023
-
1024
- # GH 19101: ensure empty results have correct dtype
1025
- if result .empty :
1026
- result = result ._values .astype (self .dtype .subtype )
1027
- else :
1028
- result = result ._values
1029
-
1030
- return type (self ).from_tuples (result , closed = self .closed , name = result_name )
1031
-
1032
- func .__name__ = op_name
1033
- return setop_check (func )
1034
-
1035
1039
_union = _setop ("union" )
1036
1040
_difference = _setop ("difference" )
1037
1041
0 commit comments