8000 BUG: Allow attaching documentation twice in add_docstring · numpy/numpy@ba14823 · GitHub
[go: up one dir, main page]

< 8000 div class="position-relative header-wrapper js-header-wrapper "> Skip to content

Commit ba14823

Browse files
committed
BUG: Allow attaching documentation twice in add_docstring
This is technically not a bug, but some IDEs and IPython have autoreload magic which can mean that NumPy gets reloaded a second time. This is not safe, but when it happens ignoring that an identical docstring is already attached fixes the issue.
1 parent d329a66 commit ba14823

File tree

2 files changed

+34
-3
lines changed

2 files changed

+34
-3
lines changed

numpy/core/src/multiarray/compiled_base.c

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1425,7 +1425,7 @@ arr_add_docstring(PyObject *NPY_UNUSED(dummy), PyObject *args)
14251425
#else
14261426
char *docstr;
14271427
#endif
1428-
static char *msg = "already has a docstring";
1428+
static char *msg = "already has a different docstring";
14291429
PyObject *tp_dict = PyArrayDescr_Type.tp_dict;
14301430
PyObject *myobj;
14311431
static PyTypeObject *PyMemberDescr_TypePtr = NULL;
@@ -1482,7 +1482,7 @@ arr_add_docstring(PyObject *NPY_UNUSED(dummy), PyObject *args)
14821482
if (!(doc)) { \
14831483
doc = docstr; \
14841484
} \
1485-
else { \
1485+
else if (strcmp(doc, docstr) != 0) { \
14861486
PyErr_Format(PyExc_RuntimeError, "%s method %s", name, msg); \
14871487
return NULL; \
14881488
} \
@@ -1507,7 +1507,12 @@ arr_add_docstring(PyObject *NPY_UNUSED(dummy), PyObject *args)
15071507
PyObject *doc_attr;
15081508

15091509
doc_attr = PyObject_GetAttrString(obj, "__doc__");
1510-
if (doc_attr != NULL && doc_attr != Py_None) {
1510+
if (doc_attr != NULL && doc_attr != Py_None &&
1511+
(PyUnicode_Compare(doc_attr, str) != 0)) {
1512+
if (PyErr_Occurred()) {
1513+
/* error during PyUnicode_Compare */
1514+
return NULL;
1515+
}
15111516
PyErr_Format(PyExc_RuntimeError, "object %s", msg);
15121517
return NULL;
15131518
}

numpy/tests/test_reloading.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
11
from numpy.testing import assert_raises, assert_, assert_equal
22
from numpy.compat import pickle
33

4+
import sys
5+
import subprocess
6+
import textwrap
47
from importlib import reload
58

9+
610
def test_numpy_reloading():
711
# gh-7844. Also check that relevant globals retain their identity.
812
import numpy as np
@@ -29,3 +33,25 @@ def test_novalue():
2933
assert_equal(repr(np._NoValue), '<no value>')
3034
assert_(pickle.loads(pickle.dumps(np._NoValue,
3135
protocol=proto)) is np._NoValue)
36+
37+
38+
def test_full_reimport():
39+
"""At the time of writing this, it is *not* truly supported, but
40+
apparently enough users rely on it, for it to be an annoying change
41+
when it started failing previously.
42+
"""
43+
# Test within a new process, to ensure that we do not mess with the
44+
# global state during the test run (could lead to cryptic test failures).
45+
# This is generally unsafe, especially, since we also reload the C-modules.
46+
code = textwrap.dedent(r"""
47+
import sys
48+
import numpy as np
49+
50+
for k in list(sys.modules.keys()):
51+
if "numpy" in k:
52+
del sys.modules[k]
53+
54+
import numpy as np
55+
""")
56+
p = subprocess.run([sys.executable, '-c', code])
57+
assert p.returncode == 0

0 commit comments

Comments
 (0)
0