Skip to content

Commit 8caf2b8

Browse files
committed
Explicitly defined class methods override injected methods
If a method (such as 'argmin') has been explicitly defined on a class (so that hasattr(cls, "argmin")==True), then do not inject that method, as it would override the explicitly defined one. Instead inject a private method, prefixed by "_injected_" (such as '_injected_argmin'), so that the injected method is available to the explicitly defined one. Do not perform the hasattr check on binary ops, because this breaks some operations (e.g. addition between DataArray and int in test_dask.py).
1 parent f8952a8 commit 8caf2b8

File tree

2 files changed

+30
-1
lines changed

2 files changed

+30
-1
lines changed

doc/api-hidden.rst

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
Dataset.any
1919
Dataset.argmax
2020
Dataset.argmin
21+
Dataset._injected_argmax
22+
Dataset._injected_argmin
2123
Dataset.max
2224
Dataset.min
2325
Dataset.mean
@@ -94,6 +96,8 @@
9496
core.resample.DatasetResample.ffill
9597
core.resample.DatasetResample.fillna
9698
core.resample.DatasetResample.first
99+
core.resample.DatasetResample._injected_argmax
100+
core.resample.DatasetResample._injected_argmin
97101
core.resample.DatasetResample.last
98102
core.resample.DatasetResample.map
99103
core.resample.DatasetResample.max
@@ -160,6 +164,8 @@
160164
DataArray.any
161165
DataArray.argmax
162166
DataArray.argmin
167+
DataArray._injected_argmax
168+
DataArray._injected_argmin
163169
DataArray.max
164170
DataArray.min
165171
DataArray.mean
@@ -234,6 +240,8 @@
234240
core.resample.DataArrayResample.ffill
235241
core.resample.DataArrayResample.fillna
236242
core.resample.DataArrayResample.first
243+
core.resample.DataArrayResample._injected_argmax
244+
core.resample.DataArrayResample._injected_argmin
237245
core.resample.DataArrayResample.last
238246
core.resample.DataArrayResample.map
239247
core.resample.DataArrayResample.max
@@ -369,6 +377,8 @@
369377
Variable.fillna
370378
Variable.get_axis_num
371379
Variable.identical
380+
Variable._injected_argmax
381+
Variable._injected_argmin
372382
Variable.isel
373383
Variable.isnull
374384
Variable.item
@@ -442,6 +452,8 @@
442452
IndexVariable.get_axis_num
443453
IndexVariable.get_level_variable
444454
IndexVariable.identical
455+
IndexVariable._injected_argmax
456+
IndexVariable._injected_argmin
445457
IndexVariable.isel
446458
IndexVariable.isnull
447459
IndexVariable.item

xarray/core/ops.py

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,9 @@ def inject_reduce_methods(cls):
260260
+ [("count", duck_array_ops.count, False)]
261261
)
262262
for name, f, include_skipna in methods:
263+
if hasattr(cls, name):
264+
name = "_injected_" + name
265+
263266
numeric_only = getattr(f, "numeric_only", False)
264267
available_min_count = getattr(f, "available_min_count", False)
265268
min_count_docs = _MINCOUNT_DOCSTRING if available_min_count else ""
@@ -278,6 +281,9 @@ def inject_reduce_methods(cls):
278281
def inject_cum_methods(cls):
279282
methods = [(name, getattr(duck_array_ops, name), True) for name in NAN_CUM_METHODS]
280283
for name, f, include_skipna in methods:
284+
if hasattr(cls, name):
285+
name = "_injected_" + name
286+
281287
numeric_only = getattr(f, "numeric_only", False)
282288
func = cls._reduce_method(f, include_skipna, numeric_only)
283289
func.__name__ = name
@@ -325,24 +331,35 @@ def inject_all_ops_and_reduce_methods(cls, priority=50, array_only=True):
325331

326332
# patch in standard special operations
327333
for name in UNARY_OPS:
334+
if hasattr(cls, op_str(name)):
335+
name = "_injected_" + name
328336
setattr(cls, op_str(name), cls._unary_op(get_op(name)))
329337
inject_binary_ops(cls, inplace=True)
330338

331339
# patch in numpy/pandas methods
332340
for name in NUMPY_UNARY_METHODS:
341+
if hasattr(cls, op_str(name)):
342+
name = "_injected_" + name
333343
setattr(cls, name, cls._unary_op(_method_wrapper(name)))
334344

335345
for name in PANDAS_UNARY_FUNCTIONS:
336346
f = _func_slash_method_wrapper(getattr(duck_array_ops, name), name=name)
347+
if hasattr(cls, op_str(name)):
348+
name = "_injected_" + name
337349
setattr(cls, name, cls._unary_op(f))
338350

339351
f = _func_slash_method_wrapper(duck_array_ops.around, name="round")
340-
setattr(cls, "round", cls._unary_op(f))
352+
if hasattr(cls, "round"):
353+
setattr(cls, "_injected_round", cls._unary_op(f))
354+
else:
355+
setattr(cls, "round", cls._unary_op(f))
341356

342357
if array_only:
343358
# these methods don't return arrays of the same shape as the input, so
344359
# don't try to patch these in for Dataset objects
345360
for name in NUMPY_SAME_METHODS:
361+
if hasattr(cls, op_str(name)):
362+
name = "_injected_" + name
346363
setattr(cls, name, _values_method_wrapper(name))
347364

348365
inject_reduce_methods(cls)

0 commit comments

Comments
 (0)