Skip to content

Commit 77058df

Browse files
BUG: Fixup __array__ copy paths based on review
A few of these were just wrong, a few others are enhancements to allow the cases that clearly should work without copy to still pass. Co-authored-by: Joris Van den Bossche <[email protected]>
1 parent 9b6c209 commit 77058df

File tree

6 files changed

+26
-15
lines changed

6 files changed

+26
-15
lines changed

pandas/core/arrays/arrow/array.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -673,7 +673,8 @@ def __array__(
673673
"Unable to avoid copy while creating an array as requested."
674674
)
675675
elif copy is None:
676-
copy = False # The NumPy copy=False meaning is different here.
676+
# `to_numpy(copy=False)` has the meaning of NumPy `copy=None`.
677+
copy = False
677678

678679
return self.to_numpy(dtype=dtype, copy=copy)
679680

pandas/core/arrays/categorical.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1697,10 +1697,8 @@ def __array__(
16971697
# we need to ensure __array__ gets all the way to an
16981698
# ndarray.
16991699

1700-
if copy is None:
1701-
# Branch required since copy=None is not defined on 1.x
1702-
return np.asarray(ret, dtype=dtype)
1703-
return np.array(ret, dtype=dtype)
1700+
# `take_nd` should already make a copy, so don't force again.
1701+
return np.asarray(ret, dtype=dtype)
17041702

17051703
def __array_ufunc__(self, ufunc: np.ufunc, method: str, *inputs, **kwargs):
17061704
# for binary ops, use our custom dunder methods

pandas/core/arrays/period.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -389,14 +389,20 @@ def freqstr(self) -> str:
389389
def __array__(
390390
self, dtype: NpDtype | None = None, copy: bool | None = None
391391
) -> np.ndarray:
392+
if dtype == "i8":
393+
# For NumPy 1.x compatibility we cannot use copy=None. And
394+
# `copy=False` has the meaning of `copy=None` here:
395+
if not copy:
396+
return np.asarray(self, dtype=dtype)
397+
else:
398+
return np.array(self, dtype=dtype)
399+
392400
if copy is False:
393401
raise ValueError(
394402
"Unable to avoid copy while creating an array as requested."
395403
)
396404

397-
if dtype == "i8":
398-
return self.asi8
399-
elif dtype == bool:
405+
if dtype == bool:
400406
return ~self._isnan
401407

402408
# This will raise TypeError for non-object dtypes

pandas/core/arrays/sparse/array.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -547,16 +547,20 @@ def from_spmatrix(cls, data: spmatrix) -> Self:
547547
def __array__(
548548
self, dtype: NpDtype | None = None, copy: bool | None = None
549549
) -> np.ndarray:
550+
if self.sp_index.ngaps == 0:
551+
# Compat for na dtype and int values.
552+
if copy is True:
553+
return np.array(self.sp_values)
554+
else:
555+
return self.sp_values
556+
550557
if copy is False:
551558
raise ValueError(
552559
"Unable to avoid copy while creating an array as requested."
553560
)
554561

555562
fill_value = self.fill_value
556563

557-
if self.sp_index.ngaps == 0:
558-
# Compat for na dtype and int values.
559-
return self.sp_values
560564
if dtype is None:
561565
# Can NumPy represent this type?
562566
# If not, `np.result_type` will raise. We catch that

pandas/core/generic.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2022,7 +2022,7 @@ def __array__(
20222022
arr = np.array(values, dtype=dtype, copy=copy)
20232023

20242024
if (
2025-
copy is not False
2025+
copy is not True
20262026
and astype_is_view(values.dtype, arr.dtype)
20272027
and self._mgr.is_single_block
20282028
):

pandas/core/indexes/multi.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1391,9 +1391,11 @@ def copy( # type: ignore[override]
13911391

13921392
def __array__(self, dtype=None, copy=None) -> np.ndarray:
13931393
"""the array interface, return my values"""
1394-
if copy is True:
1395-
# Note: branch avoids `copy=None` for NumPy 1.x support
1396-
return np.array(self.values, dtype=dtype, copy=copy)
1394+
if copy is False:
1395+
# self.values is always a newly construct array, so raise.
1396+
raise ValueError(
1397+
"Unable to avoid copy while creating an array as requested."
1398+
)
13971399
return self.values
13981400

13991401
def view(self, cls=None) -> Self:

0 commit comments

Comments
 (0)