diff --git a/doc/release/upcoming_changes/23998.expired.rst b/doc/release/upcoming_changes/23998.expired.rst new file mode 100644 index 000000000000..f2c065ab27e0 --- /dev/null +++ b/doc/release/upcoming_changes/23998.expired.rst @@ -0,0 +1,3 @@ +* The deprecation of ``set_numeric_ops`` and the C functions + ``PyArray_SetNumericOps`` and ``PyArray_GetNumericOps`` has + been expired and the functions removed. (Deprecated NumPy 1.16) diff --git a/doc/source/reference/c-api/array.rst b/doc/source/reference/c-api/array.rst index 038702bcf118..c1d83ee0ef31 100644 --- a/doc/source/reference/c-api/array.rst +++ b/doc/source/reference/c-api/array.rst @@ -3246,47 +3246,6 @@ extension with the lowest :c:data:`NPY_FEATURE_VERSION` as possible. Internal Flexibility ~~~~~~~~~~~~~~~~~~~~ -.. c:function:: int PyArray_SetNumericOps(PyObject* dict) - - NumPy stores an internal table of Python callable objects that are - used to implement arithmetic operations for arrays as well as - certain array calculation methods. This function allows the user - to replace any or all of these Python objects with their own - versions. The keys of the dictionary, *dict*, are the named - functions to replace and the paired value is the Python callable - object to use. Care should be taken that the function used to - replace an internal array operation does not itself call back to - that internal array operation (unless you have designed the - function to handle that), or an unchecked infinite recursion can - result (possibly causing program crash). The key names that - represent operations that can be replaced are: - - **add**, **subtract**, **multiply**, **divide**, - **remainder**, **power**, **square**, **reciprocal**, - **ones_like**, **sqrt**, **negative**, **positive**, - **absolute**, **invert**, **left_shift**, **right_shift**, - **bitwise_and**, **bitwise_xor**, **bitwise_or**, - **less**, **less_equal**, **equal**, **not_equal**, - **greater**, **greater_equal**, **floor_divide**, - **true_divide**, **logical_or**, **logical_and**, - **floor**, **ceil**, **maximum**, **minimum**, **rint**. - - - These functions are included here because they are used at least once - in the array object's methods. The function returns -1 (without - 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/__init__.cython-30.pxd b/numpy/__init__.cython-30.pxd index 5cf075d556de..72829c23ba7b 100644 --- a/numpy/__init__.cython-30.pxd +++ b/numpy/__init__.cython-30.pxd @@ -548,8 +548,6 @@ cdef extern from "numpy/arrayobject.h": # Functions taking dtype and returning object/ndarray are disabled # for now as they steal dtype references. I'm conservative and disable # more than is probably needed until it can be checked further. - int PyArray_SetNumericOps (object) except -1 - object PyArray_GetNumericOps () int PyArray_INCREF (ndarray) except * # uses PyArray_Item_INCREF... int PyArray_XDECREF (ndarray) except * # uses PyArray_Item_DECREF... void PyArray_SetStringFunction (object, int) diff --git a/numpy/__init__.pxd b/numpy/__init__.pxd index a82392a39f68..7eb20daaaeb9 100644 --- a/numpy/__init__.pxd +++ b/numpy/__init__.pxd @@ -506,8 +506,6 @@ cdef extern from "numpy/arrayobject.h": # Functions taking dtype and returning object/ndarray are disabled # for now as they steal dtype references. I'm conservative and disable # more than is probably needed until it can be checked further. - int PyArray_SetNumericOps (object) except -1 - object PyArray_GetNumericOps () int PyArray_INCREF (ndarray) except * # uses PyArray_Item_INCREF... int PyArray_XDECREF (ndarray) except * # uses PyArray_Item_DECREF... void PyArray_SetStringFunction (object, int) diff --git a/numpy/core/_add_newdocs.py b/numpy/core/_add_newdocs.py index 65a6c278b9ba..670c974975ba 100644 --- a/numpy/core/_add_newdocs.py +++ b/numpy/core/_add_newdocs.py @@ -1822,56 +1822,6 @@ """) -add_newdoc('numpy.core.multiarray', 'set_numeric_ops', - """ - set_numeric_ops(op1=func1, op2=func2, ...) - - Set numerical operators for array objects. - - .. deprecated:: 1.16 - - For the general case, use :c:func:`PyUFunc_ReplaceLoopBySignature`. - For ndarray subclasses, define the ``__array_ufunc__`` method and - override the relevant ufunc. - - Parameters - ---------- - op1, op2, ... : callable - Each ``op = func`` pair describes an operator to be replaced. - For example, ``add = lambda x, y: np.add(x, y) % 5`` would replace - addition by modulus 5 addition. - - Returns - ------- - saved_ops : list of callables - A list of all operators, stored before making replacements. - - Notes - ----- - .. warning:: - Use with care! Incorrect usage may lead to memory errors. - - A function replacing an operator cannot make use of that operator. - For example, when replacing add, you may not use ``+``. Instead, - directly call ufuncs. - - Examples - -------- - >>> def add_mod5(x, y): - ... return np.add(x, y) % 5 - ... - >>> old_funcs = np.set_numeric_ops(add=add_mod5) - - >>> x = np.arange(12).reshape((3, 4)) - >>> x + x - array([[0, 2, 4, 1], - [3, 0, 2, 4], - [1, 3, 0, 2]]) - - >>> ignore = np.set_numeric_ops(**old_funcs) # restore operators - - """) - add_newdoc('numpy.core.multiarray', 'promote_types', """ promote_types(type1, type2) diff --git a/numpy/core/code_generators/cversions.txt b/numpy/core/code_generators/cversions.txt index 6efebb14df09..9f82c6d70d17 100644 --- a/numpy/core/code_generators/cversions.txt +++ b/numpy/core/code_generators/cversions.txt @@ -73,4 +73,4 @@ 0x00000011 = ca1aebdad799358149567d9d93cbca09 # Version 18 (NumPy 2.0.0) -0x00000012 = 4c86e23257f345e755945dfb21c04120 +0x00000012 = 5af92e858ce8e95409ae1fcc8f508ddd diff --git a/numpy/core/code_generators/numpy_api.py b/numpy/core/code_generators/numpy_api.py index 97457ff56cf6..72fb86d92cfe 100644 --- a/numpy/core/code_generators/numpy_api.py +++ b/numpy/core/code_generators/numpy_api.py @@ -98,10 +98,10 @@ def get_annotations(): # define _PyArrayScalar_BoolValues ((PyBoolScalarObject *)PyArray_API[8]) multiarray_funcs_api = { - '__unused_indices__': [67, 68, 163, 164, 201, 202, 278, 291], + '__unused_indices__': [40, 41, 67, 68, 163, 164, 201, 202, 278, 291], 'PyArray_GetNDArrayCVersion': (0,), - 'PyArray_SetNumericOps': (40,), - 'PyArray_GetNumericOps': (41,), + # Unused slot 40, was `PyArray_SetNumericOps` + # Unused slot 41, was `PyArray_GetNumericOps`, 'PyArray_INCREF': (42,), 'PyArray_XDECREF': (43,), 'PyArray_SetStringFunction': (44,), diff --git a/numpy/core/multiarray.py b/numpy/core/multiarray.py index dfa451d885f9..266904e17fd2 100644 --- a/numpy/core/multiarray.py +++ b/numpy/core/multiarray.py @@ -39,7 +39,7 @@ 'min_scalar_type', 'ndarray', 'nditer', 'nested_iters', 'normalize_axis_index', 'packbits', 'promote_types', 'putmask', 'ravel_multi_index', 'result_type', 'scalar', 'set_datetimeparse_function', - 'set_legacy_print_mode', 'set_numeric_ops', 'set_string_function', + 'set_legacy_print_mode', 'set_string_function', 'set_typeDict', 'shares_memory', 'tracemalloc_domain', 'typeinfo', 'unpackbits', 'unravel_index', 'vdot', 'where', 'zeros', '_get_promotion_state', '_set_promotion_state'] @@ -66,7 +66,6 @@ may_share_memory.__module__ = 'numpy' nested_iters.__module__ = 'numpy' promote_types.__module__ = 'numpy' -set_numeric_ops.__module__ = 'numpy' zeros.__module__ = 'numpy' _get_promotion_state.__module__ = 'numpy' _set_promotion_state.__module__ = 'numpy' diff --git a/numpy/core/numeric.py b/numpy/core/numeric.py index 88a39fcf4a8f..0434928d5059 100644 --- a/numpy/core/numeric.py +++ b/numpy/core/numeric.py @@ -17,7 +17,7 @@ empty_like, flatiter, frombuffer, from_dlpack, fromfile, fromiter, fromstring, inner, lexsort, matmul, may_share_memory, min_scalar_type, ndarray, nditer, nested_iters, promote_types, - putmask, result_type, set_numeric_ops, shares_memory, vdot, where, + putmask, result_type, shares_memory, vdot, where, zeros, normalize_axis_index, _get_promotion_state, _set_promotion_state) from . import overrides @@ -44,7 +44,7 @@ 'asfortranarray', 'zeros', 'count_nonzero', 'empty', 'broadcast', 'dtype', 'fromstring', 'fromfile', 'frombuffer', 'from_dlpack', 'where', 'argwhere', 'copyto', 'concatenate', 'fastCopyAndTranspose', 'lexsort', - 'set_numeric_ops', 'can_cast', 'promote_types', 'min_scalar_type', + 'can_cast', 'promote_types', 'min_scalar_type', 'result_type', 'isfortran', 'empty_like', 'zeros_like', 'ones_like', 'correlate', 'convolve', 'inner', 'dot', 'outer', 'vdot', 'roll', 'rollaxis', 'moveaxis', 'cross', 'tensordot', 'little_endian', diff --git a/numpy/core/src/multiarray/_multiarray_tests.c.src b/numpy/core/src/multiarray/_multiarray_tests.c.src index b38383037b76..c2d53ef4eae2 100644 --- a/numpy/core/src/multiarray/_multiarray_tests.c.src +++ b/numpy/core/src/multiarray/_multiarray_tests.c.src @@ -2129,20 +2129,6 @@ 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 *ret; - PyObject *ops = PyArray_GetNumericOps(); - if (ops == NULL) { - return NULL; - } - ret = PyLong_FromLong(PyArray_SetNumericOps(ops)); - Py_DECREF(ops); - return ret; -} - - static PyObject * run_byteorder_converter(PyObject* NPY_UNUSED(self), PyObject *args) { @@ -2424,9 +2410,6 @@ 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 024f41df9499..a47528d17bd2 100644 --- a/numpy/core/src/multiarray/multiarraymodule.c +++ b/numpy/core/src/multiarray/multiarraymodule.c @@ -3282,30 +3282,6 @@ array_set_string_function(PyObject *NPY_UNUSED(self), PyObject *args, Py_RETURN_NONE; } -static PyObject * -array_set_ops_function(PyObject *NPY_UNUSED(self), PyObject *NPY_UNUSED(args), - PyObject *kwds) -{ - PyObject *oldops = NULL; - - if ((oldops = _PyArray_GetNumericOps()) == NULL) { - return NULL; - } - /* - * Should probably ensure that objects are at least callable - * Leave this to the caller for now --- error will be raised - * later when use is attempted - */ - if (kwds && PyArray_SetNumericOps(kwds) == -1) { - Py_DECREF(oldops); - if (PyErr_Occurred() == NULL) { - PyErr_SetString(PyExc_ValueError, - "one or more objects not callable"); - } - return NULL; - } - return oldops; -} static PyObject * array_set_datetimeparse_function(PyObject *NPY_UNUSED(self), @@ -4451,9 +4427,6 @@ static struct PyMethodDef array_module_methods[] = { {"set_string_function", (PyCFunction)array_set_string_function, METH_VARARGS|METH_KEYWORDS, NULL}, - {"set_numeric_ops", - (PyCFunction)array_set_ops_function, - METH_VARARGS|METH_KEYWORDS, NULL}, {"set_datetimeparse_function", (PyCFunction)array_set_datetimeparse_function, METH_VARARGS|METH_KEYWORDS, NULL}, diff --git a/numpy/core/src/multiarray/number.c b/numpy/core/src/multiarray/number.c index 35e4af79c8d7..2ab7a3f789d0 100644 --- a/numpy/core/src/multiarray/number.c +++ b/numpy/core/src/multiarray/number.c @@ -121,20 +121,6 @@ _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 && \ @@ -192,19 +178,6 @@ _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/tests/test_deprecations.py b/numpy/core/tests/test_deprecations.py index 7d512a11f23e..3f1d3e3c1ca5 100644 --- a/numpy/core/tests/test_deprecations.py +++ b/numpy/core/tests/test_deprecations.py @@ -356,18 +356,6 @@ def test_deprecate_unparsable_string(self, invalid_str): assert_array_equal(res, x) -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') - - class TestShape1Fields(_DeprecationTestCase): warning_cls = FutureWarning diff --git a/tools/functions_missing_types.py b/tools/functions_missing_types.py index 99c6887a981b..481e0720944f 100755 --- a/tools/functions_missing_types.py +++ b/tools/functions_missing_types.py @@ -43,7 +43,6 @@ "numarray", "oldnumeric", "safe_eval", - "set_numeric_ops", "test", "typeDict", # Builtins