2
2
3
3
import functools
4
4
from collections .abc import Iterable
5
- from typing import TYPE_CHECKING , cast
5
+ from typing import TYPE_CHECKING , TypeVar , cast
6
6
7
7
import numpy as np
8
+ from pandas .api .extensions import ExtensionDtype
8
9
from pandas .api .types import is_extension_array_dtype
9
10
10
11
from xarray .compat import array_api_compat , npcompat
14
15
if TYPE_CHECKING :
15
16
from typing import Any
16
17
17
- from pandas .api .extensions import ExtensionDtype
18
18
19
19
# Use as a sentinel value to indicate a dtype appropriate NA value.
20
20
NA = utils .ReprObject ("<NA>" )
@@ -53,10 +53,10 @@ def __eq__(self, other):
53
53
(np .bytes_ , np .str_ ), # numpy promotes to unicode
54
54
)
55
55
56
+ T_dtype = TypeVar ("T_dtype" , np .dtype , ExtensionDtype )
56
57
57
- def maybe_promote (
58
- dtype : np .dtype | ExtensionDtype ,
59
- ) -> tuple [np .dtype | ExtensionDtype , Any ]:
58
+
59
+ def maybe_promote (dtype : T_dtype ) -> tuple [T_dtype , Any ]:
60
60
"""Simpler equivalent of pandas.core.common._maybe_promote
61
61
62
62
Parameters
@@ -72,10 +72,12 @@ def maybe_promote(
72
72
dtype_ : np .typing .DTypeLike
73
73
fill_value : Any
74
74
if is_extension_array_dtype (dtype ):
75
- return dtype , dtype .na_value
76
- else :
77
- dtype = cast (np .dtype , dtype )
78
- if HAS_STRING_DTYPE and np .issubdtype (dtype , np .dtypes .StringDType ()):
75
+ return dtype , cast (ExtensionDtype , dtype ).na_value # type: ignore[redundant-cast]
76
+ if not isinstance (dtype , np .dtype ):
77
+ raise TypeError (
78
+ f"dtype { dtype } must be one of an extension array dtype or numpy dtype"
79
+ )
80
+ elif HAS_STRING_DTYPE and np .issubdtype (dtype , np .dtypes .StringDType ()):
79
81
# for now, we always promote string dtypes to object for consistency with existing behavior
80
82
# TODO: refactor this once we have a better way to handle numpy vlen-string dtypes
81
83
dtype_ = object
@@ -235,10 +237,14 @@ def isdtype(dtype, kind: str | tuple[str, ...], xp=None) -> bool:
235
237
236
238
237
239
def maybe_promote_to_variable_width (
238
- array_or_dtype : np .typing .ArrayLike | np .typing .DTypeLike ,
240
+ array_or_dtype : np .typing .ArrayLike
241
+ | np .typing .DTypeLike
242
+ | ExtensionDtype
243
+ | str
244
+ | bytes ,
239
245
* ,
240
246
should_return_str_or_bytes : bool = False ,
241
- ) -> np .typing .ArrayLike | np .typing .DTypeLike :
247
+ ) -> np .typing .ArrayLike | np .typing .DTypeLike | ExtensionDtype :
242
248
if isinstance (array_or_dtype , str | bytes ):
243
249
if should_return_str_or_bytes :
244
250
return array_or_dtype
@@ -256,7 +262,10 @@ def maybe_promote_to_variable_width(
256
262
257
263
258
264
def should_promote_to_object (
259
- arrays_and_dtypes : Iterable [np .typing .ArrayLike | np .typing .DTypeLike ], xp
265
+ arrays_and_dtypes : Iterable [
266
+ np .typing .ArrayLike | np .typing .DTypeLike | ExtensionDtype
267
+ ],
268
+ xp ,
260
269
) -> bool :
261
270
"""
262
271
Test whether the given arrays_and_dtypes, when evaluated individually, match the
@@ -286,9 +295,7 @@ def should_promote_to_object(
286
295
287
296
288
297
def result_type (
289
- * arrays_and_dtypes : list [
290
- np .typing .ArrayLike | np .typing .DTypeLike | ExtensionDtype
291
- ],
298
+ * arrays_and_dtypes : np .typing .ArrayLike | np .typing .DTypeLike | ExtensionDtype ,
292
299
xp = None ,
293
300
) -> np .dtype :
294
301
"""Like np.result_type, but with type promotion rules matching pandas.
0 commit comments