3
3
import functools
4
4
import warnings
5
5
import operator
6
+ import types
6
7
7
8
from . import numeric as _nx
8
9
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):
427
428
return result .astype (dtype , copy = False )
428
429
429
430
430
- #always succeed
431
- def _add_docstring (obj , doc ):
431
+ def _needs_add_docstring (obj ):
432
+ """
433
+ Returns true if the only way to set the docstring of `obj` from python is
434
+ via add_docstring.
435
+
436
+ This function errs on the side of being overly conservative.
437
+ """
438
+ Py_TPFLAGS_HEAPTYPE = 1 << 9
439
+
440
+ if isinstance (obj , (types .FunctionType , types .MethodType , property )):
441
+ return False
442
+
443
+ if isinstance (obj , type ) and obj .__flags__ & Py_TPFLAGS_HEAPTYPE :
444
+ return False
445
+
446
+ return True
447
+
448
+
449
+ def _add_docstring (obj , doc , warn_on_python ):
450
+ if warn_on_python and not _needs_add_docstring (obj ):
451
+ warnings .warn (
452
+ "add_newdoc was used on a pure-python object {}. "
453
+ "Prefer to attach it directly to the source."
454
+ .format (obj ),
455
+ UserWarning ,
456
+ stacklevel = 3 )
432
457
try :
433
458
add_docstring (obj , doc )
434
459
except Exception :
435
460
pass
436
461
437
462
438
- def add_newdoc (place , obj , doc ):
463
+ def add_newdoc (place , obj , doc , warn_on_python = True ):
439
464
"""
440
465
Add documentation to an existing object, typically one defined in C
441
466
@@ -457,6 +482,9 @@ def add_newdoc(place, obj, doc):
457
482
458
483
If a list, then each element of the list should be a tuple of length
459
484
two - ``[(method1, docstring1), (method2, docstring2), ...]``
485
+ warn_on_python : bool
486
+ If True, the default, emit `UserWarning` if this is used to attach
487
+ documentation to a pure-python object.
460
488
461
489
Notes
462
490
-----
@@ -480,10 +508,10 @@ def add_newdoc(place, obj, doc):
480
508
"""
481
509
new = getattr (__import__ (place , globals (), {}, [obj ]), obj )
482
510
if isinstance (doc , str ):
483
- _add_docstring (new , doc .strip ())
511
+ _add_docstring (new , doc .strip (), warn_on_python )
484
512
elif isinstance (doc , tuple ):
485
513
attr , docstring = doc
486
- _add_docstring (getattr (new , attr ), docstring .strip ())
514
+ _add_docstring (getattr (new , attr ), docstring .strip (), warn_on_python )
487
515
elif isinstance (doc , list ):
488
516
for attr , docstring in doc :
489
- _add_docstring (getattr (new , attr ), docstring .strip ())
517
+ _add_docstring (getattr (new , attr ), docstring .strip (), warn_on_python )
0 commit comments