8000 DEP: Deprecate non-tuple nd-indices by eric-wieser · Pull Request #9686 · numpy/numpy · GitHub
[go: up one dir, main page]

Skip to content

DEP: Deprecate non-tuple nd-indices #9686

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
May 27, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions doc/release/1.15.0-notes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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`
Expand Down
17 changes: 11 additions & 6 deletions doc/source/reference/arrays.indexing.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
^^^^^^^^^^^^^^^^^^^^^^
Expand Down
17 changes: 15 additions & 2 deletions numpy/core/src/multiarray/mapping.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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;
}
}
Expand All @@ -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;
}

/**
Expand Down
16 changes: 16 additions & 0 deletions numpy/core/tests/test_deprecations.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
0