Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/numpy/lib/utils.py: 9%
462 statements
« prev ^ index » next coverage.py v7.0.5, created at 2023-01-17 06:27 +0000
« prev ^ index » next coverage.py v7.0.5, created at 2023-01-17 06:27 +0000
1import os
2import sys
3import textwrap
4import types
5import re
6import warnings
7import functools
8import platform
10from .._utils import set_module
11from numpy.core.numerictypes import issubclass_, issubsctype, issubdtype
12from numpy.core import ndarray, ufunc, asarray
13import numpy as np
15__all__ = [
16 'issubclass_', 'issubsctype', 'issubdtype', 'deprecate',
17 'deprecate_with_doc', 'get_include', 'info', 'source', 'who',
18 'lookfor', 'byte_bounds', 'safe_eval', 'show_runtime'
19 ]
22def show_runtime():
23 """
24 Print information about various resources in the system
25 including available intrinsic support and BLAS/LAPACK library
26 in use
28 .. versionadded:: 1.24.0
30 See Also
31 --------
32 show_config : Show libraries in the system on which NumPy was built.
34 Notes
35 -----
36 1. Information is derived with the help of `threadpoolctl <https://pypi.org/project/threadpoolctl/>`_
37 library if available.
38 2. SIMD related information is derived from ``__cpu_features__``,
39 ``__cpu_baseline__`` and ``__cpu_dispatch__``
41 """
42 from numpy.core._multiarray_umath import (
43 __cpu_features__, __cpu_baseline__, __cpu_dispatch__
44 )
45 from pprint import pprint
46 config_found = [{
47 "numpy_version": np.__version__,
48 "python": sys.version,
49 "uname": platform.uname(),
50 }]
51 features_found, features_not_found = [], []
52 for feature in __cpu_dispatch__:
53 if __cpu_features__[feature]:
54 features_found.append(feature)
55 else:
56 features_not_found.append(feature)
57 config_found.append({
58 "simd_extensions": {
59 "baseline": __cpu_baseline__,
60 "found": features_found,
61 "not_found": features_not_found
62 }
63 })
64 try:
65 from threadpoolctl import threadpool_info
66 config_found.extend(threadpool_info())
67 except ImportError:
68 print("WARNING: `threadpoolctl` not found in system!"
69 " Install it by `pip install threadpoolctl`."
70 " Once installed, try `np.show_runtime` again"
71 " for more detailed build information")
72 pprint(config_found)
75def get_include():
76 """
77 Return the directory that contains the NumPy \\*.h header files.
79 Extension modules that need to compile against NumPy should use this
80 function to locate the appropriate include directory.
82 Notes
83 -----
84 When using ``distutils``, for example in ``setup.py``::
86 import numpy as np
87 ...
88 Extension('extension_name', ...
89 include_dirs=[np.get_include()])
90 ...
92 """
93 import numpy
94 if numpy.show_config is None:
95 # running from numpy source directory
96 d = os.path.join(os.path.dirname(numpy.__file__), 'core', 'include')
97 else:
98 # using installed numpy core headers
99 import numpy.core as core
100 d = os.path.join(os.path.dirname(core.__file__), 'include')
101 return d
104class _Deprecate:
105 """
106 Decorator class to deprecate old functions.
108 Refer to `deprecate` for details.
110 See Also
111 --------
112 deprecate
114 """
116 def __init__(self, old_name=None, new_name=None, message=None):
117 self.old_name = old_name
118 self.new_name = new_name
119 self.message = message
121 def __call__(self, func, *args, **kwargs):
122 """
123 Decorator call. Refer to ``decorate``.
125 """
126 old_name = self.old_name
127 new_name = self.new_name
128 message = self.message
130 if old_name is None:
131 old_name = func.__name__
132 if new_name is None:
133 depdoc = "`%s` is deprecated!" % old_name
134 else:
135 depdoc = "`%s` is deprecated, use `%s` instead!" % \
136 (old_name, new_name)
138 if message is not None:
139 depdoc += "\n" + message
141 @functools.wraps(func)
142 def newfunc(*args, **kwds):
143 warnings.warn(depdoc, DeprecationWarning, stacklevel=2)
144 return func(*args, **kwds)
146 newfunc.__name__ = old_name
147 doc = func.__doc__
148 if doc is None:
149 doc = depdoc
150 else:
151 lines = doc.expandtabs().split('\n')
152 indent = _get_indent(lines[1:])
153 if lines[0].lstrip():
154 # Indent the original first line to let inspect.cleandoc()
155 # dedent the docstring despite the deprecation notice.
156 doc = indent * ' ' + doc
157 else:
158 # Remove the same leading blank lines as cleandoc() would.
159 skip = len(lines[0]) + 1
160 for line in lines[1:]:
161 if len(line) > indent:
162 break
163 skip += len(line) + 1
164 doc = doc[skip:]
165 depdoc = textwrap.indent(depdoc, ' ' * indent)
166 doc = '\n\n'.join([depdoc, doc])
167 newfunc.__doc__ = doc
169 return newfunc
172def _get_indent(lines):
173 """
174 Determines the leading whitespace that could be removed from all the lines.
175 """
176 indent = sys.maxsize
177 for line in lines:
178 content = len(line.lstrip())
179 if content:
180 indent = min(indent, len(line) - content)
181 if indent == sys.maxsize:
182 indent = 0
183 return indent
186def deprecate(*args, **kwargs):
187 """
188 Issues a DeprecationWarning, adds warning to `old_name`'s
189 docstring, rebinds ``old_name.__name__`` and returns the new
190 function object.
192 This function may also be used as a decorator.
194 Parameters
195 ----------
196 func : function
197 The function to be deprecated.
198 old_name : str, optional
199 The name of the function to be deprecated. Default is None, in
200 which case the name of `func` is used.
201 new_name : str, optional
202 The new name for the function. Default is None, in which case the
203 deprecation message is that `old_name` is deprecated. If given, the
204 deprecation message is that `old_name` is deprecated and `new_name`
205 should be used instead.
206 message : str, optional
207 Additional explanation of the deprecation. Displayed in the
208 docstring after the warning.
210 Returns
211 -------
212 old_func : function
213 The deprecated function.
215 Examples
216 --------
217 Note that ``olduint`` returns a value after printing Deprecation
218 Warning:
220 >>> olduint = np.deprecate(np.uint)
221 DeprecationWarning: `uint64` is deprecated! # may vary
222 >>> olduint(6)
223 6
225 """
226 # Deprecate may be run as a function or as a decorator
227 # If run as a function, we initialise the decorator class
228 # and execute its __call__ method.
230 if args:
231 fn = args[0]
232 args = args[1:]
234 return _Deprecate(*args, **kwargs)(fn)
235 else:
236 return _Deprecate(*args, **kwargs)
239def deprecate_with_doc(msg):
240 """
241 Deprecates a function and includes the deprecation in its docstring.
243 This function is used as a decorator. It returns an object that can be
244 used to issue a DeprecationWarning, by passing the to-be decorated
245 function as argument, this adds warning to the to-be decorated function's
246 docstring and returns the new function object.
248 See Also
249 --------
250 deprecate : Decorate a function such that it issues a `DeprecationWarning`
252 Parameters
253 ----------
254 msg : str
255 Additional explanation of the deprecation. Displayed in the
256 docstring after the warning.
258 Returns
259 -------
260 obj : object
262 """
263 return _Deprecate(message=msg)
266#--------------------------------------------
267# Determine if two arrays can share memory
268#--------------------------------------------
270def byte_bounds(a):
271 """
272 Returns pointers to the end-points of an array.
274 Parameters
275 ----------
276 a : ndarray
277 Input array. It must conform to the Python-side of the array
278 interface.
280 Returns
281 -------
282 (low, high) : tuple of 2 integers
283 The first integer is the first byte of the array, the second
284 integer is just past the last byte of the array. If `a` is not
285 contiguous it will not use every byte between the (`low`, `high`)
286 values.
288 Examples
289 --------
290 >>> I = np.eye(2, dtype='f'); I.dtype
291 dtype('float32')
292 >>> low, high = np.byte_bounds(I)
293 >>> high - low == I.size*I.itemsize
294 True
295 >>> I = np.eye(2); I.dtype
296 dtype('float64')
297 >>> low, high = np.byte_bounds(I)
298 >>> high - low == I.size*I.itemsize
299 True
301 """
302 ai = a.__array_interface__
303 a_data = ai['data'][0]
304 astrides = ai['strides']
305 ashape = ai['shape']
306 bytes_a = asarray(a).dtype.itemsize
308 a_low = a_high = a_data
309 if astrides is None:
310 # contiguous case
311 a_high += a.size * bytes_a
312 else:
313 for shape, stride in zip(ashape, astrides):
314 if stride < 0:
315 a_low += (shape-1)*stride
316 else:
317 a_high += (shape-1)*stride
318 a_high += bytes_a
319 return a_low, a_high
322#-----------------------------------------------------------------------------
323# Function for output and information on the variables used.
324#-----------------------------------------------------------------------------
327def who(vardict=None):
328 """
329 Print the NumPy arrays in the given dictionary.
331 If there is no dictionary passed in or `vardict` is None then returns
332 NumPy arrays in the globals() dictionary (all NumPy arrays in the
333 namespace).
335 Parameters
336 ----------
337 vardict : dict, optional
338 A dictionary possibly containing ndarrays. Default is globals().
340 Returns
341 -------
342 out : None
343 Returns 'None'.
345 Notes
346 -----
347 Prints out the name, shape, bytes and type of all of the ndarrays
348 present in `vardict`.
350 Examples
351 --------
352 >>> a = np.arange(10)
353 >>> b = np.ones(20)
354 >>> np.who()
355 Name Shape Bytes Type
356 ===========================================================
357 a 10 80 int64
358 b 20 160 float64
359 Upper bound on total bytes = 240
361 >>> d = {'x': np.arange(2.0), 'y': np.arange(3.0), 'txt': 'Some str',
362 ... 'idx':5}
363 >>> np.who(d)
364 Name Shape Bytes Type
365 ===========================================================
366 x 2 16 float64
367 y 3 24 float64
368 Upper bound on total bytes = 40
370 """
371 if vardict is None:
372 frame = sys._getframe().f_back
373 vardict = frame.f_globals
374 sta = []
375 cache = {}
376 for name in vardict.keys():
377 if isinstance(vardict[name], ndarray):
378 var = vardict[name]
379 idv = id(var)
380 if idv in cache.keys():
381 namestr = name + " (%s)" % cache[idv]
382 original = 0
383 else:
384 cache[idv] = name
385 namestr = name
386 original = 1
387 shapestr = " x ".join(map(str, var.shape))
388 bytestr = str(var.nbytes)
389 sta.append([namestr, shapestr, bytestr, var.dtype.name,
390 original])
392 maxname = 0
393 maxshape = 0
394 maxbyte = 0
395 totalbytes = 0
396 for val in sta:
397 if maxname < len(val[0]):
398 maxname = len(val[0])
399 if maxshape < len(val[1]):
400 maxshape = len(val[1])
401 if maxbyte < len(val[2]):
402 maxbyte = len(val[2])
403 if val[4]:
404 totalbytes += int(val[2])
406 if len(sta) > 0:
407 sp1 = max(10, maxname)
408 sp2 = max(10, maxshape)
409 sp3 = max(10, maxbyte)
410 prval = "Name %s Shape %s Bytes %s Type" % (sp1*' ', sp2*' ', sp3*' ')
411 print(prval + "\n" + "="*(len(prval)+5) + "\n")
413 for val in sta:
414 print("%s %s %s %s %s %s %s" % (val[0], ' '*(sp1-len(val[0])+4),
415 val[1], ' '*(sp2-len(val[1])+5),
416 val[2], ' '*(sp3-len(val[2])+5),
417 val[3]))
418 print("\nUpper bound on total bytes = %d" % totalbytes)
419 return
421#-----------------------------------------------------------------------------
424# NOTE: pydoc defines a help function which works similarly to this
425# except it uses a pager to take over the screen.
427# combine name and arguments and split to multiple lines of width
428# characters. End lines on a comma and begin argument list indented with
429# the rest of the arguments.
430def _split_line(name, arguments, width):
431 firstwidth = len(name)
432 k = firstwidth
433 newstr = name
434 sepstr = ", "
435 arglist = arguments.split(sepstr)
436 for argument in arglist:
437 if k == firstwidth:
438 addstr = ""
439 else:
440 addstr = sepstr
441 k = k + len(argument) + len(addstr)
442 if k > width:
443 k = firstwidth + 1 + len(argument)
444 newstr = newstr + ",\n" + " "*(firstwidth+2) + argument
445 else:
446 newstr = newstr + addstr + argument
447 return newstr
449_namedict = None
450_dictlist = None
452# Traverse all module directories underneath globals
453# to see if something is defined
454def _makenamedict(module='numpy'):
455 module = __import__(module, globals(), locals(), [])
456 thedict = {module.__name__:module.__dict__}
457 dictlist = [module.__name__]
458 totraverse = [module.__dict__]
459 while True:
460 if len(totraverse) == 0:
461 break
462 thisdict = totraverse.pop(0)
463 for x in thisdict.keys():
464 if isinstance(thisdict[x], types.ModuleType):
465 modname = thisdict[x].__name__
466 if modname not in dictlist:
467 moddict = thisdict[x].__dict__
468 dictlist.append(modname)
469 totraverse.append(moddict)
470 thedict[modname] = moddict
471 return thedict, dictlist
474def _info(obj, output=None):
475 """Provide information about ndarray obj.
477 Parameters
478 ----------
479 obj : ndarray
480 Must be ndarray, not checked.
481 output
482 Where printed output goes.
484 Notes
485 -----
486 Copied over from the numarray module prior to its removal.
487 Adapted somewhat as only numpy is an option now.
489 Called by info.
491 """
492 extra = ""
493 tic = ""
494 bp = lambda x: x
495 cls = getattr(obj, '__class__', type(obj))
496 nm = getattr(cls, '__name__', cls)
497 strides = obj.strides
498 endian = obj.dtype.byteorder
500 if output is None:
501 output = sys.stdout
503 print("class: ", nm, file=output)
504 print("shape: ", obj.shape, file=output)
505 print("strides: ", strides, file=output)
506 print("itemsize: ", obj.itemsize, file=output)
507 print("aligned: ", bp(obj.flags.aligned), file=output)
508 print("contiguous: ", bp(obj.flags.contiguous), file=output)
509 print("fortran: ", obj.flags.fortran, file=output)
510 print(
511 "data pointer: %s%s" % (hex(obj.ctypes._as_parameter_.value), extra),
512 file=output
513 )
514 print("byteorder: ", end=' ', file=output)
515 if endian in ['|', '=']:
516 print("%s%s%s" % (tic, sys.byteorder, tic), file=output)
517 byteswap = False
518 elif endian == '>':
519 print("%sbig%s" % (tic, tic), file=output)
520 byteswap = sys.byteorder != "big"
521 else:
522 print("%slittle%s" % (tic, tic), file=output)
523 byteswap = sys.byteorder != "little"
524 print("byteswap: ", bp(byteswap), file=output)
525 print("type: %s" % obj.dtype, file=output)
528@set_module('numpy')
529def info(object=None, maxwidth=76, output=None, toplevel='numpy'):
530 """
531 Get help information for a function, class, or module.
533 Parameters
534 ----------
535 object : object or str, optional
536 Input object or name to get information about. If `object` is a
537 numpy object, its docstring is given. If it is a string, available
538 modules are searched for matching objects. If None, information
539 about `info` itself is returned.
540 maxwidth : int, optional
541 Printing width.
542 output : file like object, optional
543 File like object that the output is written to, default is
544 ``None``, in which case ``sys.stdout`` will be used.
545 The object has to be opened in 'w' or 'a' mode.
546 toplevel : str, optional
547 Start search at this level.
549 See Also
550 --------
551 source, lookfor
553 Notes
554 -----
555 When used interactively with an object, ``np.info(obj)`` is equivalent
556 to ``help(obj)`` on the Python prompt or ``obj?`` on the IPython
557 prompt.
559 Examples
560 --------
561 >>> np.info(np.polyval) # doctest: +SKIP
562 polyval(p, x)
563 Evaluate the polynomial p at x.
564 ...
566 When using a string for `object` it is possible to get multiple results.
568 >>> np.info('fft') # doctest: +SKIP
569 *** Found in numpy ***
570 Core FFT routines
571 ...
572 *** Found in numpy.fft ***
573 fft(a, n=None, axis=-1)
574 ...
575 *** Repeat reference found in numpy.fft.fftpack ***
576 *** Total of 3 references found. ***
578 """
579 global _namedict, _dictlist
580 # Local import to speed up numpy's import time.
581 import pydoc
582 import inspect
584 if (hasattr(object, '_ppimport_importer') or
585 hasattr(object, '_ppimport_module')):
586 object = object._ppimport_module
587 elif hasattr(object, '_ppimport_attr'):
588 object = object._ppimport_attr
590 if output is None:
591 output = sys.stdout
593 if object is None:
594 info(info)
595 elif isinstance(object, ndarray):
596 _info(object, output=output)
597 elif isinstance(object, str):
598 if _namedict is None:
599 _namedict, _dictlist = _makenamedict(toplevel)
600 numfound = 0
601 objlist = []
602 for namestr in _dictlist:
603 try:
604 obj = _namedict[namestr][object]
605 if id(obj) in objlist:
606 print("\n "
607 "*** Repeat reference found in %s *** " % namestr,
608 file=output
609 )
610 else:
611 objlist.append(id(obj))
612 print(" *** Found in %s ***" % namestr, file=output)
613 info(obj)
614 print("-"*maxwidth, file=output)
615 numfound += 1
616 except KeyError:
617 pass
618 if numfound == 0:
619 print("Help for %s not found." % object, file=output)
620 else:
621 print("\n "
622 "*** Total of %d references found. ***" % numfound,
623 file=output
624 )
626 elif inspect.isfunction(object) or inspect.ismethod(object):
627 name = object.__name__
628 try:
629 arguments = str(inspect.signature(object))
630 except Exception:
631 arguments = "()"
633 if len(name+arguments) > maxwidth:
634 argstr = _split_line(name, arguments, maxwidth)
635 else:
636 argstr = name + arguments
638 print(" " + argstr + "\n", file=output)
639 print(inspect.getdoc(object), file=output)
641 elif inspect.isclass(object):
642 name = object.__name__
643 try:
644 arguments = str(inspect.signature(object))
645 except Exception:
646 arguments = "()"
648 if len(name+arguments) > maxwidth:
649 argstr = _split_line(name, arguments, maxwidth)
650 else:
651 argstr = name + arguments
653 print(" " + argstr + "\n", file=output)
654 doc1 = inspect.getdoc(object)
655 if doc1 is None:
656 if hasattr(object, '__init__'):
657 print(inspect.getdoc(object.__init__), file=output)
658 else:
659 print(inspect.getdoc(object), file=output)
661 methods = pydoc.allmethods(object)
663 public_methods = [meth for meth in methods if meth[0] != '_']
664 if public_methods:
665 print("\n\nMethods:\n", file=output)
666 for meth in public_methods:
667 thisobj = getattr(object, meth, None)
668 if thisobj is not None:
669 methstr, other = pydoc.splitdoc(
670 inspect.getdoc(thisobj) or "None"
671 )
672 print(" %s -- %s" % (meth, methstr), file=output)
674 elif hasattr(object, '__doc__'):
675 print(inspect.getdoc(object), file=output)
678@set_module('numpy')
679def source(object, output=sys.stdout):
680 """
681 Print or write to a file the source code for a NumPy object.
683 The source code is only returned for objects written in Python. Many
684 functions and classes are defined in C and will therefore not return
685 useful information.
687 Parameters
688 ----------
689 object : numpy object
690 Input object. This can be any object (function, class, module,
691 ...).
692 output : file object, optional
693 If `output` not supplied then source code is printed to screen
694 (sys.stdout). File object must be created with either write 'w' or
695 append 'a' modes.
697 See Also
698 --------
699 lookfor, info
701 Examples
702 --------
703 >>> np.source(np.interp) #doctest: +SKIP
704 In file: /usr/lib/python2.6/dist-packages/numpy/lib/function_base.py
705 def interp(x, xp, fp, left=None, right=None):
706 \"\"\".... (full docstring printed)\"\"\"
707 if isinstance(x, (float, int, number)):
708 return compiled_interp([x], xp, fp, left, right).item()
709 else:
710 return compiled_interp(x, xp, fp, left, right)
712 The source code is only returned for objects written in Python.
714 >>> np.source(np.array) #doctest: +SKIP
715 Not available for this object.
717 """
718 # Local import to speed up numpy's import time.
719 import inspect
720 try:
721 print("In file: %s\n" % inspect.getsourcefile(object), file=output)
722 print(inspect.getsource(object), file=output)
723 except Exception:
724 print("Not available for this object.", file=output)
727# Cache for lookfor: {id(module): {name: (docstring, kind, index), ...}...}
728# where kind: "func", "class", "module", "object"
729# and index: index in breadth-first namespace traversal
730_lookfor_caches = {}
732# regexp whose match indicates that the string may contain a function
733# signature
734_function_signature_re = re.compile(r"[a-z0-9_]+\(.*[,=].*\)", re.I)
737@set_module('numpy')
738def lookfor(what, module=None, import_modules=True, regenerate=False,
739 output=None):
740 """
741 Do a keyword search on docstrings.
743 A list of objects that matched the search is displayed,
744 sorted by relevance. All given keywords need to be found in the
745 docstring for it to be returned as a result, but the order does
746 not matter.
748 Parameters
749 ----------
750 what : str
751 String containing words to look for.
752 module : str or list, optional
753 Name of module(s) whose docstrings to go through.
754 import_modules : bool, optional
755 Whether to import sub-modules in packages. Default is True.
756 regenerate : bool, optional
757 Whether to re-generate the docstring cache. Default is False.
758 output : file-like, optional
759 File-like object to write the output to. If omitted, use a pager.
761 See Also
762 --------
763 source, info
765 Notes
766 -----
767 Relevance is determined only roughly, by checking if the keywords occur
768 in the function name, at the start of a docstring, etc.
770 Examples
771 --------
772 >>> np.lookfor('binary representation') # doctest: +SKIP
773 Search results for 'binary representation'
774 ------------------------------------------
775 numpy.binary_repr
776 Return the binary representation of the input number as a string.
777 numpy.core.setup_common.long_double_representation
778 Given a binary dump as given by GNU od -b, look for long double
779 numpy.base_repr
780 Return a string representation of a number in the given base system.
781 ...
783 """
784 import pydoc
786 # Cache
787 cache = _lookfor_generate_cache(module, import_modules, regenerate)
789 # Search
790 # XXX: maybe using a real stemming search engine would be better?
791 found = []
792 whats = str(what).lower().split()
793 if not whats:
794 return
796 for name, (docstring, kind, index) in cache.items():
797 if kind in ('module', 'object'):
798 # don't show modules or objects
799 continue
800 doc = docstring.lower()
801 if all(w in doc for w in whats):
802 found.append(name)
804 # Relevance sort
805 # XXX: this is full Harrison-Stetson heuristics now,
806 # XXX: it probably could be improved
808 kind_relevance = {'func': 1000, 'class': 1000,
809 'module': -1000, 'object': -1000}
811 def relevance(name, docstr, kind, index):
812 r = 0
813 # do the keywords occur within the start of the docstring?
814 first_doc = "\n".join(docstr.lower().strip().split("\n")[:3])
815 r += sum([200 for w in whats if w in first_doc])
816 # do the keywords occur in the function name?
817 r += sum([30 for w in whats if w in name])
818 # is the full name long?
819 r += -len(name) * 5
820 # is the object of bad type?
821 r += kind_relevance.get(kind, -1000)
822 # is the object deep in namespace hierarchy?
823 r += -name.count('.') * 10
824 r += max(-index / 100, -100)
825 return r
827 def relevance_value(a):
828 return relevance(a, *cache[a])
829 found.sort(key=relevance_value)
831 # Pretty-print
832 s = "Search results for '%s'" % (' '.join(whats))
833 help_text = [s, "-"*len(s)]
834 for name in found[::-1]:
835 doc, kind, ix = cache[name]
837 doclines = [line.strip() for line in doc.strip().split("\n")
838 if line.strip()]
840 # find a suitable short description
841 try:
842 first_doc = doclines[0].strip()
843 if _function_signature_re.search(first_doc):
844 first_doc = doclines[1].strip()
845 except IndexError:
846 first_doc = ""
847 help_text.append("%s\n %s" % (name, first_doc))
849 if not found:
850 help_text.append("Nothing found.")
852 # Output
853 if output is not None:
854 output.write("\n".join(help_text))
855 elif len(help_text) > 10:
856 pager = pydoc.getpager()
857 pager("\n".join(help_text))
858 else:
859 print("\n".join(help_text))
861def _lookfor_generate_cache(module, import_modules, regenerate):
862 """
863 Generate docstring cache for given module.
865 Parameters
866 ----------
867 module : str, None, module
868 Module for which to generate docstring cache
869 import_modules : bool
870 Whether to import sub-modules in packages.
871 regenerate : bool
872 Re-generate the docstring cache
874 Returns
875 -------
876 cache : dict {obj_full_name: (docstring, kind, index), ...}
877 Docstring cache for the module, either cached one (regenerate=False)
878 or newly generated.
880 """
881 # Local import to speed up numpy's import time.
882 import inspect
884 from io import StringIO
886 if module is None:
887 module = "numpy"
889 if isinstance(module, str):
890 try:
891 __import__(module)
892 except ImportError:
893 return {}
894 module = sys.modules[module]
895 elif isinstance(module, list) or isinstance(module, tuple):
896 cache = {}
897 for mod in module:
898 cache.update(_lookfor_generate_cache(mod, import_modules,
899 regenerate))
900 return cache
902 if id(module) in _lookfor_caches and not regenerate:
903 return _lookfor_caches[id(module)]
905 # walk items and collect docstrings
906 cache = {}
907 _lookfor_caches[id(module)] = cache
908 seen = {}
909 index = 0
910 stack = [(module.__name__, module)]
911 while stack:
912 name, item = stack.pop(0)
913 if id(item) in seen:
914 continue
915 seen[id(item)] = True
917 index += 1
918 kind = "object"
920 if inspect.ismodule(item):
921 kind = "module"
922 try:
923 _all = item.__all__
924 except AttributeError:
925 _all = None
927 # import sub-packages
928 if import_modules and hasattr(item, '__path__'):
929 for pth in item.__path__:
930 for mod_path in os.listdir(pth):
931 this_py = os.path.join(pth, mod_path)
932 init_py = os.path.join(pth, mod_path, '__init__.py')
933 if (os.path.isfile(this_py) and
934 mod_path.endswith('.py')):
935 to_import = mod_path[:-3]
936 elif os.path.isfile(init_py):
937 to_import = mod_path
938 else:
939 continue
940 if to_import == '__init__':
941 continue
943 try:
944 old_stdout = sys.stdout
945 old_stderr = sys.stderr
946 try:
947 sys.stdout = StringIO()
948 sys.stderr = StringIO()
949 __import__("%s.%s" % (name, to_import))
950 finally:
951 sys.stdout = old_stdout
952 sys.stderr = old_stderr
953 except KeyboardInterrupt:
954 # Assume keyboard interrupt came from a user
955 raise
956 except BaseException:
957 # Ignore also SystemExit and pytests.importorskip
958 # `Skipped` (these are BaseExceptions; gh-22345)
959 continue
961 for n, v in _getmembers(item):
962 try:
963 item_name = getattr(v, '__name__', "%s.%s" % (name, n))
964 mod_name = getattr(v, '__module__', None)
965 except NameError:
966 # ref. SWIG's global cvars
967 # NameError: Unknown C global variable
968 item_name = "%s.%s" % (name, n)
969 mod_name = None
970 if '.' not in item_name and mod_name:
971 item_name = "%s.%s" % (mod_name, item_name)
973 if not item_name.startswith(name + '.'):
974 # don't crawl "foreign" objects
975 if isinstance(v, ufunc):
976 # ... unless they are ufuncs
977 pass
978 else:
979 continue
980 elif not (inspect.ismodule(v) or _all is None or n in _all):
981 continue
982 stack.append(("%s.%s" % (name, n), v))
983 elif inspect.isclass(item):
984 kind = "class"
985 for n, v in _getmembers(item):
986 stack.append(("%s.%s" % (name, n), v))
987 elif hasattr(item, "__call__"):
988 kind = "func"
990 try:
991 doc = inspect.getdoc(item)
992 except NameError:
993 # ref SWIG's NameError: Unknown C global variable
994 doc = None
995 if doc is not None:
996 cache[name] = (doc, kind, index)
998 return cache
1000def _getmembers(item):
1001 import inspect
1002 try:
1003 members = inspect.getmembers(item)
1004 except Exception:
1005 members = [(x, getattr(item, x)) for x in dir(item)
1006 if hasattr(item, x)]
1007 return members
1010def safe_eval(source):
1011 """
1012 Protected string evaluation.
1014 Evaluate a string containing a Python literal expression without
1015 allowing the execution of arbitrary non-literal code.
1017 .. warning::
1019 This function is identical to :py:meth:`ast.literal_eval` and
1020 has the same security implications. It may not always be safe
1021 to evaluate large input strings.
1023 Parameters
1024 ----------
1025 source : str
1026 The string to evaluate.
1028 Returns
1029 -------
1030 obj : object
1031 The result of evaluating `source`.
1033 Raises
1034 ------
1035 SyntaxError
1036 If the code has invalid Python syntax, or if it contains
1037 non-literal code.
1039 Examples
1040 --------
1041 >>> np.safe_eval('1')
1042 1
1043 >>> np.safe_eval('[1, 2, 3]')
1044 [1, 2, 3]
1045 >>> np.safe_eval('{"foo": ("bar", 10.0)}')
1046 {'foo': ('bar', 10.0)}
1048 >>> np.safe_eval('import os')
1049 Traceback (most recent call last):
1050 ...
1051 SyntaxError: invalid syntax
1053 >>> np.safe_eval('open("/home/user/.ssh/id_dsa").read()')
1054 Traceback (most recent call last):
1055 ...
1056 ValueError: malformed node or string: <_ast.Call object at 0x...>
1058 """
1059 # Local import to speed up numpy's import time.
1060 import ast
1061 return ast.literal_eval(source)
1064def _median_nancheck(data, result, axis):
1065 """
1066 Utility function to check median result from data for NaN values at the end
1067 and return NaN in that case. Input result can also be a MaskedArray.
1069 Parameters
1070 ----------
1071 data : array
1072 Sorted input data to median function
1073 result : Array or MaskedArray
1074 Result of median function.
1075 axis : int
1076 Axis along which the median was computed.
1078 Returns
1079 -------
1080 result : scalar or ndarray
1081 Median or NaN in axes which contained NaN in the input. If the input
1082 was an array, NaN will be inserted in-place. If a scalar, either the
1083 input itself or a scalar NaN.
1084 """
1085 if data.size == 0:
1086 return result
1087 n = np.isnan(data.take(-1, axis=axis))
1088 # masked NaN values are ok
1089 if np.ma.isMaskedArray(n):
1090 n = n.filled(False)
1091 if np.count_nonzero(n.ravel()) > 0:
1092 # Without given output, it is possible that the current result is a
1093 # numpy scalar, which is not writeable. If so, just return nan.
1094 if isinstance(result, np.generic):
1095 return data.dtype.type(np.nan)
1097 result[n] = np.nan
1098 return result
1100def _opt_info():
1101 """
1102 Returns a string contains the supported CPU features by the current build.
1104 The string format can be explained as follows:
1105 - dispatched features that are supported by the running machine
1106 end with `*`.
1107 - dispatched features that are "not" supported by the running machine
1108 end with `?`.
1109 - remained features are representing the baseline.
1110 """
1111 from numpy.core._multiarray_umath import (
1112 __cpu_features__, __cpu_baseline__, __cpu_dispatch__
1113 )
1115 if len(__cpu_baseline__) == 0 and len(__cpu_dispatch__) == 0:
1116 return ''
1118 enabled_features = ' '.join(__cpu_baseline__)
1119 for feature in __cpu_dispatch__:
1120 if __cpu_features__[feature]:
1121 enabled_features += f" {feature}*"
1122 else:
1123 enabled_features += f" {feature}?"
1125 return enabled_features
1126#-----------------------------------------------------------------------------