44
55from contextlib import suppress
66from datetime import date , datetime , timedelta
7- from typing import TYPE_CHECKING , Any , List , Optional , Tuple , Type
7+ from typing import (
8+ TYPE_CHECKING ,
9+ Any ,
10+ List ,
11+ Optional ,
12+ Sequence ,
13+ Set ,
14+ Sized ,
15+ Tuple ,
16+ Type ,
17+ Union ,
18+ )
819
920import numpy as np
1021
2132 ints_to_pytimedelta ,
2233)
2334from pandas ._libs .tslibs .timezones import tz_compare
24- from pandas ._typing import ArrayLike , Dtype , DtypeObj
35+ from pandas ._typing import AnyArrayLike , ArrayLike , Dtype , DtypeObj , Scalar
2536from pandas .util ._validators import validate_bool_kwarg
2637
2738from pandas .core .dtypes .common import (
8697if TYPE_CHECKING :
8798 from pandas import Series
8899 from pandas .core .arrays import ExtensionArray
100+ from pandas .core .indexes .base import Index
101+ from pandas .core .indexes .datetimes import DatetimeIndex
89102
90103_int8_max = np .iinfo (np .int8 ).max
91104_int16_max = np .iinfo (np .int16 ).max
@@ -121,7 +134,7 @@ def is_nested_object(obj) -> bool:
121134 return False
122135
123136
124- def maybe_downcast_to_dtype (result , dtype ):
137+ def maybe_downcast_to_dtype (result , dtype : Dtype ):
125138 """
126139 try to cast to the specified dtype (e.g. convert back to bool/int
127140 or could be an astype of float64->float32
@@ -186,7 +199,7 @@ def maybe_downcast_to_dtype(result, dtype):
186199 return result
187200
188201
189- def maybe_downcast_numeric (result , dtype , do_round : bool = False ):
202+ def maybe_downcast_numeric (result , dtype : DtypeObj , do_round : bool = False ):
190203 """
191204 Subset of maybe_downcast_to_dtype restricted to numeric dtypes.
192205
@@ -329,7 +342,9 @@ def maybe_cast_result_dtype(dtype: DtypeObj, how: str) -> DtypeObj:
329342 return dtype
330343
331344
332- def maybe_cast_to_extension_array (cls : Type ["ExtensionArray" ], obj , dtype = None ):
345+ def maybe_cast_to_extension_array (
346+ cls : Type ["ExtensionArray" ], obj : ArrayLike , dtype : Optional [ExtensionDtype ] = None
347+ ) -> ArrayLike :
333348 """
334349 Call to `_from_sequence` that returns the object unchanged on Exception.
335350
@@ -362,7 +377,9 @@ def maybe_cast_to_extension_array(cls: Type["ExtensionArray"], obj, dtype=None):
362377 return result
363378
364379
365- def maybe_upcast_putmask (result : np .ndarray , mask : np .ndarray , other ):
380+ def maybe_upcast_putmask (
381+ result : np .ndarray , mask : np .ndarray , other : Scalar
382+ ) -> Tuple [np .ndarray , bool ]:
366383 """
367384 A safe version of putmask that potentially upcasts the result.
368385
@@ -444,7 +461,9 @@ def changeit():
444461 return result , False
445462
446463
447- def maybe_casted_values (index , codes = None ):
464+ def maybe_casted_values (
465+ index : "Index" , codes : Optional [np .ndarray ] = None
466+ ) -> ArrayLike :
448467 """
449468 Convert an index, given directly or as a pair (level, code), to a 1D array.
450469
@@ -468,7 +487,7 @@ def maybe_casted_values(index, codes=None):
468487
469488 # if we have the codes, extract the values with a mask
470489 if codes is not None :
471- mask = codes == - 1
490+ mask : np . ndarray = codes == - 1
472491
473492 # we can have situations where the whole mask is -1,
474493 # meaning there is nothing found in codes, so make all nan's
@@ -660,7 +679,7 @@ def maybe_promote(dtype, fill_value=np.nan):
660679 return dtype , fill_value
661680
662681
663- def _ensure_dtype_type (value , dtype ):
682+ def _ensure_dtype_type (value , dtype : DtypeObj ):
664683 """
665684 Ensure that the given value is an instance of the given dtype.
666685
@@ -786,8 +805,9 @@ def infer_dtype_from_scalar(val, pandas_dtype: bool = False) -> Tuple[DtypeObj,
786805 return dtype , val
787806
788807
789- # TODO: try to make the Any in the return annotation more specific
790- def infer_dtype_from_array (arr , pandas_dtype : bool = False ) -> Tuple [DtypeObj , Any ]:
808+ def infer_dtype_from_array (
809+ arr , pandas_dtype : bool = False
810+ ) -> Tuple [DtypeObj , ArrayLike ]:
791811 """
792812 Infer the dtype from an array.
793813
@@ -875,7 +895,12 @@ def maybe_infer_dtype_type(element):
875895 return tipo
876896
877897
878- def maybe_upcast (values , fill_value = np .nan , dtype = None , copy : bool = False ):
898+ def maybe_upcast (
899+ values : ArrayLike ,
900+ fill_value : Scalar = np .nan ,
901+ dtype : Dtype = None ,
902+ copy : bool = False ,
903+ ) -> Tuple [ArrayLike , Scalar ]:
879904 """
880905 Provide explicit type promotion and coercion.
881906
@@ -887,6 +912,13 @@ def maybe_upcast(values, fill_value=np.nan, dtype=None, copy: bool = False):
887912 dtype : if None, then use the dtype of the values, else coerce to this type
888913 copy : bool, default True
889914 If True always make a copy even if no upcast is required.
915+
916+ Returns
917+ -------
918+ values: ndarray or ExtensionArray
919+ the original array, possibly upcast
920+ fill_value:
921+ the fill value, possibly upcast
890922 """
891923 if not is_scalar (fill_value ) and not is_object_dtype (values .dtype ):
892924 # We allow arbitrary fill values for object dtype
@@ -907,7 +939,7 @@ def maybe_upcast(values, fill_value=np.nan, dtype=None, copy: bool = False):
907939 return values , fill_value
908940
909941
910- def invalidate_string_dtypes (dtype_set ):
942+ def invalidate_string_dtypes (dtype_set : Set [ DtypeObj ] ):
911943 """
912944 Change string like dtypes to object for
913945 ``DataFrame.select_dtypes()``.
@@ -929,7 +961,7 @@ def coerce_indexer_dtype(indexer, categories):
929961 return ensure_int64 (indexer )
930962
931963
932- def coerce_to_dtypes (result , dtypes ) :
964+ def coerce_to_dtypes (result : Sequence [ Scalar ] , dtypes : Sequence [ Dtype ]) -> List [ Scalar ] :
933965 """
934966 given a dtypes and a result set, coerce the result elements to the
935967 dtypes
@@ -959,7 +991,9 @@ def conv(r, dtype):
959991 return [conv (r , dtype ) for r , dtype in zip (result , dtypes )]
960992
961993
962- def astype_nansafe (arr , dtype , copy : bool = True , skipna : bool = False ):
994+ def astype_nansafe (
995+ arr , dtype : DtypeObj , copy : bool = True , skipna : bool = False
996+ ) -> ArrayLike :
963997 """
964998 Cast the elements of an array to a given dtype a nan-safe manner.
965999
@@ -1063,7 +1097,9 @@ def astype_nansafe(arr, dtype, copy: bool = True, skipna: bool = False):
10631097 return arr .view (dtype )
10641098
10651099
1066- def maybe_convert_objects (values : np .ndarray , convert_numeric : bool = True ):
1100+ def maybe_convert_objects (
1101+ values : np .ndarray , convert_numeric : bool = True
1102+ ) -> Union [np .ndarray , "DatetimeIndex" ]:
10671103 """
10681104 If we have an object dtype array, try to coerce dates and/or numbers.
10691105
@@ -1184,7 +1220,7 @@ def soft_convert_objects(
11841220
11851221
11861222def convert_dtypes (
1187- input_array ,
1223+ input_array : AnyArrayLike ,
11881224 convert_string : bool = True ,
11891225 convert_integer : bool = True ,
11901226 convert_boolean : bool = True ,
@@ -1195,7 +1231,7 @@ def convert_dtypes(
11951231
11961232 Parameters
11971233 ----------
1198- input_array : ExtensionArray or PandasArray
1234+ input_array : ExtensionArray, Index, Series or np.ndarray
11991235 convert_string : bool, default True
12001236 Whether object dtypes should be converted to ``StringDtype()``.
12011237 convert_integer : bool, default True
@@ -1250,9 +1286,11 @@ def convert_dtypes(
12501286 return inferred_dtype
12511287
12521288
1253- def maybe_castable (arr ) -> bool :
1289+ def maybe_castable (arr : np . ndarray ) -> bool :
12541290 # return False to force a non-fastpath
12551291
1292+ assert isinstance (arr , np .ndarray ) # GH 37024
1293+
12561294 # check datetime64[ns]/timedelta64[ns] are valid
12571295 # otherwise try to coerce
12581296 kind = arr .dtype .kind
@@ -1264,7 +1302,9 @@ def maybe_castable(arr) -> bool:
12641302 return arr .dtype .name not in POSSIBLY_CAST_DTYPES
12651303
12661304
1267- def maybe_infer_to_datetimelike (value , convert_dates : bool = False ):
1305+ def maybe_infer_to_datetimelike (
1306+ value : Union [ArrayLike , Scalar ], convert_dates : bool = False
1307+ ):
12681308 """
12691309 we might have a array (or single object) that is datetime like,
12701310 and no dtype is passed don't change the value unless we find a
@@ -1371,7 +1411,7 @@ def try_timedelta(v):
13711411 return value
13721412
13731413
1374- def maybe_cast_to_datetime (value , dtype , errors : str = "raise" ):
1414+ def maybe_cast_to_datetime (value , dtype : DtypeObj , errors : str = "raise" ):
13751415 """
13761416 try to cast the array/value to a datetimelike dtype, converting float
13771417 nan to iNaT
@@ -1564,7 +1604,9 @@ def find_common_type(types: List[DtypeObj]) -> DtypeObj:
15641604 return np .find_common_type (types , [])
15651605
15661606
1567- def cast_scalar_to_array (shape , value , dtype : Optional [DtypeObj ] = None ) -> np .ndarray :
1607+ def cast_scalar_to_array (
1608+ shape : Tuple , value : Scalar , dtype : Optional [DtypeObj ] = None
1609+ ) -> np .ndarray :
15681610 """
15691611 Create np.ndarray of specified shape and dtype, filled with values.
15701612
@@ -1592,7 +1634,7 @@ def cast_scalar_to_array(shape, value, dtype: Optional[DtypeObj] = None) -> np.n
15921634
15931635
15941636def construct_1d_arraylike_from_scalar (
1595- value , length : int , dtype : DtypeObj
1637+ value : Scalar , length : int , dtype : DtypeObj
15961638) -> ArrayLike :
15971639 """
15981640 create a np.ndarray / pandas type of specified shape and dtype
@@ -1636,7 +1678,7 @@ def construct_1d_arraylike_from_scalar(
16361678 return subarr
16371679
16381680
1639- def construct_1d_object_array_from_listlike (values ) -> np .ndarray :
1681+ def construct_1d_object_array_from_listlike (values : Sized ) -> np .ndarray :
16401682 """
16411683 Transform any list-like object in a 1-dimensional numpy array of object
16421684 dtype.
@@ -1662,7 +1704,7 @@ def construct_1d_object_array_from_listlike(values) -> np.ndarray:
16621704
16631705
16641706def construct_1d_ndarray_preserving_na (
1665- values , dtype : Optional [DtypeObj ] = None , copy : bool = False
1707+ values : Sequence , dtype : Optional [DtypeObj ] = None , copy : bool = False
16661708) -> np .ndarray :
16671709 """
16681710 Construct a new ndarray, coercing `values` to `dtype`, preserving NA.
@@ -1696,7 +1738,7 @@ def construct_1d_ndarray_preserving_na(
16961738 return subarr
16971739
16981740
1699- def maybe_cast_to_integer_array (arr , dtype , copy : bool = False ):
1741+ def maybe_cast_to_integer_array (arr , dtype : Dtype , copy : bool = False ):
17001742 """
17011743 Takes any dtype and returns the casted version, raising for when data is
17021744 incompatible with integer/unsigned integer dtypes.
@@ -1768,7 +1810,7 @@ def maybe_cast_to_integer_array(arr, dtype, copy: bool = False):
17681810 raise ValueError ("Trying to coerce float values to integers" )
17691811
17701812
1771- def convert_scalar_for_putitemlike (scalar , dtype : np .dtype ):
1813+ def convert_scalar_for_putitemlike (scalar : Scalar , dtype : np .dtype ) -> Scalar :
17721814 """
17731815 Convert datetimelike scalar if we are setting into a datetime64
17741816 or timedelta64 ndarray.
@@ -1799,7 +1841,7 @@ def convert_scalar_for_putitemlike(scalar, dtype: np.dtype):
17991841 return scalar
18001842
18011843
1802- def validate_numeric_casting (dtype : np .dtype , value ) :
1844+ def validate_numeric_casting (dtype : np .dtype , value : Scalar ) -> None :
18031845 """
18041846 Check that we can losslessly insert the given value into an array
18051847 with the given dtype.
0 commit comments