diff options
author | Matti Picus <matti.picus@gmail.com> | 2020-05-20 18:14:08 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-05-20 18:14:08 +0300 |
commit | 78d7ab3d0c35cb8aa0cdf449e0db1472e6ad60dc (patch) | |
tree | b42ceb6a82d8035d5cd5a299a04a6726db1974d5 | |
parent | dcf1614dfc11f9004e408ed8c833980c951c541e (diff) | |
parent | ffdce8b4ddf725d9f4329a745d6bfad9b5716774 (diff) | |
download | numpy-78d7ab3d0c35cb8aa0cdf449e0db1472e6ad60dc.tar.gz |
Merge pull request #16239 from seberg/reimport-do-not-set-docs
BUG,DOC: Allow attach docs twice but error if wrong
-rw-r--r-- | numpy/core/_add_newdocs.py | 678 | ||||
-rw-r--r-- | numpy/core/src/multiarray/compiled_base.c | 80 | ||||
-rw-r--r-- | numpy/core/src/multiarray/scalartypes.c.src | 56 | ||||
-rw-r--r-- | numpy/lib/tests/test_function_base.py | 40 | ||||
-rw-r--r-- | numpy/tests/test_reloading.py | 26 |
5 files changed, 214 insertions, 666 deletions
diff --git a/numpy/core/_add_newdocs.py b/numpy/core/_add_newdocs.py index f43b77c44..20ad39b05 100644 --- a/numpy/core/_add_newdocs.py +++ b/numpy/core/_add_newdocs.py @@ -5901,29 +5901,21 @@ add_newdoc('numpy.core.numerictypes', 'generic', # Attributes -add_newdoc('numpy.core.numerictypes', 'generic', ('T', - """ - Not implemented (virtual attribute) - - Class generic exists solely to derive numpy scalars from, and possesses, - albeit unimplemented, all the attributes of the ndarray class so as to - provide a uniform API. - - See also the corresponding attribute of the derived class of interest. - - """)) +def refer_to_array_attribute(attr, method=True): + docstring = """ + Scalar {} identical to the corresponding array attribute. -add_newdoc('numpy.core.numerictypes', 'generic', ('base', + Please see `ndarray.{}`. """ - Not implemented (virtual attribute) - Class generic exists solely to derive numpy scalars from, and possesses, - albeit unimplemented, all the attributes of the ndarray class so as to - a uniform API. + return attr, docstring.format("method" if method else "attribute", attr) - See also the corresponding attribute of the derived class of interest. - """)) +add_newdoc('numpy.core.numerictypes', 'generic', + refer_to_array_attribute('T', method=False)) + +add_newdoc('numpy.core.numerictypes', 'generic', + refer_to_array_attribute('base', method=False)) add_newdoc('numpy.core.numerictypes', 'generic', ('data', """Pointer to start of data.""")) @@ -5963,305 +5955,80 @@ add_newdoc('numpy.core.numerictypes', 'generic', ('strides', # Methods -add_newdoc('numpy.core.numerictypes', 'generic', ('all', - """ - Not implemented (virtual attribute) - - Class generic exists solely to derive numpy scalars from, and possesses, - albeit unimplemented, all the attributes of the ndarray class - so as to provide a uniform API. - - See also the corresponding attribute of the derived class of interest. - - """)) - -add_newdoc('numpy.core.numerictypes', 'generic', ('any', - """ - Not implemented (virtual attribute) - - Class generic exists solely to derive numpy scalars from, and possesses, - albeit unimplemented, all the attributes of the ndarray class - so as to provide a uniform API. - - See also the corresponding attribute of the derived class of interest. - - """)) - -add_newdoc('numpy.core.numerictypes', 'generic', ('argmax', - """ - Not implemented (virtual attribute) - - Class generic exists solely to derive numpy scalars from, and possesses, - albeit unimplemented, all the attributes of the ndarray class - so as to provide a uniform API. - - See also the corresponding attribute of the derived class of interest. - - """)) - -add_newdoc('numpy.core.numerictypes', 'generic', ('argmin', - """ - Not implemented (virtual attribute) - - Class generic exists solely to derive numpy scalars from, and possesses, - albeit unimplemented, all the attributes of the ndarray class - so as to provide a uniform API. - - See also the corresponding attribute of the derived class of interest. - - """)) - -add_newdoc('numpy.core.numerictypes', 'generic', ('argsort', - """ - Not implemented (virtual attribute) - - Class generic exists solely to derive numpy scalars from, and possesses, - albeit unimplemented, all the attributes of the ndarray class - so as to provide a uniform API. - - See also the corresponding attribute of the derived class of interest. - - """)) - -add_newdoc('numpy.core.numerictypes', 'generic', ('astype', - """ - Not implemented (virtual attribute) - - Class generic exists solely to derive numpy scalars from, and possesses, - albeit unimplemented, all the attributes of the ndarray class - so as to provide a uniform API. - - See also the corresponding attribute of the derived class of interest. - - """)) - -add_newdoc('numpy.core.numerictypes', 'generic', ('byteswap', - """ - Not implemented (virtual attribute) - - Class generic exists solely to derive numpy scalars from, and possesses, - albeit unimplemented, all the attributes of the ndarray class so as to - provide a uniform API. - - See also the corresponding attribute of the derived class of interest. - - """)) - -add_newdoc('numpy.core.numerictypes', 'generic', ('choose', - """ - Not implemented (virtual attribute) - - Class generic exists solely to derive numpy scalars from, and possesses, - albeit unimplemented, all the attributes of the ndarray class - so as to provide a uniform API. - - See also the corresponding attribute of the derived class of interest. - - """)) - -add_newdoc('numpy.core.numerictypes', 'generic', ('clip', - """ - Not implemented (virtual attribute) - - Class generic exists solely to derive numpy scalars from, and possesses, - albeit unimplemented, all the attributes of the ndarray class - so as to provide a uniform API. - - See also the corresponding attribute of the derived class of interest. - - """)) - -add_newdoc('numpy.core.numerictypes', 'generic', ('compress', - """ - Not implemented (virtual attribute) - - Class generic exists solely to derive numpy scalars from, and possesses, - albeit unimplemented, all the attributes of the ndarray class - so as to provide a uniform API. - - See also the corresponding attribute of the derived class of interest. - - """)) - -add_newdoc('numpy.core.numerictypes', 'generic', ('conjugate', - """ - Not implemented (virtual attribute) - - Class generic exists solely to derive numpy scalars from, and possesses, - albeit unimplemented, all the attributes of the ndarray class - so as to provide a uniform API. - - See also the corresponding attribute of the derived class of interest. - - """)) - -add_newdoc('numpy.core.numerictypes', 'generic', ('copy', - """ - Not implemented (virtual attribute) - - Class generic exists solely to derive numpy scalars from, and possesses, - albeit unimplemented, all the attributes of the ndarray class - so as to provide a uniform API. - - See also the corresponding attribute of the derived class of interest. - - """)) - -add_newdoc('numpy.core.numerictypes', 'generic', ('cumprod', - """ - Not implemented (virtual attribute) - - Class generic exists solely to derive numpy scalars from, and possesses, - albeit unimplemented, all the attributes of the ndarray class - so as to provide a uniform API. - - See also the corresponding attribute of the derived class of interest. - - """)) - -add_newdoc('numpy.core.numerictypes', 'generic', ('cumsum', - """ - Not implemented (virtual attribute) - - Class generic exists solely to derive numpy scalars from, and possesses, - albeit unimplemented, all the attributes of the ndarray class - so as to provide a uniform API. - - See also the corresponding attribute of the derived class of interest. - - """)) - -add_newdoc('numpy.core.numerictypes', 'generic', ('diagonal', - """ - Not implemented (virtual attribute) - - Class generic exists solely to derive numpy scalars from, and possesses, - albeit unimplemented, all the attributes of the ndarray class - so as to provide a uniform API. - - See also the corresponding attribute of the derived class of interest. - - """)) - -add_newdoc('numpy.core.numerictypes', 'generic', ('dump', - """ - Not implemented (virtual attribute) - - Class generic exists solely to derive numpy scalars from, and possesses, - albeit unimplemented, all the attributes of the ndarray class - so as to provide a uniform API. - - See also the corresponding attribute of the derived class of interest. - - """)) - -add_newdoc('numpy.core.numerictypes', 'generic', ('dumps', - """ - Not implemented (virtual attribute) - - Class generic exists solely to derive numpy scalars from, and possesses, - albeit unimplemented, all the attributes of the ndarray class - so as to provide a uniform API. - - See also the corresponding attribute of the derived class of interest. - - """)) - -add_newdoc('numpy.core.numerictypes', 'generic', ('fill', - """ - Not implemented (virtual attribute) - - Class generic exists solely to derive numpy scalars from, and possesses, - albeit unimplemented, all the attributes of the ndarray class - so as to provide a uniform API. - - See also the corresponding attribute of the derived class of interest. - - """)) - -add_newdoc('numpy.core.numerictypes', 'generic', ('flatten', - """ - Not implemented (virtual attribute) - - Class generic exists solely to derive numpy scalars from, and possesses, - albeit unimplemented, all the attributes of the ndarray class - so as to provide a uniform API. - - See also the corresponding attribute of the derived class of interest. - - """)) +add_newdoc('numpy.core.numerictypes', 'generic', + refer_to_array_attribute('all')) -add_newdoc('numpy.core.numerictypes', 'generic', ('getfield', - """ - Not implemented (virtual attribute) +add_newdoc('numpy.core.numerictypes', 'generic', + refer_to_array_attribute('any')) - Class generic exists solely to derive numpy scalars from, and possesses, - albeit unimplemented, all the attributes of the ndarray class - so as to provide a uniform API. +add_newdoc('numpy.core.numerictypes', 'generic', + refer_to_array_attribute('argmax')) - See also the corresponding attribute of the derived class of interest. +add_newdoc('numpy.core.numerictypes', 'generic', + refer_to_array_attribute('argmin')) - """)) +add_newdoc('numpy.core.numerictypes', 'generic', + refer_to_array_attribute('argsort')) -add_newdoc('numpy.core.numerictypes', 'generic', ('item', - """ - Not implemented (virtual attribute) +add_newdoc('numpy.core.numerictypes', 'generic', + refer_to_array_attribute('astype')) - Class generic exists solely to derive numpy scalars from, and possesses, - albeit unimplemented, all the attributes of the ndarray class - so as to provide a uniform API. +add_newdoc('numpy.core.numerictypes', 'generic', + refer_to_array_attribute('byteswap')) - See also the corresponding attribute of the derived class of interest. +add_newdoc('numpy.core.numerictypes', 'generic', + refer_to_array_attribute('choose')) - """)) +add_newdoc('numpy.core.numerictypes', 'generic', + refer_to_array_attribute('clip')) -add_newdoc('numpy.core.numerictypes', 'generic', ('itemset', - """ - Not implemented (virtual attribute) +add_newdoc('numpy.core.numerictypes', 'generic', + refer_to_array_attribute('compress')) - Class generic exists solely to derive numpy scalars from, and possesses, - albeit unimplemented, all the attributes of the ndarray class - so as to provide a uniform API. +add_newdoc('numpy.core.numerictypes', 'generic', + refer_to_array_attribute('conjugate')) - See also the corresponding attribute of the derived class of interest. +add_newdoc('numpy.core.numerictypes', 'generic', + refer_to_array_attribute('copy')) - """)) +add_newdoc('numpy.core.numerictypes', 'generic', + refer_to_array_attribute('cumprod')) -add_newdoc('numpy.core.numerictypes', 'generic', ('max', - """ - Not implemented (virtual attribute) +add_newdoc('numpy.core.numerictypes', 'generic', + refer_to_array_attribute('cumsum')) - Class generic exists solely to derive numpy scalars from, and possesses, - albeit unimplemented, all the attributes of the ndarray class - so as to provide a uniform API. +add_newdoc('numpy.core.numerictypes', 'generic', + refer_to_array_attribute('diagonal')) - See also the corresponding attribute of the derived class of interest. +add_newdoc('numpy.core.numerictypes', 'generic', + refer_to_array_attribute('dump')) - """)) +add_newdoc('numpy.core.numerictypes', 'generic', + refer_to_array_attribute('dumps')) -add_newdoc('numpy.core.numerictypes', 'generic', ('mean', - """ - Not implemented (virtual attribute) +add_newdoc('numpy.core.numerictypes', 'generic', + refer_to_array_attribute('fill')) - Class generic exists solely to derive numpy scalars from, and possesses, - albeit unimplemented, all the attributes of the ndarray class - so as to provide a uniform API. +add_newdoc('numpy.core.numerictypes', 'generic', + refer_to_array_attribute('flatten')) - See also the corresponding attribute of the derived class of interest. +add_newdoc('numpy.core.numerictypes', 'generic', + refer_to_array_attribute('getfield')) - """)) +add_newdoc('numpy.core.numerictypes', 'generic', + refer_to_array_attribute('item')) -add_newdoc('numpy.core.numerictypes', 'generic', ('min', - """ - Not implemented (virtual attribute) +add_newdoc('numpy.core.numerictypes', 'generic', + refer_to_array_attribute('itemset')) - Class generic exists solely to derive numpy scalars from, and possesses, - albeit unimplemented, all the attributes of the ndarray class - so as to provide a uniform API. +add_newdoc('numpy.core.numerictypes', 'generic', + refer_to_array_attribute('max')) - See also the corresponding attribute of the derived class of interest. +add_newdoc('numpy.core.numerictypes', 'generic', + refer_to_array_attribute('mean')) - """)) +add_newdoc('numpy.core.numerictypes', 'generic', + refer_to_array_attribute('min')) add_newdoc('numpy.core.numerictypes', 'generic', ('newbyteorder', """ @@ -6296,305 +6063,80 @@ add_newdoc('numpy.core.numerictypes', 'generic', ('newbyteorder', """)) -add_newdoc('numpy.core.numerictypes', 'generic', ('nonzero', - """ - Not implemented (virtual attribute) - - Class generic exists solely to derive numpy scalars from, and possesses, - albeit unimplemented, all the attributes of the ndarray class - so as to provide a uniform API. - - See also the corresponding attribute of the derived class of interest. - - """)) - -add_newdoc('numpy.core.numerictypes', 'generic', ('prod', - """ - Not implemented (virtual attribute) - - Class generic exists solely to derive numpy scalars from, and possesses, - albeit unimplemented, all the attributes of the ndarray class - so as to provide a uniform API. - - See also the corresponding attribute of the derived class of interest. - - """)) - -add_newdoc('numpy.core.numerictypes', 'generic', ('ptp', - """ - Not implemented (virtual attribute) - - Class generic exists solely to derive numpy scalars from, and possesses, - albeit unimplemented, all the attributes of the ndarray class - so as to provide a uniform API. - - See also the corresponding attribute of the derived class of interest. - - """)) - -add_newdoc('numpy.core.numerictypes', 'generic', ('put', - """ - Not implemented (virtual attribute) - - Class generic exists solely to derive numpy scalars from, and possesses, - albeit unimplemented, all the attributes of the ndarray class - so as to provide a uniform API. - - See also the corresponding attribute of the derived class of interest. - - """)) - -add_newdoc('numpy.core.numerictypes', 'generic', ('ravel', - """ - Not implemented (virtual attribute) - - Class generic exists solely to derive numpy scalars from, and possesses, - albeit unimplemented, all the attributes of the ndarray class - so as to provide a uniform API. - - See also the corresponding attribute of the derived class of interest. - - """)) - -add_newdoc('numpy.core.numerictypes', 'generic', ('repeat', - """ - Not implemented (virtual attribute) - - Class generic exists solely to derive numpy scalars from, and possesses, - albeit unimplemented, all the attributes of the ndarray class - so as to provide a uniform API. - - See also the corresponding attribute of the derived class of interest. - - """)) - -add_newdoc('numpy.core.numerictypes', 'generic', ('reshape', - """ - Not implemented (virtual attribute) - - Class generic exists solely to derive numpy scalars from, and possesses, - albeit unimplemented, all the attributes of the ndarray class - so as to provide a uniform API. - - See also the corresponding attribute of the derived class of interest. - - """)) - -add_newdoc('numpy.core.numerictypes', 'generic', ('resize', - """ - Not implemented (virtual attribute) - - Class generic exists solely to derive numpy scalars from, and possesses, - albeit unimplemented, all the attributes of the ndarray class - so as to provide a uniform API. - - See also the corresponding attribute of the derived class of interest. - - """)) - -add_newdoc('numpy.core.numerictypes', 'generic', ('round', - """ - Not implemented (virtual attribute) - - Class generic exists solely to derive numpy scalars from, and possesses, - albeit unimplemented, all the attributes of the ndarray class - so as to provide a uniform API. - - See also the corresponding attribute of the derived class of interest. - - """)) - -add_newdoc('numpy.core.numerictypes', 'generic', ('searchsorted', - """ - Not implemented (virtual attribute) - - Class generic exists solely to derive numpy scalars from, and possesses, - albeit unimplemented, all the attributes of the ndarray class - so as to provide a uniform API. - - See also the corresponding attribute of the derived class of interest. - - """)) - -add_newdoc('numpy.core.numerictypes', 'generic', ('setfield', - """ - Not implemented (virtual attribute) - - Class generic exists solely to derive numpy scalars from, and possesses, - albeit unimplemented, all the attributes of the ndarray class - so as to provide a uniform API. - - See also the corresponding attribute of the derived class of interest. - - """)) - -add_newdoc('numpy.core.numerictypes', 'generic', ('setflags', - """ - Not implemented (virtual attribute) - - Class generic exists solely to derive numpy scalars from, and possesses, - albeit unimplemented, all the attributes of the ndarray class so as to - provide a uniform API. - - See also the corresponding attribute of the derived class of interest. - - """)) - -add_newdoc('numpy.core.numerictypes', 'generic', ('sort', - """ - Not implemented (virtual attribute) - - Class generic exists solely to derive numpy scalars from, and possesses, - albeit unimplemented, all the attributes of the ndarray class - so as to provide a uniform API. - - See also the corresponding attribute of the derived class of interest. - - """)) - -add_newdoc('numpy.core.numerictypes', 'generic', ('squeeze', - """ - Not implemented (virtual attribute) - - Class generic exists solely to derive numpy scalars from, and possesses, - albeit unimplemented, all the attributes of the ndarray class - so as to provide a uniform API. - - See also the corresponding attribute of the derived class of interest. - - """)) - -add_newdoc('numpy.core.numerictypes', 'generic', ('std', - """ - Not implemented (virtual attribute) - - Class generic exists solely to derive numpy scalars from, and possesses, - albeit unimplemented, all the attributes of the ndarray class - so as to provide a uniform API. - - See also the corresponding attribute of the derived class of interest. - - """)) - -add_newdoc('numpy.core.numerictypes', 'generic', ('sum', - """ - Not implemented (virtual attribute) - - Class generic exists solely to derive numpy scalars from, and possesses, - albeit unimplemented, all the attributes of the ndarray class - so as to provide a uniform API. - - See also the corresponding attribute of the derived class of interest. - - """)) - -add_newdoc('numpy.core.numerictypes', 'generic', ('swapaxes', - """ - Not implemented (virtual attribute) - - Class generic exists solely to derive numpy scalars from, and possesses, - albeit unimplemented, all the attributes of the ndarray class - so as to provide a uniform API. - - See also the corresponding attribute of the derived class of interest. - - """)) - -add_newdoc('numpy.core.numerictypes', 'generic', ('take', - """ - Not implemented (virtual attribute) - - Class generic exists solely to derive numpy scalars from, and possesses, - albeit unimplemented, all the attributes of the ndarray class - so as to provide a uniform API. - - See also the corresponding attribute of the derived class of interest. - - """)) - -add_newdoc('numpy.core.numerictypes', 'generic', ('tofile', - """ - Not implemented (virtual attribute) - - Class generic exists solely to derive numpy scalars from, and possesses, - albeit unimplemented, all the attributes of the ndarray class - so as to provide a uniform API. - - See also the corresponding attribute of the derived class of interest. - - """)) +add_newdoc('numpy.core.numerictypes', 'generic', + refer_to_array_attribute('nonzero')) -add_newdoc('numpy.core.numerictypes', 'generic', ('tolist', - """ - Not implemented (virtual attribute) +add_newdoc('numpy.core.numerictypes', 'generic', + refer_to_array_attribute('prod')) - Class generic exists solely to derive numpy scalars from, and possesses, - albeit unimplemented, all the attributes of the ndarray class - so as to provide a uniform API. +add_newdoc('numpy.core.numerictypes', 'generic', + refer_to_array_attribute('ptp')) - See also the corresponding attribute of the derived class of interest. +add_newdoc('numpy.core.numerictypes', 'generic', + refer_to_array_attribute('put')) - """)) +add_newdoc('numpy.core.numerictypes', 'generic', + refer_to_array_attribute('ravel')) -add_newdoc('numpy.core.numerictypes', 'generic', ('tostring', - """ - Not implemented (virtual attribute) +add_newdoc('numpy.core.numerictypes', 'generic', + refer_to_array_attribute('repeat')) - Class generic exists solely to derive numpy scalars from, and possesses, - albeit unimplemented, all the attributes of the ndarray class - so as to provide a uniform API. +add_newdoc('numpy.core.numerictypes', 'generic', + refer_to_array_attribute('reshape')) - See also the corresponding attribute of the derived class of interest. +add_newdoc('numpy.core.numerictypes', 'generic', + refer_to_array_attribute('resize')) - """)) +add_newdoc('numpy.core.numerictypes', 'generic', + refer_to_array_attribute('round')) -add_newdoc('numpy.core.numerictypes', 'generic', ('trace', - """ - Not implemented (virtual attribute) +add_newdoc('numpy.core.numerictypes', 'generic', + refer_to_array_attribute('searchsorted')) - Class generic exists solely to derive numpy scalars from, and possesses, - albeit unimplemented, all the attributes of the ndarray class - so as to provide a uniform API. +add_newdoc('numpy.core.numerictypes', 'generic', + refer_to_array_attribute('setfield')) - See also the corresponding attribute of the derived class of interest. +add_newdoc('numpy.core.numerictypes', 'generic', + refer_to_array_attribute('setflags')) - """)) +add_newdoc('numpy.core.numerictypes', 'generic', + refer_to_array_attribute('sort')) -add_newdoc('numpy.core.numerictypes', 'generic', ('transpose', - """ - Not implemented (virtual attribute) +add_newdoc('numpy.core.numerictypes', 'generic', + refer_to_array_attribute('squeeze')) - Class generic exists solely to derive numpy scalars from, and possesses, - albeit unimplemented, all the attributes of the ndarray class - so as to provide a uniform API. +add_newdoc('numpy.core.numerictypes', 'generic', + refer_to_array_attribute('std')) - See also the corresponding attribute of the derived class of interest. +add_newdoc('numpy.core.numerictypes', 'generic', + refer_to_array_attribute('sum')) - """)) +add_newdoc('numpy.core.numerictypes', 'generic', + refer_to_array_attribute('swapaxes')) -add_newdoc('numpy.core.numerictypes', 'generic', ('var', - """ - Not implemented (virtual attribute) +add_newdoc('numpy.core.numerictypes', 'generic', + refer_to_array_attribute('take')) - Class generic exists solely to derive numpy scalars from, and possesses, - albeit unimplemented, all the attributes of the ndarray class - so as to provide a uniform API. +add_newdoc('numpy.core.numerictypes', 'generic', + refer_to_array_attribute('tofile')) - See also the corresponding attribute of the derived class of interest. +add_newdoc('numpy.core.numerictypes', 'generic', + refer_to_array_attribute('tolist')) - """)) +add_newdoc('numpy.core.numerictypes', 'generic', + refer_to_array_attribute('tostring')) -add_newdoc('numpy.core.numerictypes', 'generic', ('view', - """ - Not implemented (virtual attribute) +add_newdoc('numpy.core.numerictypes', 'generic', + refer_to_array_attribute('trace')) - Class generic exists solely to derive numpy scalars from, and possesses, - albeit unimplemented, all the attributes of the ndarray class - so as to provide a uniform API. +add_newdoc('numpy.core.numerictypes', 'generic', + refer_to_array_attribute('transpose')) - See also the corresponding attribute of the derived class of interest. +add_newdoc('numpy.core.numerictypes', 'generic', + refer_to_array_attribute('var')) - """)) +add_newdoc('numpy.core.numerictypes', 'generic', + refer_to_array_attribute('view')) ############################################################################## diff --git a/numpy/core/src/multiarray/compiled_base.c b/numpy/core/src/multiarray/compiled_base.c index 308e72009..b63bca368 100644 --- a/numpy/core/src/multiarray/compiled_base.c +++ b/numpy/core/src/multiarray/compiled_base.c @@ -1425,47 +1425,13 @@ arr_add_docstring(PyObject *NPY_UNUSED(dummy), PyObject *args) #else char *docstr; #endif - static char *msg = "already has a docstring"; - PyObject *tp_dict = PyArrayDescr_Type.tp_dict; - PyObject *myobj; - static PyTypeObject *PyMemberDescr_TypePtr = NULL; - static PyTypeObject *PyGetSetDescr_TypePtr = NULL; - static PyTypeObject *PyMethodDescr_TypePtr = NULL; + static char *msg = "already has a different docstring"; /* Don't add docstrings */ if (Py_OptimizeFlag > 1) { Py_RETURN_NONE; } - if (PyGetSetDescr_TypePtr == NULL) { - /* Get "subdescr" */ - myobj = _PyDict_GetItemStringWithError(tp_dict, "fields"); - if (myobj == NULL && PyErr_Occurred()) { - return NULL; - } - if (myobj != NULL) { - PyGetSetDescr_TypePtr = Py_TYPE(myobj); - } - } - if (PyMemberDescr_TypePtr == NULL) { - myobj = _PyDict_GetItemStringWithError(tp_dict, "alignment"); - if (myobj == NULL && PyErr_Occurred()) { - return NULL; - } - if (myobj != NULL) { - PyMemberDescr_TypePtr = Py_TYPE(myobj); - } - } - if (PyMethodDescr_TypePtr == NULL) { - myobj = _PyDict_GetItemStringWithError(tp_dict, "newbyteorder"); - if (myobj == NULL && PyErr_Occurred()) { - return NULL; - } - if (myobj != NULL) { - PyMethodDescr_TypePtr = Py_TYPE(myobj); - } - } - if (!PyArg_ParseTuple(args, "OO!:add_docstring", &obj, &PyUnicode_Type, &str)) { return NULL; } @@ -1475,39 +1441,45 @@ arr_add_docstring(PyObject *NPY_UNUSED(dummy), PyObject *args) return NULL; } -#define _TESTDOC1(typebase) (Py_TYPE(obj) == &Py##typebase##_Type) -#define _TESTDOC2(typebase) (Py_TYPE(obj) == Py##typebase##_TypePtr) -#define _ADDDOC(typebase, doc, name) do { \ - Py##typebase##Object *new = (Py##typebase##Object *)obj; \ +#define _ADDDOC(doc, name) \ if (!(doc)) { \ doc = docstr; \ } \ - else { \ + else if (strcmp(doc, docstr) != 0) { \ PyErr_Format(PyExc_RuntimeError, "%s method %s", name, msg); \ return NULL; \ - } \ - } while (0) + } - if (_TESTDOC1(CFunction)) { - _ADDDOC(CFunction, new->m_ml->ml_doc, new->m_ml->ml_name); + if (Py_TYPE(obj) == &PyCFunction_Type) { + PyCFunctionObject *new = (PyCFunctionObject *)obj; + _ADDDOC(new->m_ml->ml_doc, new->m_ml->ml_name); } - else if (_TESTDOC1(Type)) { - _ADDDOC(Type, new->tp_doc, new->tp_name); + else if (Py_TYPE(obj) == &PyType_Type) { + PyTypeObject *new = (PyTypeObject *)obj; + _ADDDOC(new->tp_doc, new->tp_name); } - else if (_TESTDOC2(MemberDescr)) { - _ADDDOC(MemberDescr, new->d_member->doc, new->d_member->name); + else if (Py_TYPE(obj) == &PyMemberDescr_Type) { + PyMemberDescrObject *new = (PyMemberDescrObject *)obj; + _ADDDOC(new->d_member->doc, new->d_member->name); } - else if (_TESTDOC2(GetSetDescr)) { - _ADDDOC(GetSetDescr, new->d_getset->doc, new->d_getset->name); + else if (Py_TYPE(obj) == &PyGetSetDescr_Type) { + PyGetSetDescrObject *new = (PyGetSetDescrObject *)obj; + _ADDDOC(new->d_getset->doc, new->d_getset->name); } - else if (_TESTDOC2(MethodDescr)) { - _ADDDOC(MethodDescr, new->d_method->ml_doc, new->d_method->ml_name); + else if (Py_TYPE(obj) == &PyMethodDescr_Type) { + PyMethodDescrObject *new = (PyMethodDescrObject *)obj; + _ADDDOC(new->d_method->ml_doc, new->d_method->ml_name); } else { PyObject *doc_attr; doc_attr = PyObject_GetAttrString(obj, "__doc__"); - if (doc_attr != NULL && doc_attr != Py_None) { + if (doc_attr != NULL && doc_attr != Py_None && + (PyUnicode_Compare(doc_attr, str) != 0)) { + if (PyErr_Occurred()) { + /* error during PyUnicode_Compare */ + return NULL; + } PyErr_Format(PyExc_RuntimeError, "object %s", msg); return NULL; } @@ -1521,8 +1493,6 @@ arr_add_docstring(PyObject *NPY_UNUSED(dummy), PyObject *args) Py_RETURN_NONE; } -#undef _TESTDOC1 -#undef _TESTDOC2 #undef _ADDDOC Py_INCREF(str); diff --git a/numpy/core/src/multiarray/scalartypes.c.src b/numpy/core/src/multiarray/scalartypes.c.src index 2f1767391..f13f50759 100644 --- a/numpy/core/src/multiarray/scalartypes.c.src +++ b/numpy/core/src/multiarray/scalartypes.c.src @@ -1333,74 +1333,46 @@ gentype_transpose_get(PyObject *self) static PyGetSetDef gentype_getsets[] = { {"ndim", (getter)gentype_ndim_get, - (setter) 0, - "number of array dimensions", - NULL}, + (setter) 0, NULL, NULL}, {"flags", (getter)gentype_flags_get, - (setter)0, - "integer value of flags", - NULL}, + (setter)0, NULL, NULL}, {"shape", (getter)gentype_shape_get, - (setter)0, - "tuple of array dimensions", - NULL}, + (setter)0, NULL, NULL}, {"strides", (getter)gentype_shape_get, - (setter) 0, - "tuple of bytes steps in each dimension", - NULL}, + (setter) 0, NULL, NULL}, {"data", (getter)gentype_data_get, - (setter) 0, - "pointer to start of data", - NULL}, + (setter) 0, NULL, NULL}, {"itemsize", (getter)gentype_itemsize_get, - (setter)0, - "length of one element in bytes", - NULL}, + (setter)0, NULL, NULL}, {"size", (getter)gentype_size_get, - (setter)0, - "number of elements in the gentype", - NULL}, + (setter)0, NULL, NULL}, {"nbytes", (getter)gentype_itemsize_get, - (setter)0, - "length of item in bytes", - NULL}, + (setter)0, NULL, NULL}, {"base", (getter)gentype_base_get, - (setter)0, - "base object", - NULL}, + (setter)0, NULL, NULL}, {"dtype", (getter)gentype_typedescr_get, - NULL, - "get array data-descriptor", - NULL}, + NULL, NULL, NULL}, {"real", (getter)gentype_real_get, - (setter)0, - "real part of scalar", - NULL}, + (setter)0, NULL, NULL}, {"imag", (getter)gentype_imag_get, - (setter)0, - "imaginary part of scalar", - NULL}, + (setter)0, NULL, NULL}, {"flat", (getter)gentype_flat_get, - (setter)0, - "a 1-d view of scalar", - NULL}, + (setter)0, NULL, NULL}, {"T", (getter)gentype_transpose_get, - (setter)0, - "transpose", - NULL}, + (setter)0, NULL, NULL}, {"__array_interface__", (getter)gentype_interface_get, NULL, diff --git a/numpy/lib/tests/test_function_base.py b/numpy/lib/tests/test_function_base.py index b4e928273..008ea0759 100644 --- a/numpy/lib/tests/test_function_base.py +++ b/numpy/lib/tests/test_function_base.py @@ -3350,12 +3350,50 @@ class TestAdd_newdoc: @pytest.mark.skipif(sys.flags.optimize == 2, reason="Python running -OO") @pytest.mark.xfail(IS_PYPY, reason="PyPy does not modify tp_doc") def test_add_doc(self): - # test np.add_newdoc + # test that np.add_newdoc did attach a docstring successfully: tgt = "Current flat index into the array." assert_equal(np.core.flatiter.index.__doc__[:len(tgt)], tgt) assert_(len(np.core.ufunc.identity.__doc__) > 300) assert_(len(np.lib.index_tricks.mgrid.__doc__) > 300) + @pytest.mark.skipif(sys.flags.optimize == 2, reason="Python running -OO") + def test_errors_are_ignored(self): + prev_doc = np.core.flatiter.index.__doc__ + # nothing changed, but error ignored, this should probably + # give a warning (or even error) in the future. + np.add_newdoc("numpy.core", "flatiter", ("index", "bad docstring")) + assert prev_doc == np.core.flatiter.index.__doc__ + + +class TestAddDocstring(): + # Test should possibly be moved, but it also fits to be close to + # the newdoc tests... + @pytest.mark.skipif(sys.flags.optimize == 2, reason="Python running -OO") + @pytest.mark.skipif(IS_PYPY, reason="PyPy does not modify tp_doc") + def test_add_same_docstring(self): + # test for attributes (which are C-level defined) + np.add_docstring(np.ndarray.flat, np.ndarray.flat.__doc__) + # And typical functions: + def func(): + """docstring""" + return + + np.add_docstring(func, func.__doc__) + + @pytest.mark.skipif(sys.flags.optimize == 2, reason="Python running -OO") + def test_different_docstring_fails(self): + # test for attributes (which are C-level defined) + with assert_raises(RuntimeError): + np.add_docstring(np.ndarray.flat, "different docstring") + # And typical functions: + def func(): + """docstring""" + return + + with assert_raises(RuntimeError): + np.add_docstring(func, "different docstring") + + class TestSortComplex: @pytest.mark.parametrize("type_in, type_out", [ diff --git a/numpy/tests/test_reloading.py b/numpy/tests/test_reloading.py index 860832be8..61ae91b00 100644 --- a/numpy/tests/test_reloading.py +++ b/numpy/tests/test_reloading.py @@ -1,8 +1,12 @@ from numpy.testing import assert_raises, assert_, assert_equal from numpy.compat import pickle +import sys +import subprocess +import textwrap from importlib import reload + def test_numpy_reloading(): # gh-7844. Also check that relevant globals retain their identity. import numpy as np @@ -29,3 +33,25 @@ def test_novalue(): assert_equal(repr(np._NoValue), '<no value>') assert_(pickle.loads(pickle.dumps(np._NoValue, protocol=proto)) is np._NoValue) + + +def test_full_reimport(): + """At the time of writing this, it is *not* truly supported, but + apparently enough users rely on it, for it to be an annoying change + when it started failing previously. + """ + # Test within a new process, to ensure that we do not mess with the + # global state during the test run (could lead to cryptic test failures). + # This is generally unsafe, especially, since we also reload the C-modules. + code = textwrap.dedent(r""" + import sys + import numpy as np + + for k in list(sys.modules.keys()): + if "numpy" in k: + del sys.modules[k] + + import numpy as np + """) + p = subprocess.run([sys.executable, '-c', code]) + assert p.returncode == 0 |