diff options
author | mattip <matti.picus@gmail.com> | 2018-09-09 09:44:31 +0300 |
---|---|---|
committer | mattip <matti.picus@gmail.com> | 2018-10-21 18:12:09 +0300 |
commit | 73c5a5aca2c17505ae352b94ebd5043e5df80f14 (patch) | |
tree | 3234b269c70ddb978582b88c9743d779a3919ed6 | |
parent | 28b3694aa1eeeaa75068436b79a87a296545fea4 (diff) | |
download | numpy-73c5a5aca2c17505ae352b94ebd5043e5df80f14.tar.gz |
DEP: deprecate np.set_numeric_ops and friends
-rw-r--r-- | doc/release/1.16.0-notes.rst | 9 | ||||
-rw-r--r-- | doc/source/reference/arrays.ndarray.rst | 2 | ||||
-rw-r--r-- | doc/source/reference/c-api.array.rst | 4 | ||||
-rw-r--r-- | numpy/core/_add_newdocs.py | 23 | ||||
-rw-r--r-- | numpy/core/code_generators/cversions.txt | 6 | ||||
-rw-r--r-- | numpy/core/setup.py | 1 | ||||
-rw-r--r-- | numpy/core/src/multiarray/_multiarray_tests.c.src | 13 | ||||
-rw-r--r-- | numpy/core/src/multiarray/multiarraymodule.c | 6 | ||||
-rw-r--r-- | numpy/core/src/multiarray/number.c | 39 | ||||
-rw-r--r-- | numpy/core/src/multiarray/number.h | 4 | ||||
-rw-r--r-- | numpy/core/src/multiarray/temp_elide.c | 2 | ||||
-rw-r--r-- | numpy/core/src/umath/umathmodule.c | 3 | ||||
-rw-r--r-- | numpy/core/tests/test_deprecations.py | 11 |
13 files changed, 95 insertions, 28 deletions
diff --git a/doc/release/1.16.0-notes.rst b/doc/release/1.16.0-notes.rst index 599123f97..73c4b52c7 100644 --- a/doc/release/1.16.0-notes.rst +++ b/doc/release/1.16.0-notes.rst @@ -4,7 +4,7 @@ NumPy 1.16.0 Release Notes This NumPy release is the last one to support Python 2.7. It will be maintained as a long term release with bug fixes only through 2020. To that end, the -planned code reorganization detailed in NEP-0015 has been made in order to +planned code reorganization detailed in `NEP 15`_ has been made in order to facilitate backporting fixes from future releases, which will now have the same code organization. @@ -41,6 +41,13 @@ These were deprecated in 1.10, had no tests, and seem to no longer work in It is an alias to the more powerful `numpy.ndarray.item`, not tested, and fails for scalars. +`np.set_array_ops` and `np.get_array_ops` have been deprecated +-------------------------------------------------------------- +As part of `NEP 15`, they have been deprecated along with the C-API functions +:c:func:`PyArray_SetNumericOps` and :c:func:`PyArray_GetNumericOps`. Users who wish to override +the inner loop functions in built-in ufuncs should use +:c:func:`PyUFunc_ReplaceLoopBySignature`. + Future Changes ============== diff --git a/doc/source/reference/arrays.ndarray.rst b/doc/source/reference/arrays.ndarray.rst index 4c8bbf66d..306d22f43 100644 --- a/doc/source/reference/arrays.ndarray.rst +++ b/doc/source/reference/arrays.ndarray.rst @@ -517,7 +517,7 @@ Arithmetic: ``__r{op}__`` special methods are not directly defined. - The functions called to implement many arithmetic special methods - for arrays can be modified using :func:`set_numeric_ops`. + for arrays can be modified using :class:`__array_ufunc__ <numpy.class.__array_ufunc__>`. Arithmetic, in-place: diff --git a/doc/source/reference/c-api.array.rst b/doc/source/reference/c-api.array.rst index 9265b1a97..3d7e65415 100644 --- a/doc/source/reference/c-api.array.rst +++ b/doc/source/reference/c-api.array.rst @@ -3209,12 +3209,16 @@ Internal Flexibility setting a Python Error) if one of the objects being assigned is not callable. + .. deprecated:: 1.16 + .. c:function:: PyObject* PyArray_GetNumericOps(void) Return a Python dictionary containing the callable Python objects stored in the internal arithmetic operation table. The keys of this dictionary are given in the explanation for :c:func:`PyArray_SetNumericOps`. + .. deprecated:: 1.16 + .. c:function:: void PyArray_SetStringFunction(PyObject* op, int repr) This function allows you to alter the tp_str and tp_repr methods diff --git a/numpy/core/_add_newdocs.py b/numpy/core/_add_newdocs.py index ea472f1b3..e1dd04edb 100644 --- a/numpy/core/_add_newdocs.py +++ b/numpy/core/_add_newdocs.py @@ -1320,6 +1320,11 @@ add_newdoc('numpy.core.multiarray', 'set_numeric_ops', Set numerical operators for array objects. + .. deprecated:: 1.16 + + Use :c:func:`PyUFunc_ReplaceLoopBySignature` or subclass ndarray and + use ``__array_ufunc__`` instead. + Parameters ---------- op1, op2, ... : callable @@ -1597,7 +1602,7 @@ add_newdoc('numpy.core.multiarray', 'c_einsum', """ c_einsum(subscripts, *operands, out=None, dtype=None, order='K', casting='safe') - + *This documentation shadows that of the native python implementation of the `einsum` function, except all references and examples related to the `optimize` argument (v 0.12.0) have been removed.* @@ -2113,7 +2118,7 @@ add_newdoc('numpy.core.multiarray', 'ndarray', ('ctypes', ----- Below are the public attributes of this object which were documented in "Guide to NumPy" (we have omitted undocumented public attributes, - as well as documented private attributes): + as well as documented private attributes): .. autoattribute:: numpy.core._internal._ctypes.data @@ -2455,7 +2460,7 @@ add_newdoc('numpy.core.multiarray', 'ndarray', ('size', Notes ----- - `a.size` returns a standard arbitrary precision Python integer. This + `a.size` returns a standard arbitrary precision Python integer. This may not be the case with other methods of obtaining the same value (like the suggested ``np.prod(a.shape)``, which returns an instance of ``np.int_``), and may be relevant if the value is used further in @@ -4090,7 +4095,7 @@ add_newdoc('numpy.core.multiarray', 'ndarray', ('tofile', machines with different endianness. Some of these problems can be overcome by outputting the data as text files, at the expense of speed and file size. - + When fid is a file object, array contents are directly written to the file, bypassing the file object's ``write`` method. As a result, tofile cannot be used with files objects supporting compression (e.g., GzipFile) @@ -5200,7 +5205,7 @@ add_newdoc('numpy.core', 'ufunc', ('reduce', to None - otherwise it defaults to ufunc.identity. If ``None`` is given, the first element of the reduction is used, and an error is thrown if the reduction is empty. - + .. versionadded:: 1.15.0 Returns @@ -5233,18 +5238,18 @@ add_newdoc('numpy.core', 'ufunc', ('reduce', >>> np.add.reduce(X, 2) array([[ 1, 5], [ 9, 13]]) - + You can use the ``initial`` keyword argument to initialize the reduction with a different value. - + >>> np.add.reduce([10], initial=5) 15 >>> np.add.reduce(np.ones((2, 2, 2)), axis=(0, 2), initializer=10) array([14., 14.]) - + Allows reductions of empty arrays where they would normally fail, i.e. for ufuncs without an identity. - + >>> np.minimum.reduce([], initial=np.inf) inf >>> np.minimum.reduce([]) diff --git a/numpy/core/code_generators/cversions.txt b/numpy/core/code_generators/cversions.txt index c8b998bfc..73cd8ddd6 100644 --- a/numpy/core/code_generators/cversions.txt +++ b/numpy/core/code_generators/cversions.txt @@ -39,9 +39,11 @@ 0x0000000b = edb1ba83730c650fd9bc5772a919cda7 # Version 12 (NumPy 1.14) Added PyArray_ResolveWritebackIfCopy, -# Version 12 (NumPy 1.15) No change. # PyArray_SetWritebackIfCopyBase and deprecated PyArray_SetUpdateIfCopyBase. +# Version 12 (NumPy 1.15) No change. 0x0000000c = a1bc756c5782853ec2e3616cf66869d8 -# Version 13 (Numpy 1.16) Added fields core_dim_flags and core_dim_sizes to PyUFuncObject +# Version 13 (NumPy 1.16) Deprecate PyArray_SetNumericOps and +# PyArray_GetNumericOps, Added fields core_dim_flags and core_dim_sizes +# to PyUFuncObject 0x0000000d = a1bc756c5782853ec2e3616cf66869d8 diff --git a/numpy/core/setup.py b/numpy/core/setup.py index fc15fe59f..9923f3dc9 100644 --- a/numpy/core/setup.py +++ b/numpy/core/setup.py @@ -901,6 +901,7 @@ def configuration(parent_package='',top_path=None): join('include', 'numpy', 'npy_math.h'), join('include', 'numpy', 'halffloat.h'), join('src', 'multiarray', 'common.h'), + join('src', 'multiarray', 'number.h'), join('src', 'common', 'templ_common.h.src'), join('src', 'umath', 'simd.inc.src'), join('src', 'umath', 'override.h'), diff --git a/numpy/core/src/multiarray/_multiarray_tests.c.src b/numpy/core/src/multiarray/_multiarray_tests.c.src index 6c4d49bd1..b98c3afb3 100644 --- a/numpy/core/src/multiarray/_multiarray_tests.c.src +++ b/numpy/core/src/multiarray/_multiarray_tests.c.src @@ -1855,6 +1855,16 @@ printf_float_g(PyObject *NPY_UNUSED(dummy), PyObject *args, PyObject *kwds) return PrintFloat_Printf_g(obj, precision); } +static PyObject * +getset_numericops(PyObject* NPY_UNUSED(self), PyObject* NPY_UNUSED(args)) +{ + PyObject * ops = PyArray_GetNumericOps(); + if (ops == NULL) { + return NULL; + } + return PyLong_FromLong(PyArray_SetNumericOps(ops)); +} + static PyMethodDef Multiarray_TestsMethods[] = { {"IsPythonScalar", IsPythonScalar, @@ -1963,6 +1973,9 @@ static PyMethodDef Multiarray_TestsMethods[] = { {"get_fpu_mode", get_fpu_mode, METH_VARARGS, get_fpu_mode_doc}, + {"getset_numericops", + getset_numericops, + METH_NOARGS, NULL}, /**begin repeat * #name = cabs, carg# */ diff --git a/numpy/core/src/multiarray/multiarraymodule.c b/numpy/core/src/multiarray/multiarraymodule.c index 8f782cff6..8db1a1951 100644 --- a/numpy/core/src/multiarray/multiarraymodule.c +++ b/numpy/core/src/multiarray/multiarraymodule.c @@ -2990,7 +2990,7 @@ array_set_ops_function(PyObject *NPY_UNUSED(self), PyObject *NPY_UNUSED(args), { PyObject *oldops = NULL; - if ((oldops = PyArray_GetNumericOps()) == NULL) { + if ((oldops = _PyArray_GetNumericOps()) == NULL) { return NULL; } /* @@ -3000,8 +3000,10 @@ array_set_ops_function(PyObject *NPY_UNUSED(self), PyObject *NPY_UNUSED(args), */ if (kwds && PyArray_SetNumericOps(kwds) == -1) { Py_DECREF(oldops); - PyErr_SetString(PyExc_ValueError, + if (PyErr_Occurred() == NULL) { + PyErr_SetString(PyExc_ValueError, "one or more objects not callable"); + } return NULL; } return oldops; diff --git a/numpy/core/src/multiarray/number.c b/numpy/core/src/multiarray/number.c index dabbae064..57702a0ca 100644 --- a/numpy/core/src/multiarray/number.c +++ b/numpy/core/src/multiarray/number.c @@ -71,12 +71,8 @@ array_inplace_power(PyArrayObject *a1, PyObject *o2, PyObject *NPY_UNUSED(modulo n_ops.op = temp; \ } - -/*NUMPY_API - *Set internal structure with number functions that all arrays will use - */ NPY_NO_EXPORT int -PyArray_SetNumericOps(PyObject *dict) +_PyArray_SetNumericOps(PyObject *dict) { PyObject *temp = NULL; SET(add); @@ -119,16 +115,28 @@ PyArray_SetNumericOps(PyObject *dict) return 0; } +/*NUMPY_API + *Set internal structure with number functions that all arrays will use + */ +NPY_NO_EXPORT int +PyArray_SetNumericOps(PyObject *dict) +{ + /* 2018-09-09, 1.16 */ + if (DEPRECATE("PyArray_SetNumericOps is deprecated. Use " + "PyUFunc_ReplaceLoopBySignature to replace ufunc inner loop functions " + "instead.") < 0) { + return -1; + } + return _PyArray_SetNumericOps(dict); +} + /* Note - macro contains goto */ #define GET(op) if (n_ops.op && \ (PyDict_SetItemString(dict, #op, n_ops.op)==-1)) \ goto fail; -/*NUMPY_API - Get dictionary showing number functions that all arrays will use -*/ NPY_NO_EXPORT PyObject * -PyArray_GetNumericOps(void) +_PyArray_GetNumericOps(void) { PyObject *dict; if ((dict = PyDict_New())==NULL) @@ -176,6 +184,19 @@ PyArray_GetNumericOps(void) return NULL; } +/*NUMPY_API + Get dictionary showing number functions that all arrays will use +*/ +NPY_NO_EXPORT PyObject * +PyArray_GetNumericOps(void) +{ + /* 2018-09-09, 1.16 */ + if (DEPRECATE("PyArray_GetNumericOps is deprecated.") < 0) { + return NULL; + } + return _PyArray_GetNumericOps(); +} + static PyObject * _get_keywords(int rtype, PyArrayObject *out) { diff --git a/numpy/core/src/multiarray/number.h b/numpy/core/src/multiarray/number.h index 99a2a722b..fbdfe6f94 100644 --- a/numpy/core/src/multiarray/number.h +++ b/numpy/core/src/multiarray/number.h @@ -48,10 +48,10 @@ NPY_NO_EXPORT PyObject * array_int(PyArrayObject *v); NPY_NO_EXPORT int -PyArray_SetNumericOps(PyObject *dict); +_PyArray_SetNumericOps(PyObject *dict); NPY_NO_EXPORT PyObject * -PyArray_GetNumericOps(void); +_PyArray_GetNumericOps(void); NPY_NO_EXPORT PyObject * PyArray_GenericBinaryFunction(PyArrayObject *m1, PyObject *m2, PyObject *op); diff --git a/numpy/core/src/multiarray/temp_elide.c b/numpy/core/src/multiarray/temp_elide.c index 3d2f976f2..09b948218 100644 --- a/numpy/core/src/multiarray/temp_elide.c +++ b/numpy/core/src/multiarray/temp_elide.c @@ -166,7 +166,7 @@ check_callers(int * cannot) return 0; } /* get multiarray base address */ - if (dladdr(&PyArray_SetNumericOps, &info)) { + if (dladdr(&PyArray_INCREF, &info)) { pos_ma_start = info.dli_fbase; pos_ma_end = info.dli_fbase; } diff --git a/numpy/core/src/umath/umathmodule.c b/numpy/core/src/umath/umathmodule.c index 20bd2b0a8..8277ad6cc 100644 --- a/numpy/core/src/umath/umathmodule.c +++ b/numpy/core/src/umath/umathmodule.c @@ -29,6 +29,7 @@ #include "abstract.h" #include "numpy/npy_math.h" +#include "number.h" static PyUFuncGenericFunction pyfunc_functions[] = {PyUFunc_On_Om}; @@ -325,7 +326,7 @@ int initumath(PyObject *m) s2 = PyDict_GetItemString(d, "remainder"); /* Setup the array object's numerical structures with appropriate ufuncs in d*/ - PyArray_SetNumericOps(d); + _PyArray_SetNumericOps(d); PyDict_SetItemString(d, "conj", s); PyDict_SetItemString(d, "mod", s2); diff --git a/numpy/core/tests/test_deprecations.py b/numpy/core/tests/test_deprecations.py index 10ef16800..7e6e256fe 100644 --- a/numpy/core/tests/test_deprecations.py +++ b/numpy/core/tests/test_deprecations.py @@ -523,3 +523,14 @@ class TestFromstring(_DeprecationTestCase): # 2017-10-19, 1.14 def test_fromstring(self): self.assert_deprecated(np.fromstring, args=('\x00'*80,)) + +class Test_GetSet_NumericOps(_DeprecationTestCase): + # 2018-09-20, 1.16.0 + def test_get_numeric_ops(self): + from numpy.core._multiarray_tests import getset_numericops + self.assert_deprecated(getset_numericops, num=2) + + # empty kwargs prevents any state actually changing which would break + # other tests. + self.assert_deprecated(np.set_numeric_ops, kwargs={}) + assert_raises(ValueError, np.set_numeric_ops, add='abc') |