summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/release/1.10.3-notes.rst39
-rw-r--r--doc/release/1.11.0-notes.rst7
-rw-r--r--numpy/add_newdocs.py31
-rw-r--r--numpy/core/fromnumeric.py6
-rw-r--r--numpy/core/records.py6
-rw-r--r--numpy/core/src/multiarray/datetime_busday.c2
-rw-r--r--numpy/core/tests/test_datetime.py6
-rw-r--r--numpy/core/tests/test_multiarray.py102
-rw-r--r--numpy/core/tests/test_records.py9
-rw-r--r--numpy/lib/user_array.py17
-rw-r--r--numpy/ma/core.py6
-rw-r--r--numpy/ma/tests/test_core.py1
-rw-r--r--numpy/random/mtrand/mtrand.pyx10
-rw-r--r--numpy/testing/utils.py3
-rwxr-xr-xtools/travis-test.sh3
15 files changed, 216 insertions, 32 deletions
diff --git a/doc/release/1.10.3-notes.rst b/doc/release/1.10.3-notes.rst
new file mode 100644
index 000000000..77b4d0a58
--- /dev/null
+++ b/doc/release/1.10.3-notes.rst
@@ -0,0 +1,39 @@
+NumPy 1.10.3 Release Notes
+**************************
+
+This release is a bugfix source release motivated by a segfault regression.
+No windows binaries are provided for this release, as there appear to be
+bugs in the toolchain we use to generate those files. Hopefully that
+problem will be fixed for the next release. In the meantime, we suggest
+using one of the providers of windows binaries.
+
+Compatibility notes
+===================
+
+* The trace function now calls the trace method on subclasses of ndarray,
+ except for matrix, for which the current behavior is preserved. This is
+ to help with the units package of AstroPy and hopefully will not cause
+ problems.
+
+Issues Fixed
+============
+
+* gh-6922 BUG: numpy.recarray.sort segfaults on Windows.
+* gh-6937 BUG: busday_offset does the wrong thing with modifiedpreceding roll.
+* gh-6949 BUG: Type is lost when slicing a subclass of recarray.
+
+Merged PRs
+==========
+
+The following PRs have been merged into 1.10.3. When the PR is a backport,
+the PR number for the original PR against master is listed.
+
+* gh-6840 TST: Update travis testing script in 1.10.x
+* gh-6843 BUG: Fix use of python 3 only FileNotFoundError in test_f2py.
+* gh-6884 REL: Update pavement.py and setup.py to reflect current version.
+* gh-6916 BUG: Fix test_f2py so it runs correctly in runtests.py.
+* gh-6924 BUG: Fix segfault gh-6922.
+* gh-6942 Fix datetime roll='modifiedpreceding' bug.
+* gh-6943 DOC,BUG: Fix some latex generation problems.
+* gh-6950 BUG trace is not subclass aware, np.trace(ma) != ma.trace().
+* gh-6952 BUG recarray slices should preserve subclass.
diff --git a/doc/release/1.11.0-notes.rst b/doc/release/1.11.0-notes.rst
index da8ec3470..e66e680d3 100644
--- a/doc/release/1.11.0-notes.rst
+++ b/doc/release/1.11.0-notes.rst
@@ -169,3 +169,10 @@ parameter in methods like ```array.flatten``` or ```array.ravel```
that were not one of the following: 'C', 'F', 'A', 'K' (note that
all of these possible values are unicode- and case-insensitive).
Such behaviour will not be allowed in future releases.
+
+Random number generator in the ``testing`` namespace
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Python standard library random number generator was previously exposed in the
+``testing`` namespace as ``testing.rand``. Using this generator is not
+recommended and it will be removed in a future release. Use generators from
+``numpy.random`` namespace instead.
diff --git a/numpy/add_newdocs.py b/numpy/add_newdocs.py
index 7eef07c4a..e79720c77 100644
--- a/numpy/add_newdocs.py
+++ b/numpy/add_newdocs.py
@@ -3888,13 +3888,13 @@ add_newdoc('numpy.core.multiarray', 'ndarray', ('newbyteorder',
----------
new_order : string, optional
Byte order to force; a value from the byte order specifications
- above. `new_order` codes can be any of::
+ below. `new_order` codes can be any of:
- * 'S' - swap dtype from current to opposite endian
- * {'<', 'L'} - little endian
- * {'>', 'B'} - big endian
- * {'=', 'N'} - native order
- * {'|', 'I'} - ignore (no change to byte order)
+ * 'S' - swap dtype from current to opposite endian
+ * {'<', 'L'} - little endian
+ * {'>', 'B'} - big endian
+ * {'=', 'N'} - native order
+ * {'|', 'I'} - ignore (no change to byte order)
The default value ('S') results in swapping the current
byte order. The code does a case-insensitive check on the first
@@ -6359,16 +6359,15 @@ add_newdoc('numpy.core.multiarray', 'dtype', ('newbyteorder',
Parameters
----------
new_order : string, optional
- Byte order to force; a value from the byte order
- specifications below. The default value ('S') results in
- swapping the current byte order.
- `new_order` codes can be any of::
+ Byte order to force; a value from the byte order specifications
+ below. The default value ('S') results in swapping the current
+ byte order. `new_order` codes can be any of:
- * 'S' - swap dtype from current to opposite endian
- * {'<', 'L'} - little endian
- * {'>', 'B'} - big endian
- * {'=', 'N'} - native order
- * {'|', 'I'} - ignore (no change to byte order)
+ * 'S' - swap dtype from current to opposite endian
+ * {'<', 'L'} - little endian
+ * {'>', 'B'} - big endian
+ * {'=', 'N'} - native order
+ * {'|', 'I'} - ignore (no change to byte order)
The code does a case-insensitive check on the first letter of
`new_order` for these alternatives. For example, any of '>'
@@ -7231,10 +7230,10 @@ add_newdoc('numpy.core.numerictypes', 'generic', ('newbyteorder',
The `new_order` code can be any from the following:
+ * 'S' - swap dtype from current to opposite endian
* {'<', 'L'} - little endian
* {'>', 'B'} - big endian
* {'=', 'N'} - native order
- * 'S' - swap dtype from current to opposite endian
* {'|', 'I'} - ignore (no change to byte order)
Parameters
diff --git a/numpy/core/fromnumeric.py b/numpy/core/fromnumeric.py
index 362c29cb8..a2937c5c5 100644
--- a/numpy/core/fromnumeric.py
+++ b/numpy/core/fromnumeric.py
@@ -1367,7 +1367,11 @@ def trace(a, offset=0, axis1=0, axis2=1, dtype=None, out=None):
(2, 3)
"""
- return asarray(a).trace(offset, axis1, axis2, dtype, out)
+ if isinstance(a, np.matrix):
+ # Get trace of matrix via an array to preserve backward compatibility.
+ return asarray(a).trace(offset, axis1, axis2, dtype, out)
+ else:
+ return asanyarray(a).trace(offset, axis1, axis2, dtype, out)
def ravel(a, order='C'):
diff --git a/numpy/core/records.py b/numpy/core/records.py
index ca6070cf7..9f5dcc811 100644
--- a/numpy/core/records.py
+++ b/numpy/core/records.py
@@ -425,7 +425,7 @@ class recarray(ndarray):
def __array_finalize__(self, obj):
if self.dtype.type is not record:
- # if self.dtype is not np.record, invoke __setattr__ which will
+ # if self.dtype is not np.record, invoke __setattr__ which will
# convert it to a record if it is a void dtype.
self.dtype = self.dtype
@@ -496,13 +496,13 @@ class recarray(ndarray):
return self.setfield(val, *res)
def __getitem__(self, indx):
- obj = ndarray.__getitem__(self, indx)
+ obj = super(recarray, self).__getitem__(indx)
# copy behavior of getattr, except that here
# we might also be returning a single element
if isinstance(obj, ndarray):
if obj.dtype.fields:
- obj = obj.view(recarray)
+ obj = obj.view(type(self))
if issubclass(obj.dtype.type, nt.void):
return obj.view(dtype=(self.dtype.type, obj.dtype))
return obj
diff --git a/numpy/core/src/multiarray/datetime_busday.c b/numpy/core/src/multiarray/datetime_busday.c
index 331e10496..4fade4d20 100644
--- a/numpy/core/src/multiarray/datetime_busday.c
+++ b/numpy/core/src/multiarray/datetime_busday.c
@@ -889,7 +889,7 @@ PyArray_BusDayRollConverter(PyObject *roll_in, NPY_BUSDAY_ROLL *roll)
break;
case 'p':
if (strcmp(str, "modifiedpreceding") == 0) {
- *roll = NPY_BUSDAY_MODIFIEDFOLLOWING;
+ *roll = NPY_BUSDAY_MODIFIEDPRECEDING;
goto finish;
}
break;
diff --git a/numpy/core/tests/test_datetime.py b/numpy/core/tests/test_datetime.py
index 563aa48fb..8a8eafee8 100644
--- a/numpy/core/tests/test_datetime.py
+++ b/numpy/core/tests/test_datetime.py
@@ -1524,6 +1524,12 @@ class TestDateTime(TestCase):
assert_equal(
np.busday_offset('2010-10-30', 0, roll='modifiedpreceding'),
np.datetime64('2010-10-29'))
+ assert_equal(
+ np.busday_offset('2010-10-16', 0, roll='modifiedfollowing'),
+ np.datetime64('2010-10-18'))
+ assert_equal(
+ np.busday_offset('2010-10-16', 0, roll='modifiedpreceding'),
+ np.datetime64('2010-10-15'))
# roll='raise' by default
assert_raises(ValueError, np.busday_offset, '2011-06-04', 0)
diff --git a/numpy/core/tests/test_multiarray.py b/numpy/core/tests/test_multiarray.py
index d03c5f547..c66e49e5f 100644
--- a/numpy/core/tests/test_multiarray.py
+++ b/numpy/core/tests/test_multiarray.py
@@ -1936,7 +1936,80 @@ class TestMethods(TestCase):
a = np.array([[1, 0], [0, 1]])
b = np.array([[0, 1], [1, 0]])
c = np.array([[9, 1], [1, -9]])
-
+ d = np.arange(24).reshape(4, 6)
+ ddt = np.array(
+ [[ 55, 145, 235, 325],
+ [ 145, 451, 757, 1063],
+ [ 235, 757, 1279, 1801],
+ [ 325, 1063, 1801, 2539]]
+ )
+ dtd = np.array(
+ [[504, 540, 576, 612, 648, 684],
+ [540, 580, 620, 660, 700, 740],
+ [576, 620, 664, 708, 752, 796],
+ [612, 660, 708, 756, 804, 852],
+ [648, 700, 752, 804, 856, 908],
+ [684, 740, 796, 852, 908, 964]]
+ )
+
+
+ # gemm vs syrk optimizations
+ for et in [np.float32, np.float64, np.complex64, np.complex128]:
+ eaf = a.astype(et)
+ assert_equal(np.dot(eaf, eaf), eaf)
+ assert_equal(np.dot(eaf.T, eaf), eaf)
+ assert_equal(np.dot(eaf, eaf.T), eaf)
+ assert_equal(np.dot(eaf.T, eaf.T), eaf)
+ assert_equal(np.dot(eaf.T.copy(), eaf), eaf)
+ assert_equal(np.dot(eaf, eaf.T.copy()), eaf)
+ assert_equal(np.dot(eaf.T.copy(), eaf.T.copy()), eaf)
+
+ # syrk validations
+ for et in [np.float32, np.float64, np.complex64, np.complex128]:
+ eaf = a.astype(et)
+ ebf = b.astype(et)
+ assert_equal(np.dot(ebf, ebf), eaf)
+ assert_equal(np.dot(ebf.T, ebf), eaf)
+ assert_equal(np.dot(ebf, ebf.T), eaf)
+ assert_equal(np.dot(ebf.T, ebf.T), eaf)
+
+ # syrk - different shape, stride, and view validations
+ for et in [np.float32, np.float64, np.complex64, np.complex128]:
+ edf = d.astype(et)
+ assert_equal(
+ np.dot(edf[::-1, :], edf.T),
+ np.dot(edf[::-1, :].copy(), edf.T.copy())
+ )
+ assert_equal(
+ np.dot(edf[:, ::-1], edf.T),
+ np.dot(edf[:, ::-1].copy(), edf.T.copy())
+ )
+ assert_equal(
+ np.dot(edf, edf[::-1, :].T),
+ np.dot(edf, edf[::-1, :].T.copy())
+ )
+ assert_equal(
+ np.dot(edf, edf[:, ::-1].T),
+ np.dot(edf, edf[:, ::-1].T.copy())
+ )
+ assert_equal(
+ np.dot(edf[:edf.shape[0] // 2, :], edf[::2, :].T),
+ np.dot(edf[:edf.shape[0] // 2, :].copy(), edf[::2, :].T.copy())
+ )
+ assert_equal(
+ np.dot(edf[::2, :], edf[:edf.shape[0] // 2, :].T),
+ np.dot(edf[::2, :].copy(), edf[:edf.shape[0] // 2, :].T.copy())
+ )
+
+ # syrk - different shape
+ for et in [np.float32, np.float64, np.complex64, np.complex128]:
+ edf = d.astype(et)
+ eddtf = ddt.astype(et)
+ edtdf = dtd.astype(et)
+ assert_equal(np.dot(edf, edf.T), eddtf)
+ assert_equal(np.dot(edf.T, edf), edtdf)
+
+ # function versus methods
assert_equal(np.dot(a, b), a.dot(b))
assert_equal(np.dot(np.dot(a, b), c), a.dot(b).dot(c))
@@ -2010,6 +2083,33 @@ class TestMethods(TestCase):
a.diagonal()
assert_(sys.getrefcount(a) < 50)
+ def test_trace(self):
+ a = np.arange(12).reshape((3, 4))
+ assert_equal(a.trace(), 15)
+ assert_equal(a.trace(0), 15)
+ assert_equal(a.trace(1), 18)
+ assert_equal(a.trace(-1), 13)
+
+ b = np.arange(8).reshape((2, 2, 2))
+ assert_equal(b.trace(), [6, 8])
+ assert_equal(b.trace(0), [6, 8])
+ assert_equal(b.trace(1), [2, 3])
+ assert_equal(b.trace(-1), [4, 5])
+ assert_equal(b.trace(0, 0, 1), [6, 8])
+ assert_equal(b.trace(0, 0, 2), [5, 9])
+ assert_equal(b.trace(0, 1, 2), [3, 11])
+ assert_equal(b.trace(offset=1, axis1=0, axis2=2), [1, 3])
+
+ def test_trace_subclass(self):
+ # The class would need to overwrite trace to ensure single-element
+ # output also has the right subclass.
+ class MyArray(np.ndarray):
+ pass
+
+ b = np.arange(8).reshape((2, 2, 2)).view(MyArray)
+ t = b.trace()
+ assert isinstance(t, MyArray)
+
def test_put(self):
icodes = np.typecodes['AllInteger']
fcodes = np.typecodes['AllFloat']
diff --git a/numpy/core/tests/test_records.py b/numpy/core/tests/test_records.py
index e0f0a3a8f..9fbdf51d6 100644
--- a/numpy/core/tests/test_records.py
+++ b/numpy/core/tests/test_records.py
@@ -122,13 +122,20 @@ class TestFromrecords(TestCase):
assert_equal(rv.dtype.type, np.record)
#check that getitem also preserves np.recarray and np.record
- r = np.rec.array(np.ones(4, dtype=[('a', 'i4'), ('b', 'i4'),
+ r = np.rec.array(np.ones(4, dtype=[('a', 'i4'), ('b', 'i4'),
('c', 'i4,i4')]))
assert_equal(r['c'].dtype.type, np.record)
assert_equal(type(r['c']), np.recarray)
assert_equal(r[['a', 'b']].dtype.type, np.record)
assert_equal(type(r[['a', 'b']]), np.recarray)
+ #and that it preserves subclasses (gh-6949)
+ class C(np.recarray):
+ pass
+
+ c = r.view(C)
+ assert_equal(type(c['c']), C)
+
# check that accessing nested structures keep record type, but
# not for subarrays, non-void structures, non-structured voids
test_dtype = [('a', 'f4,f4'), ('b', 'V8'), ('c', ('f4',2)),
diff --git a/numpy/lib/user_array.py b/numpy/lib/user_array.py
index bb5bec628..3103da57b 100644
--- a/numpy/lib/user_array.py
+++ b/numpy/lib/user_array.py
@@ -1,5 +1,6 @@
"""
Standard container-class for easy multiple-inheritance.
+
Try to inherit from the ndarray instead of using this class as this is not
complete.
@@ -16,7 +17,19 @@ from numpy.compat import long
class container(object):
+ """
+ container(data, dtype=None, copy=True)
+
+ Standard container-class for easy multiple-inheritance.
+
+ Methods
+ -------
+ copy
+ tostring
+ byteswap
+ astype
+ """
def __init__(self, data, dtype=None, copy=True):
self.array = array(data, dtype, copy=copy)
@@ -219,15 +232,19 @@ class container(object):
return self._rc(greater_equal(self.array, other))
def copy(self):
+ ""
return self._rc(self.array.copy())
def tostring(self):
+ ""
return self.array.tostring()
def byteswap(self):
+ ""
return self._rc(self.array.byteswap())
def astype(self, typecode):
+ ""
return self._rc(self.array.astype(typecode))
def _rc(self, a):
diff --git a/numpy/ma/core.py b/numpy/ma/core.py
index de716a669..9b0b1cc79 100644
--- a/numpy/ma/core.py
+++ b/numpy/ma/core.py
@@ -3526,6 +3526,8 @@ class MaskedArray(ndarray):
def filled(self, fill_value=None):
"""
Return a copy of self, with masked values filled with a given value.
+ **However**, if there are no masked values to fill, self will be
+ returned instead as an ndarray.
Parameters
----------
@@ -3537,7 +3539,9 @@ class MaskedArray(ndarray):
-------
filled_array : ndarray
A copy of ``self`` with invalid entries replaced by *fill_value*
- (be it the function argument or the attribute of ``self``.
+ (be it the function argument or the attribute of ``self``), or
+ ``self`` itself as an ndarray if there are no invalid entries to
+ be replaced.
Notes
-----
diff --git a/numpy/ma/tests/test_core.py b/numpy/ma/tests/test_core.py
index 020bf1e62..adbbb26d1 100644
--- a/numpy/ma/tests/test_core.py
+++ b/numpy/ma/tests/test_core.py
@@ -3198,6 +3198,7 @@ class TestMaskedArrayMathMethods(TestCase):
assert_almost_equal(mX.trace(),
X.trace() - sum(mXdiag.mask * X.diagonal(),
axis=0))
+ assert_equal(np.trace(mX), mX.trace())
def test_dot(self):
# Tests dot on MaskedArrays.
diff --git a/numpy/random/mtrand/mtrand.pyx b/numpy/random/mtrand/mtrand.pyx
index 489cc9e6e..3a4e132ec 100644
--- a/numpy/random/mtrand/mtrand.pyx
+++ b/numpy/random/mtrand/mtrand.pyx
@@ -681,19 +681,15 @@ def _rand_int32(low, high, size, rngstate):
Return random np.int32 integers between `low` and `high`, inclusive.
Return random integers from the "discrete uniform" distribution in the
- closed interval [`low`, `high`). If `high` is None (the default),
- then results are from [0, `low`). On entry the arguments are presumed
+ closed interval [`low`, `high`]. On entry the arguments are presumed
to have been validated for size and order for the np.int32 type.
Parameters
----------
low : int
- Lowest (signed) integer to be drawn from the distribution (unless
- ``high=None``, in which case this parameter is the *highest* such
- integer).
+ Lowest (signed) integer to be drawn from the distribution.
high : int
- If provided, the largest (signed) integer to be drawn from the
- distribution (see above for behavior if ``high=None``).
+ Highest (signed) integer to be drawn from the distribution.
size : int or tuple of ints
Output shape. If the given shape is, e.g., ``(m, n, k)``, then
``m * n * k`` samples are drawn. Default is None, in which case a
diff --git a/numpy/testing/utils.py b/numpy/testing/utils.py
index 0c4ebe1b9..f545cd3c2 100644
--- a/numpy/testing/utils.py
+++ b/numpy/testing/utils.py
@@ -16,6 +16,7 @@ from tempfile import mkdtemp, mkstemp
from .nosetester import import_nose
from numpy.core import float32, empty, arange, array_repr, ndarray
+from numpy.lib.utils import deprecate
if sys.version_info[0] >= 3:
from io import StringIO
@@ -122,6 +123,8 @@ def gisinf(x):
raise TypeError("isinf not supported for this type")
return st
+@deprecate(message="numpy.testing.rand is deprecated in numpy 1.11. "
+ "Use numpy.random.rand instead.")
def rand(*args):
"""Returns an array of random numbers with the given shape.
diff --git a/tools/travis-test.sh b/tools/travis-test.sh
index 40e266b26..d105c15c7 100755
--- a/tools/travis-test.sh
+++ b/tools/travis-test.sh
@@ -25,7 +25,8 @@ if [ -n "$PYTHON_OO" ]; then
fi
# make some warnings fatal, mostly to match windows compilers
-werrors="-Werror=declaration-after-statement -Werror=vla -Werror=nonnull"
+werrors="-Werror=declaration-after-statement -Werror=vla "
+werrors+="-Werror=nonnull -Werror=pointer-arith"
setup_base()
{