Skip to content

Commit 6d4fded

Browse files
committed
Fix
1 parent 99ae64f commit 6d4fded

File tree

2 files changed

+14
-2
lines changed

2 files changed

+14
-2
lines changed

xarray/core/extension_array.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,4 +144,11 @@ def __array__(
144144
return np.asarray(self.array, dtype=dtype)
145145

146146
def __getattr__(self, attr: str) -> Any:
147-
return getattr(self.array, attr)
147+
# without __deepcopy__ or __copy__, the object is first constructed and then the sub-objects are attached:
148+
# "A shallow copy constructs a new compound object and then (to the extent possible) inserts references into it to the objects found in the original" +
149+
# "A deep copy constructs a new compound object and then, recursively, inserts copies into it of the objects found in the original."
150+
# So without array, this method then calls getattr for "array" again while looking for __setstate__
151+
# (which is apparently the first thing sought in copy.copy from the under-construction copied object)
152+
# because of self.array. __getattribute__ bypasses the lookup mechanism of __getattr__.
153+
# See stackoverflow.com/questions/40583131/python-deepcopy-with-custom-getattr-and-setattr as well.
154+
return getattr(super().__getattribute__("array"), attr)

xarray/tests/test_duck_array_ops.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from __future__ import annotations
22

33
import datetime as dt
4+
import pickle
45
import warnings
56

67
import numpy as np
@@ -1098,4 +1099,8 @@ def test_extension_array_repr(int1):
10981099

10991100
def test_extension_array_attr():
11001101
array = pd.Categorical(["cat2", "cat1", "cat2", "cat3", "cat1"])
1101-
assert (array.categories == PandasExtensionArray(array).categories).all()
1102+
wrapped = PandasExtensionArray(array)
1103+
assert (array.categories == wrapped.categories).all()
1104+
assert array.nbytes == wrapped.nbytes
1105+
1106+
assert (pickle.loads(pickle.dumps(wrapped)) == wrapped).all()

0 commit comments

Comments
 (0)