summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCharles Harris <charlesr.harris@gmail.com>2018-05-27 13:40:20 -0600
committerGitHub <noreply@github.com>2018-05-27 13:40:20 -0600
commit69458b02956d39082014573eb0350ae3eb3436ee (patch)
tree35a05b19a67c4aa67b40a71627eb35470479c796
parent7d7c71ccae98c448f120d42f372bb2d0d3f10f6a (diff)
parenta10b4270d4b3f538254698874560d645c0525dc5 (diff)
downloadnumpy-69458b02956d39082014573eb0350ae3eb3436ee.tar.gz
Merge pull request #9686 from eric-wieser/force-tuple
DEP: Deprecate non-tuple nd-indices
-rw-r--r--doc/release/1.15.0-notes.rst7
-rw-r--r--doc/source/reference/arrays.indexing.rst17
-rw-r--r--numpy/core/src/multiarray/mapping.c17
-rw-r--r--numpy/core/tests/test_deprecations.py16
4 files changed, 49 insertions, 8 deletions
diff --git a/doc/release/1.15.0-notes.rst b/doc/release/1.15.0-notes.rst
index 04a188c65..23e0284c4 100644
--- a/doc/release/1.15.0-notes.rst
+++ b/doc/release/1.15.0-notes.rst
@@ -46,6 +46,13 @@ Deprecations
* `np.ma.load`, `np.ma.dump` - these functions already failed on python 3,
when called with a string.
+* Multidimensional indexing with anything but a tuple is
+ deprecated. This means that code such as ``ind = [slice(None), 0]``,
+ ``arr[[slice(None), 0]]`` should be changed to ``arr[tuple(ind)]``. This is
+ necessary to avoid ambiguity in expressions such as ``arr[[[0, 1], [0, 1]]]``
+ which currently is interpreted as ``arr[array([0, 1]), array([0, 1])]``.
+ In future, this will be interpreted as ``arr[array([[0, 1], [0, 1]])]``.
+
* Direct imports from the following modules is deprecated. All testing related
imports should come from `numpy.testing`.
* `np.testing.utils`
diff --git a/doc/source/reference/arrays.indexing.rst b/doc/source/reference/arrays.indexing.rst
index b5a44c22a..ba1bfd312 100644
--- a/doc/source/reference/arrays.indexing.rst
+++ b/doc/source/reference/arrays.indexing.rst
@@ -29,11 +29,15 @@ dimensions. Basic slicing occurs when *obj* is a :class:`slice` object
(constructed by ``start:stop:step`` notation inside of brackets), an
integer, or a tuple of slice objects and integers. :const:`Ellipsis`
and :const:`newaxis` objects can be interspersed with these as
-well. In order to remain backward compatible with a common usage in
-Numeric, basic slicing is also initiated if the selection object is
-any non-ndarray sequence (such as a :class:`list`) containing :class:`slice`
-objects, the :const:`Ellipsis` object, or the :const:`newaxis` object,
-but not for integer arrays or other embedded sequences.
+well.
+
+.. deprecated:: 1.15.0
+
+ In order to remain backward compatible with a common usage in
+ Numeric, basic slicing is also initiated if the selection object is
+ any non-ndarray and non-tuple sequence (such as a :class:`list`) containing
+ :class:`slice` objects, the :const:`Ellipsis` object, or the :const:`newaxis`
+ object, but not for integer arrays or other embedded sequences.
.. index::
triple: ndarray; special methods; getitem
@@ -196,7 +200,8 @@ basic slicing that returns a :term:`view`).
why this occurs.
Also recognize that ``x[[1,2,3]]`` will trigger advanced indexing,
- whereas ``x[[1,2,slice(None)]]`` will trigger basic slicing.
+ whereas due to the deprecated Numeric compatibility mentioned above,
+ ``x[[1,2,slice(None)]]`` will trigger basic slicing.
Integer array indexing
^^^^^^^^^^^^^^^^^^^^^^
diff --git a/numpy/core/src/multiarray/mapping.c b/numpy/core/src/multiarray/mapping.c
index 4b2c6aa5a..42dbc3cce 100644
--- a/numpy/core/src/multiarray/mapping.c
+++ b/numpy/core/src/multiarray/mapping.c
@@ -293,8 +293,7 @@ unpack_indices(PyObject *index, PyObject **result, npy_intp result_n)
if (commit_to_unpack) {
/* propagate errors */
if (tmp_obj == NULL) {
- multi_DECREF(result, i);
- return -1;
+ goto fail;
}
}
else {
@@ -313,6 +312,16 @@ unpack_indices(PyObject *index, PyObject **result, npy_intp result_n)
|| PySlice_Check(tmp_obj)
|| tmp_obj == Py_Ellipsis
|| tmp_obj == Py_None) {
+ if (DEPRECATE_FUTUREWARNING(
+ "Using a non-tuple sequence for multidimensional "
+ "indexing is deprecated; use `arr[tuple(seq)]` "
+ "instead of `arr[seq]`. In the future this will be "
+ "interpreted as an array index, `arr[np.array(seq)]`, "
+ "which will result either in an error or a different "
+ "result.") < 0) {
+ i++; /* since loop update doesn't run */
+ goto fail;
+ }
commit_to_unpack = 1;
}
}
@@ -328,6 +337,10 @@ unpack_indices(PyObject *index, PyObject **result, npy_intp result_n)
multi_DECREF(result, i);
return unpack_scalar(index, result, result_n);
}
+
+fail:
+ multi_DECREF(result, i);
+ return -1;
}
/**
diff --git a/numpy/core/tests/test_deprecations.py b/numpy/core/tests/test_deprecations.py
index 5d59d8226..60a7c72f7 100644
--- a/numpy/core/tests/test_deprecations.py
+++ b/numpy/core/tests/test_deprecations.py
@@ -134,6 +134,22 @@ class _VisibleDeprecationTestCase(_DeprecationTestCase):
warning_cls = np.VisibleDeprecationWarning
+class TestNonTupleNDIndexDeprecation(object):
+ def test_basic(self):
+ a = np.zeros((5, 5))
+ with warnings.catch_warnings():
+ warnings.filterwarnings('always')
+ assert_warns(FutureWarning, a.__getitem__, [[0, 1], [0, 1]])
+ assert_warns(FutureWarning, a.__getitem__, [slice(None)])
+
+ warnings.filterwarnings('error')
+ assert_raises(FutureWarning, a.__getitem__, [[0, 1], [0, 1]])
+ assert_raises(FutureWarning, a.__getitem__, [slice(None)])
+
+ # a a[[0, 1]] always was advanced indexing, so no error/warning
+ a[[0, 1]]
+
+
class TestRankDeprecation(_DeprecationTestCase):
"""Test that np.rank is deprecated. The function should simply be
removed. The VisibleDeprecationWarning may become unnecessary.