summaryrefslogtreecommitdiff
path: root/numpy
diff options
context:
space:
mode:
Diffstat (limited to 'numpy')
-rw-r--r--numpy/core/src/npymath/npy_math_complex.c.src9
-rw-r--r--numpy/core/src/npysort/quicksort.c.src12
-rw-r--r--numpy/core/tests/test_api.py23
-rw-r--r--numpy/core/tests/test_indexing.py31
-rw-r--r--numpy/core/tests/test_item_selection.py8
-rw-r--r--numpy/core/tests/test_multiarray.py96
-rw-r--r--numpy/core/tests/test_nditer.py30
-rw-r--r--numpy/core/tests/test_numeric.py3
-rw-r--r--numpy/core/tests/test_regression.py15
-rw-r--r--numpy/core/tests/test_scalarmath.py20
-rw-r--r--numpy/doc/subclassing.py47
-rw-r--r--numpy/lib/tests/test_function_base.py4
-rw-r--r--numpy/lib/tests/test_io.py3
-rw-r--r--numpy/ma/core.py3
-rw-r--r--numpy/testing/utils.py7
15 files changed, 214 insertions, 97 deletions
diff --git a/numpy/core/src/npymath/npy_math_complex.c.src b/numpy/core/src/npymath/npy_math_complex.c.src
index c4867e28d..a50059615 100644
--- a/numpy/core/src/npymath/npy_math_complex.c.src
+++ b/numpy/core/src/npymath/npy_math_complex.c.src
@@ -1565,6 +1565,7 @@ _real_part_reciprocalf(npy_float x, npy_float y)
#undef BIAS
#undef CUTOFF
#endif
+
#if @precision@ == 2
#define BIAS (DBL_MAX_EXP - 1)
/* more guard digits are useful iff there is extra precision. */
@@ -1604,8 +1605,11 @@ _real_part_reciprocal(npy_double x, npy_double y)
#undef BIAS
#undef CUTOFF
#endif
+
#if @precision@ == 3
-#ifndef HAVE_LDOUBLE_DOUBLE_DOUBLE_BE
+#if !defined(HAVE_LDOUBLE_DOUBLE_DOUBLE_BE) && \
+ !defined(HAVE_LDOUBLE_DOUBLE_DOUBLE_LE)
+
#define BIAS (LDBL_MAX_EXP - 1)
#define CUTOFF (LDBL_MANT_DIG / 2 + 1)
static NPY_INLINE npy_longdouble
@@ -1638,13 +1642,16 @@ _real_part_reciprocall(npy_longdouble x,
}
#undef BIAS
#undef CUTOFF
+
#else
+
static NPY_INLINE npy_longdouble
_real_part_reciprocall(npy_longdouble x,
npy_longdouble y)
{
return x/(x*x + y*y);
}
+
#endif
#endif
diff --git a/numpy/core/src/npysort/quicksort.c.src b/numpy/core/src/npysort/quicksort.c.src
index 0ea9d21c7..2b6e2ed1c 100644
--- a/numpy/core/src/npysort/quicksort.c.src
+++ b/numpy/core/src/npysort/quicksort.c.src
@@ -464,13 +464,17 @@ npy_quicksort(void *start, npy_intp num, void *varr)
pi = pl;
pj = pr - elsize;
GENERIC_SWAP(pm, pj, elsize);
+ /*
+ * Generic comparisons may be buggy, so don't rely on the sentinals
+ * to keep the pointers from going out of bounds.
+ */
for (;;) {
do {
pi += elsize;
- } while (cmp(pi, vp, arr) < 0);
+ } while (cmp(pi, vp, arr) < 0 && pi < pj);
do {
pj -= elsize;
- } while (cmp(vp, pj, arr) < 0);
+ } while (cmp(vp, pj, arr) < 0 && pi < pj);
if (pi >= pj) {
break;
}
@@ -559,10 +563,10 @@ npy_aquicksort(void *vv, npy_intp* tosort, npy_intp num, void *varr)
for (;;) {
do {
++pi;
- } while (cmp(v + (*pi)*elsize, vp, arr) < 0);
+ } while (cmp(v + (*pi)*elsize, vp, arr) < 0 && pi < pj);
do {
--pj;
- } while (cmp(vp, v + (*pj)*elsize, arr) < 0);
+ } while (cmp(vp, v + (*pj)*elsize, arr) < 0 && pi < pj);
if (pi >= pj) {
break;
}
diff --git a/numpy/core/tests/test_api.py b/numpy/core/tests/test_api.py
index 08bc6f947..7b04841bb 100644
--- a/numpy/core/tests/test_api.py
+++ b/numpy/core/tests/test_api.py
@@ -6,7 +6,7 @@ import numpy as np
from numpy.compat import sixu
from numpy.testing import (
run_module_suite, assert_, assert_equal, assert_array_equal,
- assert_raises
+ assert_raises, HAS_REFCOUNT
)
# Switch between new behaviour when NPY_RELAXED_STRIDES_CHECKING is set.
@@ -19,23 +19,26 @@ def test_array_array():
tndarray = type(ones11)
# Test is_ndarray
assert_equal(np.array(ones11, dtype=np.float64), ones11)
- old_refcount = sys.getrefcount(tndarray)
- np.array(ones11)
- assert_equal(old_refcount, sys.getrefcount(tndarray))
+ if HAS_REFCOUNT:
+ old_refcount = sys.getrefcount(tndarray)
+ np.array(ones11)
+ assert_equal(old_refcount, sys.getrefcount(tndarray))
# test None
assert_equal(np.array(None, dtype=np.float64),
np.array(np.nan, dtype=np.float64))
- old_refcount = sys.getrefcount(tobj)
- np.array(None, dtype=np.float64)
- assert_equal(old_refcount, sys.getrefcount(tobj))
+ if HAS_REFCOUNT:
+ old_refcount = sys.getrefcount(tobj)
+ np.array(None, dtype=np.float64)
+ assert_equal(old_refcount, sys.getrefcount(tobj))
# test scalar
assert_equal(np.array(1.0, dtype=np.float64),
np.ones((), dtype=np.float64))
- old_refcount = sys.getrefcount(np.float64)
- np.array(np.array(1.0, dtype=np.float64), dtype=np.float64)
- assert_equal(old_refcount, sys.getrefcount(np.float64))
+ if HAS_REFCOUNT:
+ old_refcount = sys.getrefcount(np.float64)
+ np.array(np.array(1.0, dtype=np.float64), dtype=np.float64)
+ assert_equal(old_refcount, sys.getrefcount(np.float64))
# test string
S2 = np.dtype((str, 2))
diff --git a/numpy/core/tests/test_indexing.py b/numpy/core/tests/test_indexing.py
index 49231f37e..dcce2c300 100644
--- a/numpy/core/tests/test_indexing.py
+++ b/numpy/core/tests/test_indexing.py
@@ -10,7 +10,7 @@ from numpy.core.multiarray_tests import array_indexing
from itertools import product
from numpy.testing import (
TestCase, run_module_suite, assert_, assert_equal, assert_raises,
- assert_array_equal, assert_warns
+ assert_array_equal, assert_warns, HAS_REFCOUNT
)
@@ -411,7 +411,8 @@ class TestIndexing(TestCase):
def test_small_regressions(self):
# Reference count of intp for index checks
a = np.array([0])
- refcount = sys.getrefcount(np.dtype(np.intp))
+ if HAS_REFCOUNT:
+ refcount = sys.getrefcount(np.dtype(np.intp))
# item setting always checks indices in separate function:
a[np.array([0], dtype=np.intp)] = 1
a[np.array([0], dtype=np.uint8)] = 1
@@ -420,7 +421,8 @@ class TestIndexing(TestCase):
assert_raises(IndexError, a.__setitem__,
np.array([1], dtype=np.uint8), 1)
- assert_equal(sys.getrefcount(np.dtype(np.intp)), refcount)
+ if HAS_REFCOUNT:
+ assert_equal(sys.getrefcount(np.dtype(np.intp)), refcount)
def test_unaligned(self):
v = (np.zeros(64, dtype=np.int8) + ord('a'))[1:-7]
@@ -972,10 +974,12 @@ class TestMultiIndexingAutomated(TestCase):
try:
mimic_get, no_copy = self._get_multi_index(arr, index)
except Exception:
- prev_refcount = sys.getrefcount(arr)
+ if HAS_REFCOUNT:
+ prev_refcount = sys.getrefcount(arr)
assert_raises(Exception, arr.__getitem__, index)
assert_raises(Exception, arr.__setitem__, index, 0)
- assert_equal(prev_refcount, sys.getrefcount(arr))
+ if HAS_REFCOUNT:
+ assert_equal(prev_refcount, sys.getrefcount(arr))
return
self._compare_index_result(arr, index, mimic_get, no_copy)
@@ -994,10 +998,12 @@ class TestMultiIndexingAutomated(TestCase):
try:
mimic_get, no_copy = self._get_multi_index(arr, (index,))
except Exception:
- prev_refcount = sys.getrefcount(arr)
+ if HAS_REFCOUNT:
+ prev_refcount = sys.getrefcount(arr)
assert_raises(Exception, arr.__getitem__, index)
assert_raises(Exception, arr.__setitem__, index, 0)
- assert_equal(prev_refcount, sys.getrefcount(arr))
+ if HAS_REFCOUNT:
+ assert_equal(prev_refcount, sys.getrefcount(arr))
return
self._compare_index_result(arr, index, mimic_get, no_copy)
@@ -1013,11 +1019,12 @@ class TestMultiIndexingAutomated(TestCase):
if indexed_arr.size != 0 and indexed_arr.ndim != 0:
assert_(np.may_share_memory(indexed_arr, arr) == no_copy)
# Check reference count of the original array
- if no_copy:
- # refcount increases by one:
- assert_equal(sys.getrefcount(arr), 3)
- else:
- assert_equal(sys.getrefcount(arr), 2)
+ if HAS_REFCOUNT:
+ if no_copy:
+ # refcount increases by one:
+ assert_equal(sys.getrefcount(arr), 3)
+ else:
+ assert_equal(sys.getrefcount(arr), 2)
# Test non-broadcast setitem:
b = arr.copy()
diff --git a/numpy/core/tests/test_item_selection.py b/numpy/core/tests/test_item_selection.py
index ddce20fe9..1eb09f1e0 100644
--- a/numpy/core/tests/test_item_selection.py
+++ b/numpy/core/tests/test_item_selection.py
@@ -5,7 +5,7 @@ import sys
import numpy as np
from numpy.testing import (
TestCase, run_module_suite, assert_, assert_raises,
- assert_array_equal
+ assert_array_equal, HAS_REFCOUNT
)
@@ -55,12 +55,14 @@ class TestTake(TestCase):
b = np.array([2, 2, 4, 5, 3, 5])
a.take(b, out=a[:6])
del a
- assert_(all(sys.getrefcount(o) == 3 for o in objects))
+ if HAS_REFCOUNT:
+ assert_(all(sys.getrefcount(o) == 3 for o in objects))
# not contiguous, example:
a = np.array(objects * 2)[::2]
a.take(b, out=a[:6])
del a
- assert_(all(sys.getrefcount(o) == 3 for o in objects))
+ if HAS_REFCOUNT:
+ assert_(all(sys.getrefcount(o) == 3 for o in objects))
def test_unicode_mode(self):
d = np.arange(10)
diff --git a/numpy/core/tests/test_multiarray.py b/numpy/core/tests/test_multiarray.py
index 9446f0ac2..977378cfa 100644
--- a/numpy/core/tests/test_multiarray.py
+++ b/numpy/core/tests/test_multiarray.py
@@ -28,7 +28,7 @@ from numpy.core.multiarray_tests import (
from numpy.testing import (
TestCase, run_module_suite, assert_, assert_raises,
assert_equal, assert_almost_equal, assert_array_equal,
- assert_array_almost_equal, assert_allclose,
+ assert_array_almost_equal, assert_allclose, IS_PYPY, HAS_REFCOUNT,
assert_array_less, runstring, dec, SkipTest, temppath
)
@@ -1349,6 +1349,17 @@ class TestMethods(TestCase):
msg = 'test empty array sort with axis=None'
assert_equal(np.sort(a, axis=None), a.ravel(), msg)
+ # test generic class with bogus ordering,
+ # should not segfault.
+ class Boom(object):
+ def __lt__(self, other):
+ return True
+
+ a = np.array([Boom()]*100, dtype=object)
+ for kind in ['q', 'm', 'h']:
+ msg = "bogus comparison object sort, kind=%s" % kind
+ c.sort(kind=kind)
+
def test_sort_degraded(self):
# test degraded dataset would take minutes to run with normal qsort
d = np.arange(1000000)
@@ -2326,10 +2337,12 @@ class TestMethods(TestCase):
def test_diagonal_memleak(self):
# Regression test for a bug that crept in at one point
a = np.zeros((100, 100))
- assert_(sys.getrefcount(a) < 50)
+ if HAS_REFCOUNT:
+ assert_(sys.getrefcount(a) < 50)
for i in range(100):
a.diagonal()
- assert_(sys.getrefcount(a) < 50)
+ if HAS_REFCOUNT:
+ assert_(sys.getrefcount(a) < 50)
def test_trace(self):
a = np.arange(12).reshape((3, 4))
@@ -4723,7 +4736,8 @@ class TestDot(TestCase):
r = np.empty((1024, 32))
for i in range(12):
dot(f, v, r)
- assert_equal(sys.getrefcount(r), 2)
+ if HAS_REFCOUNT:
+ assert_equal(sys.getrefcount(r), 2)
r2 = dot(f, v, out=None)
assert_array_equal(r2, r)
assert_(r is dot(f, v, out=r))
@@ -5967,11 +5981,13 @@ class TestNewBufferProtocol(object):
self._check_roundtrip(x)
def test_reference_leak(self):
- count_1 = sys.getrefcount(np.core._internal)
+ if HAS_REFCOUNT:
+ count_1 = sys.getrefcount(np.core._internal)
a = np.zeros(4)
b = memoryview(a)
c = np.asarray(b)
- count_2 = sys.getrefcount(np.core._internal)
+ if HAS_REFCOUNT:
+ count_2 = sys.getrefcount(np.core._internal)
assert_equal(count_1, count_2)
del c # avoid pyflakes unused variable warning.
@@ -6355,50 +6371,52 @@ class TestWhere(TestCase):
assert_equal(np.where(False, b, a), "abcd")
-class TestSizeOf(TestCase):
+if not IS_PYPY:
+ # sys.getsizeof() is not valid on PyPy
+ class TestSizeOf(TestCase):
- def test_empty_array(self):
- x = np.array([])
- assert_(sys.getsizeof(x) > 0)
+ def test_empty_array(self):
+ x = np.array([])
+ assert_(sys.getsizeof(x) > 0)
- def check_array(self, dtype):
- elem_size = dtype(0).itemsize
+ def check_array(self, dtype):
+ elem_size = dtype(0).itemsize
- for length in [10, 50, 100, 500]:
- x = np.arange(length, dtype=dtype)
- assert_(sys.getsizeof(x) > length * elem_size)
+ for length in [10, 50, 100, 500]:
+ x = np.arange(length, dtype=dtype)
+ assert_(sys.getsizeof(x) > length * elem_size)
- def test_array_int32(self):
- self.check_array(np.int32)
+ def test_array_int32(self):
+ self.check_array(np.int32)
- def test_array_int64(self):
- self.check_array(np.int64)
+ def test_array_int64(self):
+ self.check_array(np.int64)
- def test_array_float32(self):
- self.check_array(np.float32)
+ def test_array_float32(self):
+ self.check_array(np.float32)
- def test_array_float64(self):
- self.check_array(np.float64)
+ def test_array_float64(self):
+ self.check_array(np.float64)
- def test_view(self):
- d = np.ones(100)
- assert_(sys.getsizeof(d[...]) < sys.getsizeof(d))
+ def test_view(self):
+ d = np.ones(100)
+ assert_(sys.getsizeof(d[...]) < sys.getsizeof(d))
- def test_reshape(self):
- d = np.ones(100)
- assert_(sys.getsizeof(d) < sys.getsizeof(d.reshape(100, 1, 1).copy()))
+ def test_reshape(self):
+ d = np.ones(100)
+ assert_(sys.getsizeof(d) < sys.getsizeof(d.reshape(100, 1, 1).copy()))
- def test_resize(self):
- d = np.ones(100)
- old = sys.getsizeof(d)
- d.resize(50)
- assert_(old > sys.getsizeof(d))
- d.resize(150)
- assert_(old < sys.getsizeof(d))
+ def test_resize(self):
+ d = np.ones(100)
+ old = sys.getsizeof(d)
+ d.resize(50)
+ assert_(old > sys.getsizeof(d))
+ d.resize(150)
+ assert_(old < sys.getsizeof(d))
- def test_error(self):
- d = np.ones(100)
- assert_raises(TypeError, d.__sizeof__, "a")
+ def test_error(self):
+ d = np.ones(100)
+ assert_raises(TypeError, d.__sizeof__, "a")
class TestHashing(TestCase):
diff --git a/numpy/core/tests/test_nditer.py b/numpy/core/tests/test_nditer.py
index ed0197991..f83d81624 100644
--- a/numpy/core/tests/test_nditer.py
+++ b/numpy/core/tests/test_nditer.py
@@ -9,7 +9,7 @@ from numpy.compat import asbytes, sixu
from numpy.core.multiarray_tests import test_nditer_too_large
from numpy.testing import (
run_module_suite, assert_, assert_equal, assert_array_equal,
- assert_raises, dec
+ assert_raises, dec, HAS_REFCOUNT
)
@@ -34,6 +34,7 @@ def iter_iterindices(i):
i.iternext()
return ret
+@dec.skipif(not HAS_REFCOUNT, "python does not have sys.getrefcount")
def test_iter_refcount():
# Make sure the iterator doesn't leak
@@ -1000,17 +1001,20 @@ def test_iter_object_arrays_basic():
obj = {'a':3,'b':'d'}
a = np.array([[1, 2, 3], None, obj, None], dtype='O')
- rc = sys.getrefcount(obj)
+ if HAS_REFCOUNT:
+ rc = sys.getrefcount(obj)
# Need to allow references for object arrays
assert_raises(TypeError, nditer, a)
- assert_equal(sys.getrefcount(obj), rc)
+ if HAS_REFCOUNT:
+ assert_equal(sys.getrefcount(obj), rc)
i = nditer(a, ['refs_ok'], ['readonly'])
vals = [x_[()] for x_ in i]
assert_equal(np.array(vals, dtype='O'), a)
vals, i, x = [None]*3
- assert_equal(sys.getrefcount(obj), rc)
+ if HAS_REFCOUNT:
+ assert_equal(sys.getrefcount(obj), rc)
i = nditer(a.reshape(2, 2).T, ['refs_ok', 'buffered'],
['readonly'], order='C')
@@ -1018,14 +1022,16 @@ def test_iter_object_arrays_basic():
vals = [x_[()] for x_ in i]
assert_equal(np.array(vals, dtype='O'), a.reshape(2, 2).ravel(order='F'))
vals, i, x = [None]*3
- assert_equal(sys.getrefcount(obj), rc)
+ if HAS_REFCOUNT:
+ assert_equal(sys.getrefcount(obj), rc)
i = nditer(a.reshape(2, 2).T, ['refs_ok', 'buffered'],
['readwrite'], order='C')
for x in i:
x[...] = None
vals, i, x = [None]*3
- assert_equal(sys.getrefcount(obj), rc-1)
+ if HAS_REFCOUNT:
+ assert_(sys.getrefcount(obj) == rc-1)
assert_equal(a, np.array([None]*4, dtype='O'))
def test_iter_object_arrays_conversions():
@@ -1061,10 +1067,12 @@ def test_iter_object_arrays_conversions():
i = nditer(a, ['refs_ok', 'buffered'], ['readwrite'],
casting='unsafe', op_dtypes='O')
ob = i[0][()]
- rc = sys.getrefcount(ob)
+ if HAS_REFCOUNT:
+ rc = sys.getrefcount(ob)
for x in i:
x[...] += 1
- assert_equal(sys.getrefcount(ob), rc-1)
+ if HAS_REFCOUNT:
+ assert_(sys.getrefcount(ob) == rc-1)
assert_equal(a, np.arange(6)+98172489)
def test_iter_common_dtype():
@@ -1704,7 +1712,8 @@ def test_iter_buffered_cast_structured_type():
a[0] = (0.5, 0.5, [[0.5, 0.5, 0.5], [0.5, 0.5, 0.5]], 0.5)
a[1] = (1.5, 1.5, [[1.5, 1.5, 1.5], [1.5, 1.5, 1.5]], 1.5)
a[2] = (2.5, 2.5, [[2.5, 2.5, 2.5], [2.5, 2.5, 2.5]], 2.5)
- rc = sys.getrefcount(a[0])
+ if HAS_REFCOUNT:
+ rc = sys.getrefcount(a[0])
i = nditer(a, ['buffered', 'refs_ok'], ['readonly'],
casting='unsafe',
op_dtypes=sdt)
@@ -1719,7 +1728,8 @@ def test_iter_buffered_cast_structured_type():
assert_equal(vals[1]['d'], 1.5)
assert_equal(vals[0].dtype, np.dtype(sdt))
vals, i, x = [None]*3
- assert_equal(sys.getrefcount(a[0]), rc)
+ if HAS_REFCOUNT:
+ assert_equal(sys.getrefcount(a[0]), rc)
# struct type -> simple (takes the first value)
sdt = [('a', 'f4'), ('b', 'i8'), ('d', 'O')]
diff --git a/numpy/core/tests/test_numeric.py b/numpy/core/tests/test_numeric.py
index 7830c5c5a..990d13a3e 100644
--- a/numpy/core/tests/test_numeric.py
+++ b/numpy/core/tests/test_numeric.py
@@ -12,7 +12,7 @@ from numpy.random import rand, randint, randn
from numpy.testing import (
TestCase, run_module_suite, assert_, assert_equal, assert_raises,
assert_raises_regex, assert_array_equal, assert_almost_equal,
- assert_array_almost_equal, dec
+ assert_array_almost_equal, dec, HAS_REFCOUNT
)
@@ -2011,6 +2011,7 @@ class TestCreationFuncs(TestCase):
self.check_function(np.full, 0)
self.check_function(np.full, 1)
+ @dec.skipif(not HAS_REFCOUNT, "python has no sys.getrefcount")
def test_for_reference_leak(self):
# Make sure we have an object for reference
dim = 1
diff --git a/numpy/core/tests/test_regression.py b/numpy/core/tests/test_regression.py
index ace2c1814..022438ab1 100644
--- a/numpy/core/tests/test_regression.py
+++ b/numpy/core/tests/test_regression.py
@@ -17,7 +17,7 @@ from numpy.testing import (
assert_almost_equal, assert_array_equal, assert_array_almost_equal,
assert_raises, assert_warns, dec
)
-from numpy.testing.utils import _assert_valid_refcount
+from numpy.testing.utils import _assert_valid_refcount, HAS_REFCOUNT
from numpy.compat import asbytes, asunicode, asbytes_nested, long, sixu
rlevel = 1
@@ -706,12 +706,14 @@ class TestRegression(TestCase):
# Issue gh-3001
d = 123.
a = np.array([d, 1], dtype=object)
- ref_d = sys.getrefcount(d)
+ if HAS_REFCOUNT:
+ ref_d = sys.getrefcount(d)
try:
a.take([0, 100])
except IndexError:
pass
- assert_(ref_d == sys.getrefcount(d))
+ if HAS_REFCOUNT:
+ assert_(ref_d == sys.getrefcount(d))
def test_array_str_64bit(self, level=rlevel):
# Ticket #501
@@ -1458,6 +1460,7 @@ class TestRegression(TestCase):
x[x.nonzero()] = x.ravel()[:1]
assert_(x[0, 1] == x[0, 0])
+ @dec.skipif(not HAS_REFCOUNT, "python has no sys.getrefcount")
def test_structured_arrays_with_objects2(self):
# Ticket #1299 second test
stra = 'aaaa'
@@ -1572,6 +1575,7 @@ class TestRegression(TestCase):
y = np.add(x, x, x)
assert_equal(id(x), id(y))
+ @dec.skipif(not HAS_REFCOUNT, "python has no sys.getrefcount")
def test_take_refcount(self):
# ticket #939
a = np.arange(16, dtype=np.float)
@@ -1745,7 +1749,8 @@ class TestRegression(TestCase):
# causing segmentation faults (gh-3787)
a = np.array(object(), dtype=object)
np.copyto(a, a)
- assert_equal(sys.getrefcount(a[()]), 2)
+ if HAS_REFCOUNT:
+ assert_(sys.getrefcount(a[()]) == 2)
a[()].__class__ # will segfault if object was deleted
def test_zerosize_accumulate(self):
@@ -1948,6 +1953,7 @@ class TestRegression(TestCase):
a = np.empty((100000000,), dtype='i1')
del a
+ @dec.skipif(not HAS_REFCOUNT, "python has no sys.getrefcount")
def test_ufunc_reduce_memoryleak(self):
a = np.arange(6)
acnt = sys.getrefcount(a)
@@ -2152,6 +2158,7 @@ class TestRegression(TestCase):
assert_equal(uf(a), ())
assert_array_equal(a, [[3, 2, 1], [5, 4], [9, 7, 8, 6]])
+ @dec.skipif(not HAS_REFCOUNT, "python has no sys.getrefcount")
def test_leak_in_structured_dtype_comparison(self):
# gh-6250
recordtype = np.dtype([('a', np.float64),
diff --git a/numpy/core/tests/test_scalarmath.py b/numpy/core/tests/test_scalarmath.py
index b8f4388b1..1c71565f4 100644
--- a/numpy/core/tests/test_scalarmath.py
+++ b/numpy/core/tests/test_scalarmath.py
@@ -9,7 +9,7 @@ import numpy as np
from numpy.testing.utils import _gen_alignment_data
from numpy.testing import (
TestCase, run_module_suite, assert_, assert_equal, assert_raises,
- assert_almost_equal, assert_allclose, assert_array_equal
+ assert_almost_equal, assert_allclose, assert_array_equal, IS_PYPY
)
types = [np.bool_, np.byte, np.ubyte, np.short, np.ushort, np.intc, np.uintc,
@@ -454,16 +454,18 @@ class TestRepr(object):
yield self._test_type_repr, t
-class TestSizeOf(TestCase):
+if not IS_PYPY:
+ # sys.getsizeof() is not valid on PyPy
+ class TestSizeOf(TestCase):
- def test_equal_nbytes(self):
- for type in types:
- x = type(0)
- assert_(sys.getsizeof(x) > x.nbytes)
+ def test_equal_nbytes(self):
+ for type in types:
+ x = type(0)
+ assert_(sys.getsizeof(x) > x.nbytes)
- def test_error(self):
- d = np.float32()
- assert_raises(TypeError, d.__sizeof__, "a")
+ def test_error(self):
+ d = np.float32()
+ assert_raises(TypeError, d.__sizeof__, "a")
class TestMultiply(TestCase):
diff --git a/numpy/doc/subclassing.py b/numpy/doc/subclassing.py
index 1dd73d4ce..40522bb9c 100644
--- a/numpy/doc/subclassing.py
+++ b/numpy/doc/subclassing.py
@@ -555,6 +555,53 @@ the original array is deleted, but not the views. For an example of
how this can work, have a look at the ``memmap`` class in
``numpy.core``.
+Subclassing and Downstream Compatibility
+----------------------------------------
+
+When sub-classing ``ndarray`` or creating duck-types that mimic the ``ndarray``
+interface, it is your responsibility to decide how aligned your APIs will be
+with those of numpy. For convenience, many numpy functions that have a corresponding
+``ndarray`` method (e.g., ``sum``, ``mean``, ``take``, ``reshape``) work by checking
+if the first argument to a function has a method of the same name. If it exists, the
+method is called instead of coercing the arguments to a numpy array.
+
+For example, if you want your sub-class or duck-type to be compatible with
+numpy's ``sum`` function, the method signature for this object's ``sum`` method
+should be the following:
+
+.. testcode::
+
+ def sum(self, axis=None, dtype=None, out=None, keepdims=False):
+ ...
+
+This is the exact same method signature for ``np.sum``, so now if a user calls
+``np.sum`` on this object, numpy will call the object's own ``sum`` method and
+pass in these arguments enumerated above in the signature, and no errors will
+be raised because the signatures are completely compatible with each other.
+
+If, however, you decide to deviate from this signature and do something like this:
+
+.. testcode::
+
+ def sum(self, axis=None, dtype=None):
+ ...
+
+This object is no longer compatible with ``np.sum`` because if you call ``np.sum``,
+it will pass in unexpected arguments ``out`` and ``keepdims``, causing a TypeError
+to be raised.
+
+If you wish to maintain compatibility with numpy and its subsequent versions (which
+might add new keyword arguments) but do not want to surface all of numpy's arguments,
+your function's signature should accept ``**kwargs``. For example:
+
+.. testcode::
+
+ def sum(self, axis=None, dtype=None, **unused_kwargs):
+ ...
+
+This object is now compatible with ``np.sum`` again because any extraneous arguments
+(i.e. keywords that are not ``axis`` or ``dtype``) will be hidden away in the
+``**unused_kwargs`` parameter.
"""
from __future__ import division, absolute_import, print_function
diff --git a/numpy/lib/tests/test_function_base.py b/numpy/lib/tests/test_function_base.py
index c2bcc62ba..0d7b11c44 100644
--- a/numpy/lib/tests/test_function_base.py
+++ b/numpy/lib/tests/test_function_base.py
@@ -10,6 +10,7 @@ from numpy.testing import (
assert_allclose, assert_array_max_ulp, assert_warns,
assert_raises_regex, dec, clear_and_catch_warnings
)
+from numpy.testing.utils import HAS_REFCOUNT
import numpy.lib.function_base as nfb
from numpy.random import rand
from numpy.lib import (
@@ -17,7 +18,7 @@ from numpy.lib import (
delete, diff, digitize, extract, flipud, gradient, hamming, hanning,
histogram, histogramdd, i0, insert, interp, kaiser, meshgrid, msort,
piecewise, place, rot90, select, setxor1d, sinc, split, trapz, trim_zeros,
- unwrap, unique, vectorize,
+ unwrap, unique, vectorize
)
from numpy.compat import long
@@ -2232,6 +2233,7 @@ class TestBincount(TestCase):
"minlength must be positive",
lambda: np.bincount(x, minlength=0))
+ @dec.skipif(not HAS_REFCOUNT, "python has no sys.getrefcount")
def test_dtype_reference_leaks(self):
# gh-6805
intp_refcount = sys.getrefcount(np.dtype(np.intp))
diff --git a/numpy/lib/tests/test_io.py b/numpy/lib/tests/test_io.py
index de73d57f7..1474349de 100644
--- a/numpy/lib/tests/test_io.py
+++ b/numpy/lib/tests/test_io.py
@@ -19,7 +19,7 @@ from numpy.ma.testutils import assert_equal
from numpy.testing import (
TestCase, run_module_suite, assert_warns, assert_,
assert_raises_regex, assert_raises, assert_allclose,
- assert_array_equal, temppath, dec
+ assert_array_equal, temppath, dec, IS_PYPY
)
@@ -266,6 +266,7 @@ class TestSavezLoad(RoundtripTest, TestCase):
fp.seek(0)
assert_(not fp.closed)
+ @np.testing.dec.skipif(IS_PYPY, "context manager required on PyPy")
def test_closing_fid(self):
# Test that issue #1517 (too many opened files) remains closed
# It might be a "weak" test since failed to get triggered on
diff --git a/numpy/ma/core.py b/numpy/ma/core.py
index 37836a0a0..b01656ec9 100644
--- a/numpy/ma/core.py
+++ b/numpy/ma/core.py
@@ -3279,12 +3279,13 @@ class MaskedArray(ndarray):
# We want to remove the unshare logic from this place in the
# future. Note that _sharedmask has lots of false positives.
if not self._isfield:
+ notthree = getattr(sys, 'getrefcount', False) and (sys.getrefcount(_mask) != 3)
if self._sharedmask and not (
# If no one else holds a reference (we have two
# references (_mask and self._mask) -- add one for
# getrefcount) and the array owns its own data
# copying the mask should do nothing.
- (sys.getrefcount(_mask) == 3) and _mask.flags.owndata):
+ (not notthree) and _mask.flags.owndata):
# 2016.01.15 -- v1.11.0
warnings.warn(
"setting an item on a masked array which has a shared "
diff --git a/numpy/testing/utils.py b/numpy/testing/utils.py
index dc1115e1b..176d87800 100644
--- a/numpy/testing/utils.py
+++ b/numpy/testing/utils.py
@@ -32,7 +32,8 @@ __all__ = ['assert_equal', 'assert_almost_equal', 'assert_approx_equal',
'assert_', 'assert_array_almost_equal_nulp', 'assert_raises_regex',
'assert_array_max_ulp', 'assert_warns', 'assert_no_warnings',
'assert_allclose', 'IgnoreException', 'clear_and_catch_warnings',
- 'SkipTest', 'KnownFailureException', 'temppath', 'tempdir']
+ 'SkipTest', 'KnownFailureException', 'temppath', 'tempdir', 'IS_PYPY',
+ 'HAS_REFCOUNT']
class KnownFailureException(Exception):
@@ -43,6 +44,8 @@ class KnownFailureException(Exception):
KnownFailureTest = KnownFailureException # backwards compat
verbose = 0
+IS_PYPY = '__pypy__' in sys.modules
+HAS_REFCOUNT = getattr(sys, 'getrefcount', None) is not None
def assert_(val, msg=''):
"""
@@ -1274,6 +1277,8 @@ def _assert_valid_refcount(op):
Check that ufuncs don't mishandle refcount of object `1`.
Used in a few regression tests.
"""
+ if not HAS_REFCOUNT:
+ return True
import numpy as np
b = np.arange(100*100).reshape(100, 100)