summaryrefslogtreecommitdiff
path: root/numpy/core/function_base.py
diff options
context:
space:
mode:
authorEric Wieser <wieser.eric@gmail.com>2019-06-30 12:23:23 -0700
committerEric Wieser <wieser.eric@gmail.com>2019-07-14 11:31:57 -0700
commitd14632c603fc290207e38a10c2d9716ef1567666 (patch)
treed2515b15426f93e21f44fa2da20ab66b1c7a7e79 /numpy/core/function_base.py
parent45c4a8dc09ecaff6352a2e17cb242f7ae5ca11a9 (diff)
downloadnumpy-d14632c603fc290207e38a10c2d9716ef1567666.tar.gz
MAINT: Warn on the use of `_add_newdocs.py` to add docstrings to pure-python objects
This caught the duplication of docstrings between multiarray.py and _add_newdocs
Diffstat (limited to 'numpy/core/function_base.py')
-rw-r--r--numpy/core/function_base.py40
1 files changed, 34 insertions, 6 deletions
diff --git a/numpy/core/function_base.py b/numpy/core/function_base.py
index a316e072f..3964fff53 100644
--- a/numpy/core/function_base.py
+++ b/numpy/core/function_base.py
@@ -3,6 +3,7 @@ from __future__ import division, absolute_import, print_function
import functools
import warnings
import operator
+import types
from . import numeric as _nx
from .numeric import (result_type, NaN, shares_memory, MAY_SHARE_BOUNDS,
@@ -427,15 +428,39 @@ def geomspace(start, stop, num=50, endpoint=True, dtype=None, axis=0):
return result.astype(dtype, copy=False)
-#always succeed
-def _add_docstring(obj, doc):
+def _needs_add_docstring(obj):
+ """
+ Returns true if the only way to set the docstring of `obj` from python is
+ via add_docstring.
+
+ This function errs on the side of being overly conservative.
+ """
+ Py_TPFLAGS_HEAPTYPE = 1 << 9
+
+ if isinstance(obj, (types.FunctionType, types.MethodType, property)):
+ return False
+
+ if isinstance(obj, type) and obj.__flags__ & Py_TPFLAGS_HEAPTYPE:
+ return False
+
+ return True
+
+
+def _add_docstring(obj, doc, warn_on_python):
+ if warn_on_python and not _needs_add_docstring(obj):
+ warnings.warn(
+ "add_newdoc was used on a pure-python object {}. "
+ "Prefer to attach it directly to the source."
+ .format(obj),
+ UserWarning,
+ stacklevel=3)
try:
add_docstring(obj, doc)
except Exception:
pass
-def add_newdoc(place, obj, doc):
+def add_newdoc(place, obj, doc, warn_on_python=True):
"""
Add documentation to an existing object, typically one defined in C
@@ -457,6 +482,9 @@ def add_newdoc(place, obj, doc):
If a list, then each element of the list should be a tuple of length
two - ``[(method1, docstring1), (method2, docstring2), ...]``
+ warn_on_python : bool
+ If True, the default, emit `UserWarning` if this is used to attach
+ documentation to a pure-python object.
Notes
-----
@@ -480,10 +508,10 @@ def add_newdoc(place, obj, doc):
"""
new = getattr(__import__(place, globals(), {}, [obj]), obj)
if isinstance(doc, str):
- _add_docstring(new, doc.strip())
+ _add_docstring(new, doc.strip(), warn_on_python)
elif isinstance(doc, tuple):
attr, docstring = doc
- _add_docstring(getattr(new, attr), docstring.strip())
+ _add_docstring(getattr(new, attr), docstring.strip(), warn_on_python)
elif isinstance(doc, list):
for attr, docstring in doc:
- _add_docstring(getattr(new, attr), docstring.strip())
+ _add_docstring(getattr(new, attr), docstring.strip(), warn_on_python)