81
81
find_common_type ,
82
82
infer_dtype_from ,
83
83
maybe_cast_pointwise_result ,
84
- maybe_infer_to_datetimelike ,
85
84
np_can_hold_element ,
86
85
)
87
86
from pandas .core .dtypes .common import (
116
115
DatetimeTZDtype ,
117
116
ExtensionDtype ,
118
117
IntervalDtype ,
119
- PandasDtype ,
120
118
PeriodDtype ,
121
119
)
122
120
from pandas .core .dtypes .generic import (
208
206
_dtype_obj = np .dtype ("object" )
209
207
210
208
209
+ def _wrapped_sanitize (cls , data , dtype : DtypeObj | None , copy : bool ):
210
+ """
211
+ Call sanitize_array with wrapping for differences between Index/Series.
212
+ """
213
+ try :
214
+ arr = sanitize_array (data , None , dtype = dtype , copy = copy , strict_ints = True )
215
+ except ValueError as err :
216
+ if "index must be specified when data is not list-like" in str (err ):
217
+ raise cls ._raise_scalar_data_error (data ) from err
218
+ if "Data must be 1-dimensional" in str (err ):
219
+ raise ValueError ("Index data must be 1-dimensional" ) from err
220
+ raise
221
+ arr = ensure_wrapped_if_datetimelike (arr )
222
+ return arr
223
+
224
+
211
225
def _maybe_return_indexers (meth : F ) -> F :
212
226
"""
213
227
Decorator to simplify 'return_indexers' checks in Index.join.
@@ -422,21 +436,13 @@ def __new__(
422
436
tupleize_cols : bool = True ,
423
437
) -> Index :
424
438
425
- from pandas .core .arrays import PandasArray
426
439
from pandas .core .indexes .range import RangeIndex
427
440
428
441
name = maybe_extract_name (name , data , cls )
429
442
430
443
if dtype is not None :
431
444
dtype = pandas_dtype (dtype )
432
445
433
- if type (data ) is PandasArray :
434
- # ensure users don't accidentally put a PandasArray in an index,
435
- # but don't unpack StringArray
436
- data = data .to_numpy ()
437
- if isinstance (dtype , PandasDtype ):
438
- dtype = dtype .numpy_dtype
439
-
440
446
data_dtype = getattr (data , "dtype" , None )
441
447
442
448
# range
@@ -448,28 +454,10 @@ def __new__(
448
454
449
455
elif is_ea_or_datetimelike_dtype (dtype ):
450
456
# non-EA dtype indexes have special casting logic, so we punt here
451
- klass = cls ._dtype_to_subclass (dtype )
452
- if klass is not Index :
453
- return klass (data , dtype = dtype , copy = copy , name = name )
454
-
455
- ea_cls = dtype .construct_array_type ()
456
- data = ea_cls ._from_sequence (data , dtype = dtype , copy = copy )
457
- return Index ._simple_new (data , name = name )
457
+ pass
458
458
459
459
elif is_ea_or_datetimelike_dtype (data_dtype ):
460
- data_dtype = cast (DtypeObj , data_dtype )
461
- klass = cls ._dtype_to_subclass (data_dtype )
462
- if klass is not Index :
463
- result = klass (data , copy = copy , name = name )
464
- if dtype is not None :
465
- return result .astype (dtype , copy = False )
466
- return result
467
- elif dtype is not None :
468
- # GH#45206
469
- data = data .astype (dtype , copy = False )
470
-
471
- data = extract_array (data , extract_numpy = True )
472
- return Index ._simple_new (data , name = name )
460
+ pass
473
461
474
462
# index-like
475
463
elif (
@@ -483,42 +471,25 @@ def __new__(
483
471
if isinstance (data , ABCMultiIndex ):
484
472
data = data ._values
485
473
486
- if dtype is not None :
487
- # we need to avoid having numpy coerce
474
+ if data . dtype . kind not in [ "i" , "u" , "f" , "b" , "c" , "m" , "M" ] :
475
+ # GH#11836 we need to avoid having numpy coerce
488
476
# things that look like ints/floats to ints unless
489
477
# they are actually ints, e.g. '0' and 0.0
490
478
# should not be coerced
491
- # GH 11836
492
- data = sanitize_array (data , None , dtype = dtype , copy = copy )
493
-
494
- dtype = data .dtype
495
-
496
- if data .dtype .kind in ["i" , "u" , "f" ]:
497
- # maybe coerce to a sub-class
498
- arr = data
499
- elif data .dtype .kind in ["b" , "c" ]:
500
- # No special subclass, and Index._ensure_array won't do this
501
- # for us.
502
- arr = np .asarray (data )
503
- else :
504
- arr = com .asarray_tuplesafe (data , dtype = _dtype_obj )
505
-
506
- if dtype is None :
507
- arr = maybe_infer_to_datetimelike (arr )
508
- arr = ensure_wrapped_if_datetimelike (arr )
509
- dtype = arr .dtype
510
-
511
- klass = cls ._dtype_to_subclass (arr .dtype )
512
- arr = klass ._ensure_array (arr , dtype , copy )
513
- return klass ._simple_new (arr , name )
479
+ data = com .asarray_tuplesafe (data , dtype = _dtype_obj )
514
480
515
481
elif is_scalar (data ):
516
482
raise cls ._raise_scalar_data_error (data )
517
483
elif hasattr (data , "__array__" ):
518
484
return Index (np .asarray (data ), dtype = dtype , copy = copy , name = name )
485
+ elif not is_list_like (data ) and not isinstance (data , memoryview ):
486
+ # 2022-11-16 the memoryview check is only necessary on some CI
487
+ # builds, not clear why
488
+ raise cls ._raise_scalar_data_error (data )
489
+
519
490
else :
520
491
521
- if tupleize_cols and is_list_like ( data ) :
492
+ if tupleize_cols :
522
493
# GH21470: convert iterable to list before determining if empty
523
494
if is_iterator (data ):
524
495
data = list (data )
@@ -531,12 +502,24 @@ def __new__(
531
502
return MultiIndex .from_tuples (data , names = name )
532
503
# other iterable of some kind
533
504
534
- subarr = com .asarray_tuplesafe (data , dtype = _dtype_obj )
535
- if dtype is None :
536
- # with e.g. a list [1, 2, 3] casting to numeric is _not_ deprecated
537
- subarr = _maybe_cast_data_without_dtype (subarr )
538
- dtype = subarr .dtype
539
- return Index (subarr , dtype = dtype , copy = copy , name = name )
505
+ if not isinstance (data , (list , tuple )):
506
+ # we allow set/frozenset, which Series/sanitize_array does not, so
507
+ # cast to list here
508
+ data = list (data )
509
+ if len (data ) == 0 :
510
+ # unlike Series, we default to object dtype:
511
+ data = np .array (data , dtype = object )
512
+
513
+ if len (data ) and isinstance (data [0 ], tuple ):
514
+ # Ensure we get 1-D array of tuples instead of 2D array.
515
+ data = com .asarray_tuplesafe (data , dtype = _dtype_obj )
516
+
517
+ arr = _wrapped_sanitize (cls , data , dtype , copy )
518
+ klass = cls ._dtype_to_subclass (arr .dtype )
519
+
520
+ # _ensure_array _may_ be unnecessary once Int64Index etc are gone
521
+ arr = klass ._ensure_array (arr , arr .dtype , copy = False )
522
+ return klass ._simple_new (arr , name )
540
523
541
524
@classmethod
542
525
def _ensure_array (cls , data , dtype , copy : bool ):
@@ -7048,32 +7031,6 @@ def maybe_extract_name(name, obj, cls) -> Hashable:
7048
7031
return name
7049
7032
7050
7033
7051
- def _maybe_cast_data_without_dtype (subarr : npt .NDArray [np .object_ ]) -> ArrayLike :
7052
- """
7053
- If we have an arraylike input but no passed dtype, try to infer
7054
- a supported dtype.
7055
-
7056
- Parameters
7057
- ----------
7058
- subarr : np.ndarray[object]
7059
-
7060
- Returns
7061
- -------
7062
- np.ndarray or ExtensionArray
7063
- """
7064
-
7065
- result = lib .maybe_convert_objects (
7066
- subarr ,
7067
- convert_datetime = True ,
7068
- convert_timedelta = True ,
7069
- convert_period = True ,
7070
- convert_interval = True ,
7071
- dtype_if_all_nat = np .dtype ("datetime64[ns]" ),
7072
- )
7073
- result = ensure_wrapped_if_datetimelike (result )
7074
- return result
7075
-
7076
-
7077
7034
def get_unanimous_names (* indexes : Index ) -> tuple [Hashable , ...]:
7078
7035
"""
7079
7036
Return common name if all indices agree, otherwise None (level-by-level).
0 commit comments