utils.py 35 KB

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