Skip to content

Commit 3c93d06

Browse files
authored
DEPS: Update NumpyExtensionArray repr for NEP51 (#61085)
* DEPS: Update NumpyExtensionArray repr for NEP51 * Cleanup * GH# * Debug * Fix fixture * Fixups * whatsnew
1 parent cdc9e95 commit 3c93d06

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 work correctly with NumPy >= 2 (:issue:`57739`)
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,
@@ -565,3 +568,12 @@ def _wrap_ndarray_result(self, result: np.ndarray):
565568

566569
return TimedeltaArray._simple_new(result, dtype=result.dtype)
567570
return type(self)(result)
571+
572+
def _formatter(self, boxed: bool = False) -> Callable[[Any], str | None]:
573+
# NEP 51: https://github.com/numpy/numpy/pull/22449
574+
if self.dtype.kind in "SU":
575+
return "'{}'".format
576+
elif self.dtype == "object":
577+
return repr
578+
else:
579+
return str

pandas/tests/arrays/numpy_/test_numpy.py

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

3535

3636
# ----------------------------------------------------------------------------
@@ -323,3 +323,30 @@ def test_factorize_unsigned():
323323
tm.assert_numpy_array_equal(res_codes, exp_codes)
324324

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

0 commit comments

Comments
 (0)