Skip to content

Commit 6d035c6

Browse files
committed
Deprecate Quantities(... copy=) kwarg. Fix warnings.
1 parent ed43021 commit 6d035c6

File tree

6 files changed

+76
-57
lines changed

6 files changed

+76
-57
lines changed

quantities/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,8 @@
265265
266266
"""
267267

268+
class QuantitiesDeprecationWarning(DeprecationWarning):
269+
pass
268270

269271
from ._version import __version__
270272

quantities/dimensionality.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
from .registry import unit_registry
1010
from .decorators import memoize
1111

12+
_np_version = tuple(map(int, np.__version__.split('.')))
13+
1214
def assert_isinstance(obj, types):
1315
try:
1416
assert isinstance(obj, types)
@@ -329,10 +331,11 @@ def _d_copy(q1, out=None):
329331

330332
def _d_clip(a1, a2, a3, q):
331333
return q.dimensionality
332-
try:
334+
335+
if _np_version < (2, 0, 0):
333336
p_dict[np.core.umath.clip] = _d_clip
334-
except AttributeError:
335-
pass # For compatibility with Numpy < 1.17 when clip wasn't a ufunc yet
337+
else:
338+
p_dict[np.clip] = _d_clip
336339

337340
def _d_sqrt(q1, out=None):
338341
return q1._dimensionality**0.5

quantities/quantity.py

Lines changed: 31 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,11 @@
33

44
import copy
55
from functools import wraps
6+
import warnings
67

78
import numpy as np
89

9-
from . import markup
10+
from . import markup, QuantitiesDeprecationWarning
1011
from .dimensionality import Dimensionality, p_dict
1112
from .registry import unit_registry
1213
from .decorators import with_doc
@@ -114,7 +115,11 @@ class Quantity(np.ndarray):
114115
# TODO: what is an appropriate value?
115116
__array_priority__ = 21
116117

117-
def __new__(cls, data, units='', dtype=None, copy=True):
118+
def __new__(cls, data, units='', dtype=None, copy=None):
119+
if copy is not None:
120+
warnings.warn(("The 'copy' argument in Quantity is deprecated and will be removed in the future. "
121+
"The argument has no effect since quantities-0.16.0 (to aid numpy-2.0 support)."),
122+
QuantitiesDeprecationWarning, stacklevel=2)
118123
if isinstance(data, Quantity):
119124
if units:
120125
data = data.rescale(units)
@@ -285,11 +290,12 @@ def __array_prepare__(self, obj, context=None):
285290
)
286291
return res
287292

288-
def __array_wrap__(self, obj, context=None):
293+
def __array_wrap__(self, obj, context=None, return_scalar=False):
289294
if not isinstance(obj, Quantity):
290295
# backwards compatibility with numpy-1.3
291-
obj = self.__array_prepare__(obj, context)
292-
return obj
296+
return self.__array_prepare__(obj, context)
297+
else:
298+
return super().__array_wrap__(obj, context, return_scalar)
293299

294300
@with_doc(np.ndarray.__add__)
295301
@scale_other_units
@@ -478,7 +484,7 @@ def sum(self, axis=None, dtype=None, out=None):
478484
ret = self.magnitude.sum(axis, dtype, None if out is None else out.magnitude)
479485
dim = self.dimensionality
480486
if out is None:
481-
return Quantity(ret, dim, copy=False)
487+
return Quantity(ret, dim)
482488
if not isinstance(out, Quantity):
483489
raise TypeError("out parameter must be a Quantity")
484490
out._dimensionality = dim
@@ -489,8 +495,7 @@ def nansum(self, axis=None, dtype=None, out=None):
489495
import numpy as np
490496
return Quantity(
491497
np.nansum(self.magnitude, axis, dtype, out),
492-
self.dimensionality,
493-
copy=False
498+
self.dimensionality
494499
)
495500

496501
@with_doc(np.ndarray.fill)
@@ -525,7 +530,7 @@ def argsort(self, axis=-1, kind='quick', order=None):
525530
@with_doc(np.ndarray.searchsorted)
526531
def searchsorted(self,values, side='left'):
527532
if not isinstance (values, Quantity):
528-
values = Quantity(values, copy=False)
533+
values = Quantity(values)
529534

530535
if values._dimensionality != self._dimensionality:
531536
raise ValueError("values does not have the same units as self")
@@ -541,7 +546,7 @@ def max(self, axis=None, out=None):
541546
ret = self.magnitude.max(axis, None if out is None else out.magnitude)
542547
dim = self.dimensionality
543548
if out is None:
544-
return Quantity(ret, dim, copy=False)
549+
return Quantity(ret, dim)
545550
if not isinstance(out, Quantity):
546551
raise TypeError("out parameter must be a Quantity")
547552
out._dimensionality = dim
@@ -555,16 +560,15 @@ def argmax(self, axis=None, out=None):
555560
def nanmax(self, axis=None, out=None):
556561
return Quantity(
557562
np.nanmax(self.magnitude),
558-
self.dimensionality,
559-
copy=False
563+
self.dimensionality
560564
)
561565

562566
@with_doc(np.ndarray.min)
563567
def min(self, axis=None, out=None):
564568
ret = self.magnitude.min(axis, None if out is None else out.magnitude)
565569
dim = self.dimensionality
566570
if out is None:
567-
return Quantity(ret, dim, copy=False)
571+
return Quantity(ret, dim)
568572
if not isinstance(out, Quantity):
569573
raise TypeError("out parameter must be a Quantity")
570574
out._dimensionality = dim
@@ -574,8 +578,7 @@ def min(self, axis=None, out=None):
574578
def nanmin(self, axis=None, out=None):
575579
return Quantity(
576580
np.nanmin(self.magnitude),
577-
self.dimensionality,
578-
copy=False
581+
self.dimensionality
579582
)
580583

581584
@with_doc(np.ndarray.argmin)
@@ -595,7 +598,7 @@ def ptp(self, axis=None, out=None):
595598
ret = np.ptp(self.magnitude, axis, None if out is None else out.magnitude)
596599
dim = self.dimensionality
597600
if out is None:
598-
return Quantity(ret, dim, copy=False)
601+
return Quantity(ret, dim)
599602
if not isinstance(out, Quantity):
600603
raise TypeError("out parameter must be a Quantity")
601604
out._dimensionality = dim
@@ -622,7 +625,7 @@ def clip(self, min=None, max=None, out=None):
622625
)
623626
dim = self.dimensionality
624627
if out is None:
625-
return Quantity(clipped, dim, copy=False)
628+
return Quantity(clipped, dim)
626629
if not isinstance(out, Quantity):
627630
raise TypeError("out parameter must be a Quantity")
628631
out._dimensionality = dim
@@ -633,7 +636,7 @@ def round(self, decimals=0, out=None):
633636
ret = self.magnitude.round(decimals, None if out is None else out.magnitude)
634637
dim = self.dimensionality
635638
if out is None:
636-
return Quantity(ret, dim, copy=False)
639+
return Quantity(ret, dim)
637640
if not isinstance(out, Quantity):
638641
raise TypeError("out parameter must be a Quantity")
639642
out._dimensionality = dim
@@ -644,7 +647,7 @@ def trace(self, offset=0, axis1=0, axis2=1, dtype=None, out=None):
644647
ret = self.magnitude.trace(offset, axis1, axis2, dtype, None if out is None else out.magnitude)
645648
dim = self.dimensionality
646649
if out is None:
647-
return Quantity(ret, dim, copy=False)
650+
return Quantity(ret, dim)
648651
if not isinstance(out, Quantity):
649652
raise TypeError("out parameter must be a Quantity")
650653
out._dimensionality = dim
@@ -654,16 +657,15 @@ def trace(self, offset=0, axis1=0, axis2=1, dtype=None, out=None):
654657
def squeeze(self, axis=None):
655658
return Quantity(
656659
self.magnitude.squeeze(axis),
657-
self.dimensionality,
658-
copy=False
660+
self.dimensionality
659661
)
660662

661663
@with_doc(np.ndarray.mean)
662664
def mean(self, axis=None, dtype=None, out=None):
663665
ret = self.magnitude.mean(axis, dtype, None if out is None else out.magnitude)
664666
dim = self.dimensionality
665667
if out is None:
666-
return Quantity(ret, dim, copy=False)
668+
return Quantity(ret, dim)
667669
if not isinstance(out, Quantity):
668670
raise TypeError("out parameter must be a Quantity")
669671
out._dimensionality = dim
@@ -674,15 +676,14 @@ def nanmean(self, axis=None, dtype=None, out=None):
674676
import numpy as np
675677
return Quantity(
676678
np.nanmean(self.magnitude, axis, dtype, out),
677-
self.dimensionality,
678-
copy=False)
679+
self.dimensionality)
679680

680681
@with_doc(np.ndarray.var)
681682
def var(self, axis=None, dtype=None, out=None, ddof=0):
682683
ret = self.magnitude.var(axis, dtype, out, ddof)
683684
dim = self._dimensionality**2
684685
if out is None:
685-
return Quantity(ret, dim, copy=False)
686+
return Quantity(ret, dim)
686687
if not isinstance(out, Quantity):
687688
raise TypeError("out parameter must be a Quantity")
688689
out._dimensionality = dim
@@ -693,7 +694,7 @@ def std(self, axis=None, dtype=None, out=None, ddof=0):
693694
ret = self.magnitude.std(axis, dtype, out, ddof)
694695
dim = self.dimensionality
695696
if out is None:
696-
return Quantity(ret, dim, copy=False)
697+
return Quantity(ret, dim)
697698
if not isinstance(out, Quantity):
698699
raise TypeError("out parameter must be a Quantity")
699700
out._dimensionality = dim
@@ -703,8 +704,7 @@ def std(self, axis=None, dtype=None, out=None, ddof=0):
703704
def nanstd(self, axis=None, dtype=None, out=None, ddof=0):
704705
return Quantity(
705706
np.nanstd(self.magnitude, axis, dtype, out, ddof),
706-
self._dimensionality,
707-
copy=False
707+
self._dimensionality
708708
)
709709

710710
@with_doc(np.ndarray.prod)
@@ -717,7 +717,7 @@ def prod(self, axis=None, dtype=None, out=None):
717717
ret = self.magnitude.prod(axis, dtype, None if out is None else out.magnitude)
718718
dim = self._dimensionality**power
719719
if out is None:
720-
return Quantity(ret, dim, copy=False)
720+
return Quantity(ret, dim)
721721
if not isinstance(out, Quantity):
722722
raise TypeError("out parameter must be a Quantity")
723723
out._dimensionality = dim
@@ -728,7 +728,7 @@ def cumsum(self, axis=None, dtype=None, out=None):
728728
ret = self.magnitude.cumsum(axis, dtype, None if out is None else out.magnitude)
729729
dim = self.dimensionality
730730
if out is None:
731-
return Quantity(ret, dim, copy=False)
731+
return Quantity(ret, dim)
732732
if not isinstance(out, Quantity):
733733
raise TypeError("out parameter must be a Quantity")
734734
out._dimensionality = dim
@@ -745,7 +745,7 @@ def cumprod(self, axis=None, dtype=None, out=None):
745745
ret = self.magnitude.cumprod(axis, dtype, out)
746746
dim = self.dimensionality
747747
if out is None:
748-
return Quantity(ret, dim, copy=False)
748+
return Quantity(ret, dim)
749749
if isinstance(out, Quantity):
750750
out._dimensionality = dim
751751
return out

quantities/tests/test_methods.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
from .. import units as pq
1+
import warnings
2+
from .. import QuantitiesDeprecationWarning, units as pq
23
from .common import TestCase
34
import numpy as np
45

@@ -119,7 +120,10 @@ def methodWithOut(self, name, result, q=None, *args, **kw):
119120
)
120121
if isinstance(result, Quantity):
121122
# deliberately using an incompatible unit
122-
out = Quantity(np.empty_like(result.magnitude), pq.s, copy=False)
123+
with warnings.catch_warnings():
124+
warnings.simplefilter("ignore", category=QuantitiesDeprecationWarning)
125+
out = Quantity(np.empty_like(result.magnitude), pq.s, copy=False)
126+
# we can drop 'copy=False' above once the deprecation of the arg has expired.
123127
else:
124128
out = np.empty_like(result)
125129
ret = getattr(q.copy(), name)(*args, out=out, **kw)

quantities/tests/test_umath.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
from .. import units as pq
44
from .common import TestCase, unittest
55

6+
_np_version = tuple(map(int, np.__version__.split('.')))
7+
68

79
class TestUmath(TestCase):
810

@@ -54,7 +56,13 @@ def test_cross(self):
5456
self.assertQuantityEqual(np.cross(a,b), [-15,-2,39]*pq.kPa*pq.m**2)
5557

5658
def test_trapz(self):
57-
self.assertQuantityEqual(np.trapz(self.q, dx = 1*pq.m), 7.5 * pq.J*pq.m)
59+
# np.trapz is deprecated, np.trapezoid is recommend
60+
if _np_version < (2, 0, 0):
61+
self.assertQuantityEqual(np.trapz(self.q, dx = 1*pq.m), 7.5 * pq.J*pq.m)
62+
63+
def test_trapezoid(self):
64+
if _np_version >= (2, 0, 0):
65+
self.assertQuantityEqual(np.trapezoid(self.q, dx = 1*pq.m), 7.5 * pq.J*pq.m)
5866

5967
def test_sinh(self):
6068
q = [1, 2, 3, 4, 6] * pq.radian

0 commit comments

Comments
 (0)