Skip to content

Commit 47bc953

Browse files
Backport PR #61085 on branch 2.3.x (DEPS: Update NumpyExtensionArray repr for NEP51) (#61107)
Backport PR #61085: DEPS: Update NumpyExtensionArray repr for NEP51 Co-authored-by: Richard Shadrach <[email protected]>
1 parent 9857d31 commit 47bc953

File tree

3 files changed

+42
-2
lines changed

3 files changed

+42
-2
lines changed

doc/source/whatsnew/v2.3.0.rst

+1
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ Other enhancements
3737
updated to raise FutureWarning with NumPy >= 2 (:issue:`60340`)
3838
- :meth:`Series.str.decode` result now has ``StringDtype`` when ``future.infer_string`` is True (:issue:`60709`)
3939
- :meth:`~Series.to_hdf` and :meth:`~DataFrame.to_hdf` now round-trip with ``StringDtype`` (:issue:`60663`)
40+
- Improved ``repr`` of :class:`.NumpyExtensionArray` to account for NEP51 (:issue:`61085`)
4041
- The :meth:`Series.str.decode` has gained the argument ``dtype`` to control the dtype of the result (:issue:`60940`)
4142
- The :meth:`~Series.cumsum`, :meth:`~Series.cummin`, and :meth:`~Series.cummax` reductions are now implemented for ``StringDtype`` columns (:issue:`60633`)
4243
- The :meth:`~Series.sum` reduction is now implemented for ``StringDtype`` columns (:issue:`59853`)

pandas/core/arrays/numpy_.py

+12
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
from typing import (
44
TYPE_CHECKING,
5+
Any,
56
Literal,
67
)
78

@@ -29,6 +30,8 @@
2930
from pandas.core.strings.object_array import ObjectStringArrayMixin
3031

3132
if TYPE_CHECKING:
33+
from collections.abc import Callable
34+
3235
from pandas._typing import (
3336
AxisInt,
3437
Dtype,
@@ -560,3 +563,12 @@ def _wrap_ndarray_result(self, result: np.ndarray):
560563

561564
return TimedeltaArray._simple_new(result, dtype=result.dtype)
562565
return type(self)(result)
566+
567+
def _formatter(self, boxed: bool = False) -> Callable[[Any], str | None]:
568+
# NEP 51: https://github.com/numpy/numpy/pull/22449
569+
if self.dtype.kind in "SU":
570+
return "'{}'".format
571+
elif self.dtype == "object":
572+
return repr
573+
else:
574+
return str

pandas/tests/arrays/numpy_/test_numpy.py

+29-2
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,15 @@
2121
np.array([True, False], dtype=bool),
2222
np.array([0, 1], dtype="datetime64[ns]"),
2323
np.array([0, 1], dtype="timedelta64[ns]"),
24-
]
24+
],
2525
)
2626
def any_numpy_array(request):
2727
"""
2828
Parametrized fixture for NumPy arrays with different dtypes.
2929
3030
This excludes string and bytes.
3131
"""
32-
return request.param
32+
return request.param.copy()
3333

3434

3535
# ----------------------------------------------------------------------------
@@ -322,3 +322,30 @@ def test_factorize_unsigned():
322322
tm.assert_numpy_array_equal(res_codes, exp_codes)
323323

324324
tm.assert_extension_array_equal(res_unique, NumpyExtensionArray(exp_unique))
325+
326+
327+
# ----------------------------------------------------------------------------
328+
# Output formatting
329+
330+
331+
def test_array_repr(any_numpy_array):
332+
# GH#61085
333+
nparray = any_numpy_array
334+
arr = NumpyExtensionArray(nparray)
335+
if nparray.dtype == "object":
336+
values = "['a', 'b']"
337+
elif nparray.dtype == "float64":
338+
values = "[0.0, 1.0]"
339+
elif str(nparray.dtype).startswith("int"):
340+
values = "[0, 1]"
341+
elif nparray.dtype == "complex128":
342+
values = "[0j, (1+2j)]"
343+
elif nparray.dtype == "bool":
344+
values = "[True, False]"
345+
elif nparray.dtype == "datetime64[ns]":
346+
values = "[1970-01-01T00:00:00.000000000, 1970-01-01T00:00:00.000000001]"
347+
elif nparray.dtype == "timedelta64[ns]":
348+
values = "[0 nanoseconds, 1 nanoseconds]"
349+
expected = f"<NumpyExtensionArray>\n{values}\nLength: 2, dtype: {nparray.dtype}"
350+
result = repr(arr)
351+
assert result == expected, f"{result} vs {expected}"

0 commit comments

Comments
 (0)