|
19 | 19 | cast, |
20 | 20 | overload, |
21 | 21 | ) |
| 22 | +import warnings |
22 | 23 |
|
23 | 24 | import numpy as np |
24 | 25 |
|
|
33 | 34 | cache_readonly, |
34 | 35 | set_module, |
35 | 36 | ) |
| 37 | +from pandas.util._exceptions import find_stack_level |
36 | 38 | from pandas.util._validators import ( |
37 | 39 | validate_bool_kwarg, |
38 | 40 | validate_insert_loc, |
|
86 | 88 | AstypeArg, |
87 | 89 | AxisInt, |
88 | 90 | Dtype, |
| 91 | + DtypeObj, |
89 | 92 | FillnaOptions, |
90 | 93 | InterpolateOptions, |
91 | 94 | NumpySorter, |
@@ -383,13 +386,67 @@ def _from_factorized(cls, values, original): |
383 | 386 | """ |
384 | 387 | raise AbstractMethodError(cls) |
385 | 388 |
|
| 389 | + @classmethod |
| 390 | + def _from_scalars(cls, scalars, *, dtype: DtypeObj) -> Self: |
| 391 | + """ |
| 392 | + Strict analogue to _from_sequence, allowing only sequences of scalars |
| 393 | + that should be specifically inferred to the given dtype. |
| 394 | +
|
| 395 | + Parameters |
| 396 | + ---------- |
| 397 | + scalars : sequence |
| 398 | + dtype : ExtensionDtype |
| 399 | +
|
| 400 | + Raises |
| 401 | + ------ |
| 402 | + TypeError or ValueError |
| 403 | +
|
| 404 | + Notes |
| 405 | + ----- |
| 406 | + This is called in a try/except block when casting the result of a |
| 407 | + pointwise operation in ExtensionArray._cast_pointwise_result. |
| 408 | + """ |
| 409 | + try: |
| 410 | + return cls._from_sequence(scalars, dtype=dtype, copy=False) |
| 411 | + except (ValueError, TypeError): |
| 412 | + raise |
| 413 | + except Exception: |
| 414 | + warnings.warn( |
| 415 | + "_from_scalars should only raise ValueError or TypeError. " |
| 416 | + "Consider overriding _from_scalars where appropriate.", |
| 417 | + stacklevel=find_stack_level(), |
| 418 | + ) |
| 419 | + raise |
| 420 | + |
386 | 421 | def _cast_pointwise_result(self, values) -> ArrayLike: |
387 | 422 | """ |
| 423 | + Construct an ExtensionArray after a pointwise operation. |
| 424 | +
|
388 | 425 | Cast the result of a pointwise operation (e.g. Series.map) to an |
389 | | - array, preserve dtype_backend if possible. |
| 426 | + array. This is not required to return an ExtensionArray of the same |
| 427 | + type as self or of the same dtype. It can also return another |
| 428 | + ExtensionArray of the same "family" if you implement multiple |
| 429 | + ExtensionArrays/Dtypes that are interoperable (e.g. if you have float |
| 430 | + array with units, this method can return an int array with units). |
| 431 | +
|
| 432 | + If converting to your own ExtensionArray is not possible, this method |
| 433 | + falls back to returning an array with the default type inference. |
| 434 | + If you only need to cast to `self.dtype`, it is recommended to override |
| 435 | + `_from_scalars` instead of this method. |
| 436 | +
|
| 437 | + Parameters |
| 438 | + ---------- |
| 439 | + values : sequence |
| 440 | +
|
| 441 | + Returns |
| 442 | + ------- |
| 443 | + ExtensionArray or ndarray |
390 | 444 | """ |
391 | | - values = np.asarray(values, dtype=object) |
392 | | - return lib.maybe_convert_objects(values, convert_non_numeric=True) |
| 445 | + try: |
| 446 | + return type(self)._from_scalars(values, dtype=self.dtype) |
| 447 | + except (ValueError, TypeError): |
| 448 | + values = np.asarray(values, dtype=object) |
| 449 | + return lib.maybe_convert_objects(values, convert_non_numeric=True) |
393 | 450 |
|
394 | 451 | # ------------------------------------------------------------------------ |
395 | 452 | # Must be a Sequence |
|
0 commit comments