Chris@87
|
1 from __future__ import division, absolute_import, print_function
|
Chris@87
|
2
|
Chris@87
|
3 import os
|
Chris@87
|
4 import sys
|
Chris@87
|
5 import types
|
Chris@87
|
6 import re
|
Chris@87
|
7
|
Chris@87
|
8 from numpy.core.numerictypes import issubclass_, issubsctype, issubdtype
|
Chris@87
|
9 from numpy.core import ndarray, ufunc, asarray
|
Chris@87
|
10
|
Chris@87
|
11 __all__ = [
|
Chris@87
|
12 'issubclass_', 'issubsctype', 'issubdtype', 'deprecate',
|
Chris@87
|
13 'deprecate_with_doc', 'get_include', 'info', 'source', 'who',
|
Chris@87
|
14 'lookfor', 'byte_bounds', 'safe_eval'
|
Chris@87
|
15 ]
|
Chris@87
|
16
|
Chris@87
|
17 def get_include():
|
Chris@87
|
18 """
|
Chris@87
|
19 Return the directory that contains the NumPy \\*.h header files.
|
Chris@87
|
20
|
Chris@87
|
21 Extension modules that need to compile against NumPy should use this
|
Chris@87
|
22 function to locate the appropriate include directory.
|
Chris@87
|
23
|
Chris@87
|
24 Notes
|
Chris@87
|
25 -----
|
Chris@87
|
26 When using ``distutils``, for example in ``setup.py``.
|
Chris@87
|
27 ::
|
Chris@87
|
28
|
Chris@87
|
29 import numpy as np
|
Chris@87
|
30 ...
|
Chris@87
|
31 Extension('extension_name', ...
|
Chris@87
|
32 include_dirs=[np.get_include()])
|
Chris@87
|
33 ...
|
Chris@87
|
34
|
Chris@87
|
35 """
|
Chris@87
|
36 import numpy
|
Chris@87
|
37 if numpy.show_config is None:
|
Chris@87
|
38 # running from numpy source directory
|
Chris@87
|
39 d = os.path.join(os.path.dirname(numpy.__file__), 'core', 'include')
|
Chris@87
|
40 else:
|
Chris@87
|
41 # using installed numpy core headers
|
Chris@87
|
42 import numpy.core as core
|
Chris@87
|
43 d = os.path.join(os.path.dirname(core.__file__), 'include')
|
Chris@87
|
44 return d
|
Chris@87
|
45
|
Chris@87
|
46
|
Chris@87
|
47 def _set_function_name(func, name):
|
Chris@87
|
48 func.__name__ = name
|
Chris@87
|
49 return func
|
Chris@87
|
50
|
Chris@87
|
51
|
Chris@87
|
52 class _Deprecate(object):
|
Chris@87
|
53 """
|
Chris@87
|
54 Decorator class to deprecate old functions.
|
Chris@87
|
55
|
Chris@87
|
56 Refer to `deprecate` for details.
|
Chris@87
|
57
|
Chris@87
|
58 See Also
|
Chris@87
|
59 --------
|
Chris@87
|
60 deprecate
|
Chris@87
|
61
|
Chris@87
|
62 """
|
Chris@87
|
63
|
Chris@87
|
64 def __init__(self, old_name=None, new_name=None, message=None):
|
Chris@87
|
65 self.old_name = old_name
|
Chris@87
|
66 self.new_name = new_name
|
Chris@87
|
67 self.message = message
|
Chris@87
|
68
|
Chris@87
|
69 def __call__(self, func, *args, **kwargs):
|
Chris@87
|
70 """
|
Chris@87
|
71 Decorator call. Refer to ``decorate``.
|
Chris@87
|
72
|
Chris@87
|
73 """
|
Chris@87
|
74 old_name = self.old_name
|
Chris@87
|
75 new_name = self.new_name
|
Chris@87
|
76 message = self.message
|
Chris@87
|
77
|
Chris@87
|
78 import warnings
|
Chris@87
|
79 if old_name is None:
|
Chris@87
|
80 try:
|
Chris@87
|
81 old_name = func.__name__
|
Chris@87
|
82 except AttributeError:
|
Chris@87
|
83 old_name = func.__name__
|
Chris@87
|
84 if new_name is None:
|
Chris@87
|
85 depdoc = "`%s` is deprecated!" % old_name
|
Chris@87
|
86 else:
|
Chris@87
|
87 depdoc = "`%s` is deprecated, use `%s` instead!" % \
|
Chris@87
|
88 (old_name, new_name)
|
Chris@87
|
89
|
Chris@87
|
90 if message is not None:
|
Chris@87
|
91 depdoc += "\n" + message
|
Chris@87
|
92
|
Chris@87
|
93 def newfunc(*args,**kwds):
|
Chris@87
|
94 """`arrayrange` is deprecated, use `arange` instead!"""
|
Chris@87
|
95 warnings.warn(depdoc, DeprecationWarning)
|
Chris@87
|
96 return func(*args, **kwds)
|
Chris@87
|
97
|
Chris@87
|
98 newfunc = _set_function_name(newfunc, old_name)
|
Chris@87
|
99 doc = func.__doc__
|
Chris@87
|
100 if doc is None:
|
Chris@87
|
101 doc = depdoc
|
Chris@87
|
102 else:
|
Chris@87
|
103 doc = '\n\n'.join([depdoc, doc])
|
Chris@87
|
104 newfunc.__doc__ = doc
|
Chris@87
|
105 try:
|
Chris@87
|
106 d = func.__dict__
|
Chris@87
|
107 except AttributeError:
|
Chris@87
|
108 pass
|
Chris@87
|
109 else:
|
Chris@87
|
110 newfunc.__dict__.update(d)
|
Chris@87
|
111 return newfunc
|
Chris@87
|
112
|
Chris@87
|
113 def deprecate(*args, **kwargs):
|
Chris@87
|
114 """
|
Chris@87
|
115 Issues a DeprecationWarning, adds warning to `old_name`'s
|
Chris@87
|
116 docstring, rebinds ``old_name.__name__`` and returns the new
|
Chris@87
|
117 function object.
|
Chris@87
|
118
|
Chris@87
|
119 This function may also be used as a decorator.
|
Chris@87
|
120
|
Chris@87
|
121 Parameters
|
Chris@87
|
122 ----------
|
Chris@87
|
123 func : function
|
Chris@87
|
124 The function to be deprecated.
|
Chris@87
|
125 old_name : str, optional
|
Chris@87
|
126 The name of the function to be deprecated. Default is None, in
|
Chris@87
|
127 which case the name of `func` is used.
|
Chris@87
|
128 new_name : str, optional
|
Chris@87
|
129 The new name for the function. Default is None, in which case the
|
Chris@87
|
130 deprecation message is that `old_name` is deprecated. If given, the
|
Chris@87
|
131 deprecation message is that `old_name` is deprecated and `new_name`
|
Chris@87
|
132 should be used instead.
|
Chris@87
|
133 message : str, optional
|
Chris@87
|
134 Additional explanation of the deprecation. Displayed in the
|
Chris@87
|
135 docstring after the warning.
|
Chris@87
|
136
|
Chris@87
|
137 Returns
|
Chris@87
|
138 -------
|
Chris@87
|
139 old_func : function
|
Chris@87
|
140 The deprecated function.
|
Chris@87
|
141
|
Chris@87
|
142 Examples
|
Chris@87
|
143 --------
|
Chris@87
|
144 Note that ``olduint`` returns a value after printing Deprecation
|
Chris@87
|
145 Warning:
|
Chris@87
|
146
|
Chris@87
|
147 >>> olduint = np.deprecate(np.uint)
|
Chris@87
|
148 >>> olduint(6)
|
Chris@87
|
149 /usr/lib/python2.5/site-packages/numpy/lib/utils.py:114:
|
Chris@87
|
150 DeprecationWarning: uint32 is deprecated
|
Chris@87
|
151 warnings.warn(str1, DeprecationWarning)
|
Chris@87
|
152 6
|
Chris@87
|
153
|
Chris@87
|
154 """
|
Chris@87
|
155 # Deprecate may be run as a function or as a decorator
|
Chris@87
|
156 # If run as a function, we initialise the decorator class
|
Chris@87
|
157 # and execute its __call__ method.
|
Chris@87
|
158
|
Chris@87
|
159 if args:
|
Chris@87
|
160 fn = args[0]
|
Chris@87
|
161 args = args[1:]
|
Chris@87
|
162
|
Chris@87
|
163 # backward compatibility -- can be removed
|
Chris@87
|
164 # after next release
|
Chris@87
|
165 if 'newname' in kwargs:
|
Chris@87
|
166 kwargs['new_name'] = kwargs.pop('newname')
|
Chris@87
|
167 if 'oldname' in kwargs:
|
Chris@87
|
168 kwargs['old_name'] = kwargs.pop('oldname')
|
Chris@87
|
169
|
Chris@87
|
170 return _Deprecate(*args, **kwargs)(fn)
|
Chris@87
|
171 else:
|
Chris@87
|
172 return _Deprecate(*args, **kwargs)
|
Chris@87
|
173
|
Chris@87
|
174 deprecate_with_doc = lambda msg: _Deprecate(message=msg)
|
Chris@87
|
175
|
Chris@87
|
176
|
Chris@87
|
177 #--------------------------------------------
|
Chris@87
|
178 # Determine if two arrays can share memory
|
Chris@87
|
179 #--------------------------------------------
|
Chris@87
|
180
|
Chris@87
|
181 def byte_bounds(a):
|
Chris@87
|
182 """
|
Chris@87
|
183 Returns pointers to the end-points of an array.
|
Chris@87
|
184
|
Chris@87
|
185 Parameters
|
Chris@87
|
186 ----------
|
Chris@87
|
187 a : ndarray
|
Chris@87
|
188 Input array. It must conform to the Python-side of the array
|
Chris@87
|
189 interface.
|
Chris@87
|
190
|
Chris@87
|
191 Returns
|
Chris@87
|
192 -------
|
Chris@87
|
193 (low, high) : tuple of 2 integers
|
Chris@87
|
194 The first integer is the first byte of the array, the second
|
Chris@87
|
195 integer is just past the last byte of the array. If `a` is not
|
Chris@87
|
196 contiguous it will not use every byte between the (`low`, `high`)
|
Chris@87
|
197 values.
|
Chris@87
|
198
|
Chris@87
|
199 Examples
|
Chris@87
|
200 --------
|
Chris@87
|
201 >>> I = np.eye(2, dtype='f'); I.dtype
|
Chris@87
|
202 dtype('float32')
|
Chris@87
|
203 >>> low, high = np.byte_bounds(I)
|
Chris@87
|
204 >>> high - low == I.size*I.itemsize
|
Chris@87
|
205 True
|
Chris@87
|
206 >>> I = np.eye(2, dtype='G'); I.dtype
|
Chris@87
|
207 dtype('complex192')
|
Chris@87
|
208 >>> low, high = np.byte_bounds(I)
|
Chris@87
|
209 >>> high - low == I.size*I.itemsize
|
Chris@87
|
210 True
|
Chris@87
|
211
|
Chris@87
|
212 """
|
Chris@87
|
213 ai = a.__array_interface__
|
Chris@87
|
214 a_data = ai['data'][0]
|
Chris@87
|
215 astrides = ai['strides']
|
Chris@87
|
216 ashape = ai['shape']
|
Chris@87
|
217 bytes_a = asarray(a).dtype.itemsize
|
Chris@87
|
218
|
Chris@87
|
219 a_low = a_high = a_data
|
Chris@87
|
220 if astrides is None:
|
Chris@87
|
221 # contiguous case
|
Chris@87
|
222 a_high += a.size * bytes_a
|
Chris@87
|
223 else:
|
Chris@87
|
224 for shape, stride in zip(ashape, astrides):
|
Chris@87
|
225 if stride < 0:
|
Chris@87
|
226 a_low += (shape-1)*stride
|
Chris@87
|
227 else:
|
Chris@87
|
228 a_high += (shape-1)*stride
|
Chris@87
|
229 a_high += bytes_a
|
Chris@87
|
230 return a_low, a_high
|
Chris@87
|
231
|
Chris@87
|
232
|
Chris@87
|
233 #-----------------------------------------------------------------------------
|
Chris@87
|
234 # Function for output and information on the variables used.
|
Chris@87
|
235 #-----------------------------------------------------------------------------
|
Chris@87
|
236
|
Chris@87
|
237
|
Chris@87
|
238 def who(vardict=None):
|
Chris@87
|
239 """
|
Chris@87
|
240 Print the Numpy arrays in the given dictionary.
|
Chris@87
|
241
|
Chris@87
|
242 If there is no dictionary passed in or `vardict` is None then returns
|
Chris@87
|
243 Numpy arrays in the globals() dictionary (all Numpy arrays in the
|
Chris@87
|
244 namespace).
|
Chris@87
|
245
|
Chris@87
|
246 Parameters
|
Chris@87
|
247 ----------
|
Chris@87
|
248 vardict : dict, optional
|
Chris@87
|
249 A dictionary possibly containing ndarrays. Default is globals().
|
Chris@87
|
250
|
Chris@87
|
251 Returns
|
Chris@87
|
252 -------
|
Chris@87
|
253 out : None
|
Chris@87
|
254 Returns 'None'.
|
Chris@87
|
255
|
Chris@87
|
256 Notes
|
Chris@87
|
257 -----
|
Chris@87
|
258 Prints out the name, shape, bytes and type of all of the ndarrays
|
Chris@87
|
259 present in `vardict`.
|
Chris@87
|
260
|
Chris@87
|
261 Examples
|
Chris@87
|
262 --------
|
Chris@87
|
263 >>> a = np.arange(10)
|
Chris@87
|
264 >>> b = np.ones(20)
|
Chris@87
|
265 >>> np.who()
|
Chris@87
|
266 Name Shape Bytes Type
|
Chris@87
|
267 ===========================================================
|
Chris@87
|
268 a 10 40 int32
|
Chris@87
|
269 b 20 160 float64
|
Chris@87
|
270 Upper bound on total bytes = 200
|
Chris@87
|
271
|
Chris@87
|
272 >>> d = {'x': np.arange(2.0), 'y': np.arange(3.0), 'txt': 'Some str',
|
Chris@87
|
273 ... 'idx':5}
|
Chris@87
|
274 >>> np.who(d)
|
Chris@87
|
275 Name Shape Bytes Type
|
Chris@87
|
276 ===========================================================
|
Chris@87
|
277 y 3 24 float64
|
Chris@87
|
278 x 2 16 float64
|
Chris@87
|
279 Upper bound on total bytes = 40
|
Chris@87
|
280
|
Chris@87
|
281 """
|
Chris@87
|
282 if vardict is None:
|
Chris@87
|
283 frame = sys._getframe().f_back
|
Chris@87
|
284 vardict = frame.f_globals
|
Chris@87
|
285 sta = []
|
Chris@87
|
286 cache = {}
|
Chris@87
|
287 for name in vardict.keys():
|
Chris@87
|
288 if isinstance(vardict[name], ndarray):
|
Chris@87
|
289 var = vardict[name]
|
Chris@87
|
290 idv = id(var)
|
Chris@87
|
291 if idv in cache.keys():
|
Chris@87
|
292 namestr = name + " (%s)" % cache[idv]
|
Chris@87
|
293 original = 0
|
Chris@87
|
294 else:
|
Chris@87
|
295 cache[idv] = name
|
Chris@87
|
296 namestr = name
|
Chris@87
|
297 original = 1
|
Chris@87
|
298 shapestr = " x ".join(map(str, var.shape))
|
Chris@87
|
299 bytestr = str(var.nbytes)
|
Chris@87
|
300 sta.append([namestr, shapestr, bytestr, var.dtype.name,
|
Chris@87
|
301 original])
|
Chris@87
|
302
|
Chris@87
|
303 maxname = 0
|
Chris@87
|
304 maxshape = 0
|
Chris@87
|
305 maxbyte = 0
|
Chris@87
|
306 totalbytes = 0
|
Chris@87
|
307 for k in range(len(sta)):
|
Chris@87
|
308 val = sta[k]
|
Chris@87
|
309 if maxname < len(val[0]):
|
Chris@87
|
310 maxname = len(val[0])
|
Chris@87
|
311 if maxshape < len(val[1]):
|
Chris@87
|
312 maxshape = len(val[1])
|
Chris@87
|
313 if maxbyte < len(val[2]):
|
Chris@87
|
314 maxbyte = len(val[2])
|
Chris@87
|
315 if val[4]:
|
Chris@87
|
316 totalbytes += int(val[2])
|
Chris@87
|
317
|
Chris@87
|
318 if len(sta) > 0:
|
Chris@87
|
319 sp1 = max(10, maxname)
|
Chris@87
|
320 sp2 = max(10, maxshape)
|
Chris@87
|
321 sp3 = max(10, maxbyte)
|
Chris@87
|
322 prval = "Name %s Shape %s Bytes %s Type" % (sp1*' ', sp2*' ', sp3*' ')
|
Chris@87
|
323 print(prval + "\n" + "="*(len(prval)+5) + "\n")
|
Chris@87
|
324
|
Chris@87
|
325 for k in range(len(sta)):
|
Chris@87
|
326 val = sta[k]
|
Chris@87
|
327 print("%s %s %s %s %s %s %s" % (val[0], ' '*(sp1-len(val[0])+4),
|
Chris@87
|
328 val[1], ' '*(sp2-len(val[1])+5),
|
Chris@87
|
329 val[2], ' '*(sp3-len(val[2])+5),
|
Chris@87
|
330 val[3]))
|
Chris@87
|
331 print("\nUpper bound on total bytes = %d" % totalbytes)
|
Chris@87
|
332 return
|
Chris@87
|
333
|
Chris@87
|
334 #-----------------------------------------------------------------------------
|
Chris@87
|
335
|
Chris@87
|
336
|
Chris@87
|
337 # NOTE: pydoc defines a help function which works simliarly to this
|
Chris@87
|
338 # except it uses a pager to take over the screen.
|
Chris@87
|
339
|
Chris@87
|
340 # combine name and arguments and split to multiple lines of width
|
Chris@87
|
341 # characters. End lines on a comma and begin argument list indented with
|
Chris@87
|
342 # the rest of the arguments.
|
Chris@87
|
343 def _split_line(name, arguments, width):
|
Chris@87
|
344 firstwidth = len(name)
|
Chris@87
|
345 k = firstwidth
|
Chris@87
|
346 newstr = name
|
Chris@87
|
347 sepstr = ", "
|
Chris@87
|
348 arglist = arguments.split(sepstr)
|
Chris@87
|
349 for argument in arglist:
|
Chris@87
|
350 if k == firstwidth:
|
Chris@87
|
351 addstr = ""
|
Chris@87
|
352 else:
|
Chris@87
|
353 addstr = sepstr
|
Chris@87
|
354 k = k + len(argument) + len(addstr)
|
Chris@87
|
355 if k > width:
|
Chris@87
|
356 k = firstwidth + 1 + len(argument)
|
Chris@87
|
357 newstr = newstr + ",\n" + " "*(firstwidth+2) + argument
|
Chris@87
|
358 else:
|
Chris@87
|
359 newstr = newstr + addstr + argument
|
Chris@87
|
360 return newstr
|
Chris@87
|
361
|
Chris@87
|
362 _namedict = None
|
Chris@87
|
363 _dictlist = None
|
Chris@87
|
364
|
Chris@87
|
365 # Traverse all module directories underneath globals
|
Chris@87
|
366 # to see if something is defined
|
Chris@87
|
367 def _makenamedict(module='numpy'):
|
Chris@87
|
368 module = __import__(module, globals(), locals(), [])
|
Chris@87
|
369 thedict = {module.__name__:module.__dict__}
|
Chris@87
|
370 dictlist = [module.__name__]
|
Chris@87
|
371 totraverse = [module.__dict__]
|
Chris@87
|
372 while True:
|
Chris@87
|
373 if len(totraverse) == 0:
|
Chris@87
|
374 break
|
Chris@87
|
375 thisdict = totraverse.pop(0)
|
Chris@87
|
376 for x in thisdict.keys():
|
Chris@87
|
377 if isinstance(thisdict[x], types.ModuleType):
|
Chris@87
|
378 modname = thisdict[x].__name__
|
Chris@87
|
379 if modname not in dictlist:
|
Chris@87
|
380 moddict = thisdict[x].__dict__
|
Chris@87
|
381 dictlist.append(modname)
|
Chris@87
|
382 totraverse.append(moddict)
|
Chris@87
|
383 thedict[modname] = moddict
|
Chris@87
|
384 return thedict, dictlist
|
Chris@87
|
385
|
Chris@87
|
386
|
Chris@87
|
387 def _info(obj, output=sys.stdout):
|
Chris@87
|
388 """Provide information about ndarray obj.
|
Chris@87
|
389
|
Chris@87
|
390 Parameters
|
Chris@87
|
391 ----------
|
Chris@87
|
392 obj: ndarray
|
Chris@87
|
393 Must be ndarray, not checked.
|
Chris@87
|
394 output:
|
Chris@87
|
395 Where printed output goes.
|
Chris@87
|
396
|
Chris@87
|
397 Notes
|
Chris@87
|
398 -----
|
Chris@87
|
399 Copied over from the numarray module prior to its removal.
|
Chris@87
|
400 Adapted somewhat as only numpy is an option now.
|
Chris@87
|
401
|
Chris@87
|
402 Called by info.
|
Chris@87
|
403
|
Chris@87
|
404 """
|
Chris@87
|
405 extra = ""
|
Chris@87
|
406 tic = ""
|
Chris@87
|
407 bp = lambda x: x
|
Chris@87
|
408 cls = getattr(obj, '__class__', type(obj))
|
Chris@87
|
409 nm = getattr(cls, '__name__', cls)
|
Chris@87
|
410 strides = obj.strides
|
Chris@87
|
411 endian = obj.dtype.byteorder
|
Chris@87
|
412
|
Chris@87
|
413 print("class: ", nm, file=output)
|
Chris@87
|
414 print("shape: ", obj.shape, file=output)
|
Chris@87
|
415 print("strides: ", strides, file=output)
|
Chris@87
|
416 print("itemsize: ", obj.itemsize, file=output)
|
Chris@87
|
417 print("aligned: ", bp(obj.flags.aligned), file=output)
|
Chris@87
|
418 print("contiguous: ", bp(obj.flags.contiguous), file=output)
|
Chris@87
|
419 print("fortran: ", obj.flags.fortran, file=output)
|
Chris@87
|
420 print(
|
Chris@87
|
421 "data pointer: %s%s" % (hex(obj.ctypes._as_parameter_.value), extra),
|
Chris@87
|
422 file=output
|
Chris@87
|
423 )
|
Chris@87
|
424 print("byteorder: ", end=' ', file=output)
|
Chris@87
|
425 if endian in ['|', '=']:
|
Chris@87
|
426 print("%s%s%s" % (tic, sys.byteorder, tic), file=output)
|
Chris@87
|
427 byteswap = False
|
Chris@87
|
428 elif endian == '>':
|
Chris@87
|
429 print("%sbig%s" % (tic, tic), file=output)
|
Chris@87
|
430 byteswap = sys.byteorder != "big"
|
Chris@87
|
431 else:
|
Chris@87
|
432 print("%slittle%s" % (tic, tic), file=output)
|
Chris@87
|
433 byteswap = sys.byteorder != "little"
|
Chris@87
|
434 print("byteswap: ", bp(byteswap), file=output)
|
Chris@87
|
435 print("type: %s" % obj.dtype, file=output)
|
Chris@87
|
436
|
Chris@87
|
437
|
Chris@87
|
438 def info(object=None, maxwidth=76, output=sys.stdout, toplevel='numpy'):
|
Chris@87
|
439 """
|
Chris@87
|
440 Get help information for a function, class, or module.
|
Chris@87
|
441
|
Chris@87
|
442 Parameters
|
Chris@87
|
443 ----------
|
Chris@87
|
444 object : object or str, optional
|
Chris@87
|
445 Input object or name to get information about. If `object` is a
|
Chris@87
|
446 numpy object, its docstring is given. If it is a string, available
|
Chris@87
|
447 modules are searched for matching objects. If None, information
|
Chris@87
|
448 about `info` itself is returned.
|
Chris@87
|
449 maxwidth : int, optional
|
Chris@87
|
450 Printing width.
|
Chris@87
|
451 output : file like object, optional
|
Chris@87
|
452 File like object that the output is written to, default is
|
Chris@87
|
453 ``stdout``. The object has to be opened in 'w' or 'a' mode.
|
Chris@87
|
454 toplevel : str, optional
|
Chris@87
|
455 Start search at this level.
|
Chris@87
|
456
|
Chris@87
|
457 See Also
|
Chris@87
|
458 --------
|
Chris@87
|
459 source, lookfor
|
Chris@87
|
460
|
Chris@87
|
461 Notes
|
Chris@87
|
462 -----
|
Chris@87
|
463 When used interactively with an object, ``np.info(obj)`` is equivalent
|
Chris@87
|
464 to ``help(obj)`` on the Python prompt or ``obj?`` on the IPython
|
Chris@87
|
465 prompt.
|
Chris@87
|
466
|
Chris@87
|
467 Examples
|
Chris@87
|
468 --------
|
Chris@87
|
469 >>> np.info(np.polyval) # doctest: +SKIP
|
Chris@87
|
470 polyval(p, x)
|
Chris@87
|
471 Evaluate the polynomial p at x.
|
Chris@87
|
472 ...
|
Chris@87
|
473
|
Chris@87
|
474 When using a string for `object` it is possible to get multiple results.
|
Chris@87
|
475
|
Chris@87
|
476 >>> np.info('fft') # doctest: +SKIP
|
Chris@87
|
477 *** Found in numpy ***
|
Chris@87
|
478 Core FFT routines
|
Chris@87
|
479 ...
|
Chris@87
|
480 *** Found in numpy.fft ***
|
Chris@87
|
481 fft(a, n=None, axis=-1)
|
Chris@87
|
482 ...
|
Chris@87
|
483 *** Repeat reference found in numpy.fft.fftpack ***
|
Chris@87
|
484 *** Total of 3 references found. ***
|
Chris@87
|
485
|
Chris@87
|
486 """
|
Chris@87
|
487 global _namedict, _dictlist
|
Chris@87
|
488 # Local import to speed up numpy's import time.
|
Chris@87
|
489 import pydoc
|
Chris@87
|
490 import inspect
|
Chris@87
|
491
|
Chris@87
|
492 if (hasattr(object, '_ppimport_importer') or
|
Chris@87
|
493 hasattr(object, '_ppimport_module')):
|
Chris@87
|
494 object = object._ppimport_module
|
Chris@87
|
495 elif hasattr(object, '_ppimport_attr'):
|
Chris@87
|
496 object = object._ppimport_attr
|
Chris@87
|
497
|
Chris@87
|
498 if object is None:
|
Chris@87
|
499 info(info)
|
Chris@87
|
500 elif isinstance(object, ndarray):
|
Chris@87
|
501 _info(object, output=output)
|
Chris@87
|
502 elif isinstance(object, str):
|
Chris@87
|
503 if _namedict is None:
|
Chris@87
|
504 _namedict, _dictlist = _makenamedict(toplevel)
|
Chris@87
|
505 numfound = 0
|
Chris@87
|
506 objlist = []
|
Chris@87
|
507 for namestr in _dictlist:
|
Chris@87
|
508 try:
|
Chris@87
|
509 obj = _namedict[namestr][object]
|
Chris@87
|
510 if id(obj) in objlist:
|
Chris@87
|
511 print("\n "
|
Chris@87
|
512 "*** Repeat reference found in %s *** " % namestr,
|
Chris@87
|
513 file=output
|
Chris@87
|
514 )
|
Chris@87
|
515 else:
|
Chris@87
|
516 objlist.append(id(obj))
|
Chris@87
|
517 print(" *** Found in %s ***" % namestr, file=output)
|
Chris@87
|
518 info(obj)
|
Chris@87
|
519 print("-"*maxwidth, file=output)
|
Chris@87
|
520 numfound += 1
|
Chris@87
|
521 except KeyError:
|
Chris@87
|
522 pass
|
Chris@87
|
523 if numfound == 0:
|
Chris@87
|
524 print("Help for %s not found." % object, file=output)
|
Chris@87
|
525 else:
|
Chris@87
|
526 print("\n "
|
Chris@87
|
527 "*** Total of %d references found. ***" % numfound,
|
Chris@87
|
528 file=output
|
Chris@87
|
529 )
|
Chris@87
|
530
|
Chris@87
|
531 elif inspect.isfunction(object):
|
Chris@87
|
532 name = object.__name__
|
Chris@87
|
533 arguments = inspect.formatargspec(*inspect.getargspec(object))
|
Chris@87
|
534
|
Chris@87
|
535 if len(name+arguments) > maxwidth:
|
Chris@87
|
536 argstr = _split_line(name, arguments, maxwidth)
|
Chris@87
|
537 else:
|
Chris@87
|
538 argstr = name + arguments
|
Chris@87
|
539
|
Chris@87
|
540 print(" " + argstr + "\n", file=output)
|
Chris@87
|
541 print(inspect.getdoc(object), file=output)
|
Chris@87
|
542
|
Chris@87
|
543 elif inspect.isclass(object):
|
Chris@87
|
544 name = object.__name__
|
Chris@87
|
545 arguments = "()"
|
Chris@87
|
546 try:
|
Chris@87
|
547 if hasattr(object, '__init__'):
|
Chris@87
|
548 arguments = inspect.formatargspec(
|
Chris@87
|
549 *inspect.getargspec(object.__init__.__func__)
|
Chris@87
|
550 )
|
Chris@87
|
551 arglist = arguments.split(', ')
|
Chris@87
|
552 if len(arglist) > 1:
|
Chris@87
|
553 arglist[1] = "("+arglist[1]
|
Chris@87
|
554 arguments = ", ".join(arglist[1:])
|
Chris@87
|
555 except:
|
Chris@87
|
556 pass
|
Chris@87
|
557
|
Chris@87
|
558 if len(name+arguments) > maxwidth:
|
Chris@87
|
559 argstr = _split_line(name, arguments, maxwidth)
|
Chris@87
|
560 else:
|
Chris@87
|
561 argstr = name + arguments
|
Chris@87
|
562
|
Chris@87
|
563 print(" " + argstr + "\n", file=output)
|
Chris@87
|
564 doc1 = inspect.getdoc(object)
|
Chris@87
|
565 if doc1 is None:
|
Chris@87
|
566 if hasattr(object, '__init__'):
|
Chris@87
|
567 print(inspect.getdoc(object.__init__), file=output)
|
Chris@87
|
568 else:
|
Chris@87
|
569 print(inspect.getdoc(object), file=output)
|
Chris@87
|
570
|
Chris@87
|
571 methods = pydoc.allmethods(object)
|
Chris@87
|
572 if methods != []:
|
Chris@87
|
573 print("\n\nMethods:\n", file=output)
|
Chris@87
|
574 for meth in methods:
|
Chris@87
|
575 if meth[0] == '_':
|
Chris@87
|
576 continue
|
Chris@87
|
577 thisobj = getattr(object, meth, None)
|
Chris@87
|
578 if thisobj is not None:
|
Chris@87
|
579 methstr, other = pydoc.splitdoc(
|
Chris@87
|
580 inspect.getdoc(thisobj) or "None"
|
Chris@87
|
581 )
|
Chris@87
|
582 print(" %s -- %s" % (meth, methstr), file=output)
|
Chris@87
|
583
|
Chris@87
|
584 elif (sys.version_info[0] < 3
|
Chris@87
|
585 and isinstance(object, types.InstanceType)):
|
Chris@87
|
586 # check for __call__ method
|
Chris@87
|
587 # types.InstanceType is the type of the instances of oldstyle classes
|
Chris@87
|
588 print("Instance of class: ", object.__class__.__name__, file=output)
|
Chris@87
|
589 print(file=output)
|
Chris@87
|
590 if hasattr(object, '__call__'):
|
Chris@87
|
591 arguments = inspect.formatargspec(
|
Chris@87
|
592 *inspect.getargspec(object.__call__.__func__)
|
Chris@87
|
593 )
|
Chris@87
|
594 arglist = arguments.split(', ')
|
Chris@87
|
595 if len(arglist) > 1:
|
Chris@87
|
596 arglist[1] = "("+arglist[1]
|
Chris@87
|
597 arguments = ", ".join(arglist[1:])
|
Chris@87
|
598 else:
|
Chris@87
|
599 arguments = "()"
|
Chris@87
|
600
|
Chris@87
|
601 if hasattr(object, 'name'):
|
Chris@87
|
602 name = "%s" % object.name
|
Chris@87
|
603 else:
|
Chris@87
|
604 name = "<name>"
|
Chris@87
|
605 if len(name+arguments) > maxwidth:
|
Chris@87
|
606 argstr = _split_line(name, arguments, maxwidth)
|
Chris@87
|
607 else:
|
Chris@87
|
608 argstr = name + arguments
|
Chris@87
|
609
|
Chris@87
|
610 print(" " + argstr + "\n", file=output)
|
Chris@87
|
611 doc = inspect.getdoc(object.__call__)
|
Chris@87
|
612 if doc is not None:
|
Chris@87
|
613 print(inspect.getdoc(object.__call__), file=output)
|
Chris@87
|
614 print(inspect.getdoc(object), file=output)
|
Chris@87
|
615
|
Chris@87
|
616 else:
|
Chris@87
|
617 print(inspect.getdoc(object), file=output)
|
Chris@87
|
618
|
Chris@87
|
619 elif inspect.ismethod(object):
|
Chris@87
|
620 name = object.__name__
|
Chris@87
|
621 arguments = inspect.formatargspec(
|
Chris@87
|
622 *inspect.getargspec(object.__func__)
|
Chris@87
|
623 )
|
Chris@87
|
624 arglist = arguments.split(', ')
|
Chris@87
|
625 if len(arglist) > 1:
|
Chris@87
|
626 arglist[1] = "("+arglist[1]
|
Chris@87
|
627 arguments = ", ".join(arglist[1:])
|
Chris@87
|
628 else:
|
Chris@87
|
629 arguments = "()"
|
Chris@87
|
630
|
Chris@87
|
631 if len(name+arguments) > maxwidth:
|
Chris@87
|
632 argstr = _split_line(name, arguments, maxwidth)
|
Chris@87
|
633 else:
|
Chris@87
|
634 argstr = name + arguments
|
Chris@87
|
635
|
Chris@87
|
636 print(" " + argstr + "\n", file=output)
|
Chris@87
|
637 print(inspect.getdoc(object), file=output)
|
Chris@87
|
638
|
Chris@87
|
639 elif hasattr(object, '__doc__'):
|
Chris@87
|
640 print(inspect.getdoc(object), file=output)
|
Chris@87
|
641
|
Chris@87
|
642
|
Chris@87
|
643 def source(object, output=sys.stdout):
|
Chris@87
|
644 """
|
Chris@87
|
645 Print or write to a file the source code for a Numpy object.
|
Chris@87
|
646
|
Chris@87
|
647 The source code is only returned for objects written in Python. Many
|
Chris@87
|
648 functions and classes are defined in C and will therefore not return
|
Chris@87
|
649 useful information.
|
Chris@87
|
650
|
Chris@87
|
651 Parameters
|
Chris@87
|
652 ----------
|
Chris@87
|
653 object : numpy object
|
Chris@87
|
654 Input object. This can be any object (function, class, module,
|
Chris@87
|
655 ...).
|
Chris@87
|
656 output : file object, optional
|
Chris@87
|
657 If `output` not supplied then source code is printed to screen
|
Chris@87
|
658 (sys.stdout). File object must be created with either write 'w' or
|
Chris@87
|
659 append 'a' modes.
|
Chris@87
|
660
|
Chris@87
|
661 See Also
|
Chris@87
|
662 --------
|
Chris@87
|
663 lookfor, info
|
Chris@87
|
664
|
Chris@87
|
665 Examples
|
Chris@87
|
666 --------
|
Chris@87
|
667 >>> np.source(np.interp) #doctest: +SKIP
|
Chris@87
|
668 In file: /usr/lib/python2.6/dist-packages/numpy/lib/function_base.py
|
Chris@87
|
669 def interp(x, xp, fp, left=None, right=None):
|
Chris@87
|
670 \"\"\".... (full docstring printed)\"\"\"
|
Chris@87
|
671 if isinstance(x, (float, int, number)):
|
Chris@87
|
672 return compiled_interp([x], xp, fp, left, right).item()
|
Chris@87
|
673 else:
|
Chris@87
|
674 return compiled_interp(x, xp, fp, left, right)
|
Chris@87
|
675
|
Chris@87
|
676 The source code is only returned for objects written in Python.
|
Chris@87
|
677
|
Chris@87
|
678 >>> np.source(np.array) #doctest: +SKIP
|
Chris@87
|
679 Not available for this object.
|
Chris@87
|
680
|
Chris@87
|
681 """
|
Chris@87
|
682 # Local import to speed up numpy's import time.
|
Chris@87
|
683 import inspect
|
Chris@87
|
684 try:
|
Chris@87
|
685 print("In file: %s\n" % inspect.getsourcefile(object), file=output)
|
Chris@87
|
686 print(inspect.getsource(object), file=output)
|
Chris@87
|
687 except:
|
Chris@87
|
688 print("Not available for this object.", file=output)
|
Chris@87
|
689
|
Chris@87
|
690
|
Chris@87
|
691 # Cache for lookfor: {id(module): {name: (docstring, kind, index), ...}...}
|
Chris@87
|
692 # where kind: "func", "class", "module", "object"
|
Chris@87
|
693 # and index: index in breadth-first namespace traversal
|
Chris@87
|
694 _lookfor_caches = {}
|
Chris@87
|
695
|
Chris@87
|
696 # regexp whose match indicates that the string may contain a function
|
Chris@87
|
697 # signature
|
Chris@87
|
698 _function_signature_re = re.compile(r"[a-z0-9_]+\(.*[,=].*\)", re.I)
|
Chris@87
|
699
|
Chris@87
|
700 def lookfor(what, module=None, import_modules=True, regenerate=False,
|
Chris@87
|
701 output=None):
|
Chris@87
|
702 """
|
Chris@87
|
703 Do a keyword search on docstrings.
|
Chris@87
|
704
|
Chris@87
|
705 A list of of objects that matched the search is displayed,
|
Chris@87
|
706 sorted by relevance. All given keywords need to be found in the
|
Chris@87
|
707 docstring for it to be returned as a result, but the order does
|
Chris@87
|
708 not matter.
|
Chris@87
|
709
|
Chris@87
|
710 Parameters
|
Chris@87
|
711 ----------
|
Chris@87
|
712 what : str
|
Chris@87
|
713 String containing words to look for.
|
Chris@87
|
714 module : str or list, optional
|
Chris@87
|
715 Name of module(s) whose docstrings to go through.
|
Chris@87
|
716 import_modules : bool, optional
|
Chris@87
|
717 Whether to import sub-modules in packages. Default is True.
|
Chris@87
|
718 regenerate : bool, optional
|
Chris@87
|
719 Whether to re-generate the docstring cache. Default is False.
|
Chris@87
|
720 output : file-like, optional
|
Chris@87
|
721 File-like object to write the output to. If omitted, use a pager.
|
Chris@87
|
722
|
Chris@87
|
723 See Also
|
Chris@87
|
724 --------
|
Chris@87
|
725 source, info
|
Chris@87
|
726
|
Chris@87
|
727 Notes
|
Chris@87
|
728 -----
|
Chris@87
|
729 Relevance is determined only roughly, by checking if the keywords occur
|
Chris@87
|
730 in the function name, at the start of a docstring, etc.
|
Chris@87
|
731
|
Chris@87
|
732 Examples
|
Chris@87
|
733 --------
|
Chris@87
|
734 >>> np.lookfor('binary representation')
|
Chris@87
|
735 Search results for 'binary representation'
|
Chris@87
|
736 ------------------------------------------
|
Chris@87
|
737 numpy.binary_repr
|
Chris@87
|
738 Return the binary representation of the input number as a string.
|
Chris@87
|
739 numpy.core.setup_common.long_double_representation
|
Chris@87
|
740 Given a binary dump as given by GNU od -b, look for long double
|
Chris@87
|
741 numpy.base_repr
|
Chris@87
|
742 Return a string representation of a number in the given base system.
|
Chris@87
|
743 ...
|
Chris@87
|
744
|
Chris@87
|
745 """
|
Chris@87
|
746 import pydoc
|
Chris@87
|
747
|
Chris@87
|
748 # Cache
|
Chris@87
|
749 cache = _lookfor_generate_cache(module, import_modules, regenerate)
|
Chris@87
|
750
|
Chris@87
|
751 # Search
|
Chris@87
|
752 # XXX: maybe using a real stemming search engine would be better?
|
Chris@87
|
753 found = []
|
Chris@87
|
754 whats = str(what).lower().split()
|
Chris@87
|
755 if not whats:
|
Chris@87
|
756 return
|
Chris@87
|
757
|
Chris@87
|
758 for name, (docstring, kind, index) in cache.items():
|
Chris@87
|
759 if kind in ('module', 'object'):
|
Chris@87
|
760 # don't show modules or objects
|
Chris@87
|
761 continue
|
Chris@87
|
762 ok = True
|
Chris@87
|
763 doc = docstring.lower()
|
Chris@87
|
764 for w in whats:
|
Chris@87
|
765 if w not in doc:
|
Chris@87
|
766 ok = False
|
Chris@87
|
767 break
|
Chris@87
|
768 if ok:
|
Chris@87
|
769 found.append(name)
|
Chris@87
|
770
|
Chris@87
|
771 # Relevance sort
|
Chris@87
|
772 # XXX: this is full Harrison-Stetson heuristics now,
|
Chris@87
|
773 # XXX: it probably could be improved
|
Chris@87
|
774
|
Chris@87
|
775 kind_relevance = {'func': 1000, 'class': 1000,
|
Chris@87
|
776 'module': -1000, 'object': -1000}
|
Chris@87
|
777
|
Chris@87
|
778 def relevance(name, docstr, kind, index):
|
Chris@87
|
779 r = 0
|
Chris@87
|
780 # do the keywords occur within the start of the docstring?
|
Chris@87
|
781 first_doc = "\n".join(docstr.lower().strip().split("\n")[:3])
|
Chris@87
|
782 r += sum([200 for w in whats if w in first_doc])
|
Chris@87
|
783 # do the keywords occur in the function name?
|
Chris@87
|
784 r += sum([30 for w in whats if w in name])
|
Chris@87
|
785 # is the full name long?
|
Chris@87
|
786 r += -len(name) * 5
|
Chris@87
|
787 # is the object of bad type?
|
Chris@87
|
788 r += kind_relevance.get(kind, -1000)
|
Chris@87
|
789 # is the object deep in namespace hierarchy?
|
Chris@87
|
790 r += -name.count('.') * 10
|
Chris@87
|
791 r += max(-index / 100, -100)
|
Chris@87
|
792 return r
|
Chris@87
|
793
|
Chris@87
|
794 def relevance_value(a):
|
Chris@87
|
795 return relevance(a, *cache[a])
|
Chris@87
|
796 found.sort(key=relevance_value)
|
Chris@87
|
797
|
Chris@87
|
798 # Pretty-print
|
Chris@87
|
799 s = "Search results for '%s'" % (' '.join(whats))
|
Chris@87
|
800 help_text = [s, "-"*len(s)]
|
Chris@87
|
801 for name in found[::-1]:
|
Chris@87
|
802 doc, kind, ix = cache[name]
|
Chris@87
|
803
|
Chris@87
|
804 doclines = [line.strip() for line in doc.strip().split("\n")
|
Chris@87
|
805 if line.strip()]
|
Chris@87
|
806
|
Chris@87
|
807 # find a suitable short description
|
Chris@87
|
808 try:
|
Chris@87
|
809 first_doc = doclines[0].strip()
|
Chris@87
|
810 if _function_signature_re.search(first_doc):
|
Chris@87
|
811 first_doc = doclines[1].strip()
|
Chris@87
|
812 except IndexError:
|
Chris@87
|
813 first_doc = ""
|
Chris@87
|
814 help_text.append("%s\n %s" % (name, first_doc))
|
Chris@87
|
815
|
Chris@87
|
816 if not found:
|
Chris@87
|
817 help_text.append("Nothing found.")
|
Chris@87
|
818
|
Chris@87
|
819 # Output
|
Chris@87
|
820 if output is not None:
|
Chris@87
|
821 output.write("\n".join(help_text))
|
Chris@87
|
822 elif len(help_text) > 10:
|
Chris@87
|
823 pager = pydoc.getpager()
|
Chris@87
|
824 pager("\n".join(help_text))
|
Chris@87
|
825 else:
|
Chris@87
|
826 print("\n".join(help_text))
|
Chris@87
|
827
|
Chris@87
|
828 def _lookfor_generate_cache(module, import_modules, regenerate):
|
Chris@87
|
829 """
|
Chris@87
|
830 Generate docstring cache for given module.
|
Chris@87
|
831
|
Chris@87
|
832 Parameters
|
Chris@87
|
833 ----------
|
Chris@87
|
834 module : str, None, module
|
Chris@87
|
835 Module for which to generate docstring cache
|
Chris@87
|
836 import_modules : bool
|
Chris@87
|
837 Whether to import sub-modules in packages.
|
Chris@87
|
838 regenerate : bool
|
Chris@87
|
839 Re-generate the docstring cache
|
Chris@87
|
840
|
Chris@87
|
841 Returns
|
Chris@87
|
842 -------
|
Chris@87
|
843 cache : dict {obj_full_name: (docstring, kind, index), ...}
|
Chris@87
|
844 Docstring cache for the module, either cached one (regenerate=False)
|
Chris@87
|
845 or newly generated.
|
Chris@87
|
846
|
Chris@87
|
847 """
|
Chris@87
|
848 global _lookfor_caches
|
Chris@87
|
849 # Local import to speed up numpy's import time.
|
Chris@87
|
850 import inspect
|
Chris@87
|
851
|
Chris@87
|
852 if sys.version_info[0] >= 3:
|
Chris@87
|
853 # In Python3 stderr, stdout are text files.
|
Chris@87
|
854 from io import StringIO
|
Chris@87
|
855 else:
|
Chris@87
|
856 from StringIO import StringIO
|
Chris@87
|
857
|
Chris@87
|
858 if module is None:
|
Chris@87
|
859 module = "numpy"
|
Chris@87
|
860
|
Chris@87
|
861 if isinstance(module, str):
|
Chris@87
|
862 try:
|
Chris@87
|
863 __import__(module)
|
Chris@87
|
864 except ImportError:
|
Chris@87
|
865 return {}
|
Chris@87
|
866 module = sys.modules[module]
|
Chris@87
|
867 elif isinstance(module, list) or isinstance(module, tuple):
|
Chris@87
|
868 cache = {}
|
Chris@87
|
869 for mod in module:
|
Chris@87
|
870 cache.update(_lookfor_generate_cache(mod, import_modules,
|
Chris@87
|
871 regenerate))
|
Chris@87
|
872 return cache
|
Chris@87
|
873
|
Chris@87
|
874 if id(module) in _lookfor_caches and not regenerate:
|
Chris@87
|
875 return _lookfor_caches[id(module)]
|
Chris@87
|
876
|
Chris@87
|
877 # walk items and collect docstrings
|
Chris@87
|
878 cache = {}
|
Chris@87
|
879 _lookfor_caches[id(module)] = cache
|
Chris@87
|
880 seen = {}
|
Chris@87
|
881 index = 0
|
Chris@87
|
882 stack = [(module.__name__, module)]
|
Chris@87
|
883 while stack:
|
Chris@87
|
884 name, item = stack.pop(0)
|
Chris@87
|
885 if id(item) in seen:
|
Chris@87
|
886 continue
|
Chris@87
|
887 seen[id(item)] = True
|
Chris@87
|
888
|
Chris@87
|
889 index += 1
|
Chris@87
|
890 kind = "object"
|
Chris@87
|
891
|
Chris@87
|
892 if inspect.ismodule(item):
|
Chris@87
|
893 kind = "module"
|
Chris@87
|
894 try:
|
Chris@87
|
895 _all = item.__all__
|
Chris@87
|
896 except AttributeError:
|
Chris@87
|
897 _all = None
|
Chris@87
|
898
|
Chris@87
|
899 # import sub-packages
|
Chris@87
|
900 if import_modules and hasattr(item, '__path__'):
|
Chris@87
|
901 for pth in item.__path__:
|
Chris@87
|
902 for mod_path in os.listdir(pth):
|
Chris@87
|
903 this_py = os.path.join(pth, mod_path)
|
Chris@87
|
904 init_py = os.path.join(pth, mod_path, '__init__.py')
|
Chris@87
|
905 if (os.path.isfile(this_py) and
|
Chris@87
|
906 mod_path.endswith('.py')):
|
Chris@87
|
907 to_import = mod_path[:-3]
|
Chris@87
|
908 elif os.path.isfile(init_py):
|
Chris@87
|
909 to_import = mod_path
|
Chris@87
|
910 else:
|
Chris@87
|
911 continue
|
Chris@87
|
912 if to_import == '__init__':
|
Chris@87
|
913 continue
|
Chris@87
|
914
|
Chris@87
|
915 try:
|
Chris@87
|
916 # Catch SystemExit, too
|
Chris@87
|
917 base_exc = BaseException
|
Chris@87
|
918 except NameError:
|
Chris@87
|
919 # Python 2.4 doesn't have BaseException
|
Chris@87
|
920 base_exc = Exception
|
Chris@87
|
921
|
Chris@87
|
922 try:
|
Chris@87
|
923 old_stdout = sys.stdout
|
Chris@87
|
924 old_stderr = sys.stderr
|
Chris@87
|
925 try:
|
Chris@87
|
926 sys.stdout = StringIO()
|
Chris@87
|
927 sys.stderr = StringIO()
|
Chris@87
|
928 __import__("%s.%s" % (name, to_import))
|
Chris@87
|
929 finally:
|
Chris@87
|
930 sys.stdout = old_stdout
|
Chris@87
|
931 sys.stderr = old_stderr
|
Chris@87
|
932 except base_exc:
|
Chris@87
|
933 continue
|
Chris@87
|
934
|
Chris@87
|
935 for n, v in _getmembers(item):
|
Chris@87
|
936 try:
|
Chris@87
|
937 item_name = getattr(v, '__name__', "%s.%s" % (name, n))
|
Chris@87
|
938 mod_name = getattr(v, '__module__', None)
|
Chris@87
|
939 except NameError:
|
Chris@87
|
940 # ref. SWIG's global cvars
|
Chris@87
|
941 # NameError: Unknown C global variable
|
Chris@87
|
942 item_name = "%s.%s" % (name, n)
|
Chris@87
|
943 mod_name = None
|
Chris@87
|
944 if '.' not in item_name and mod_name:
|
Chris@87
|
945 item_name = "%s.%s" % (mod_name, item_name)
|
Chris@87
|
946
|
Chris@87
|
947 if not item_name.startswith(name + '.'):
|
Chris@87
|
948 # don't crawl "foreign" objects
|
Chris@87
|
949 if isinstance(v, ufunc):
|
Chris@87
|
950 # ... unless they are ufuncs
|
Chris@87
|
951 pass
|
Chris@87
|
952 else:
|
Chris@87
|
953 continue
|
Chris@87
|
954 elif not (inspect.ismodule(v) or _all is None or n in _all):
|
Chris@87
|
955 continue
|
Chris@87
|
956 stack.append(("%s.%s" % (name, n), v))
|
Chris@87
|
957 elif inspect.isclass(item):
|
Chris@87
|
958 kind = "class"
|
Chris@87
|
959 for n, v in _getmembers(item):
|
Chris@87
|
960 stack.append(("%s.%s" % (name, n), v))
|
Chris@87
|
961 elif hasattr(item, "__call__"):
|
Chris@87
|
962 kind = "func"
|
Chris@87
|
963
|
Chris@87
|
964 try:
|
Chris@87
|
965 doc = inspect.getdoc(item)
|
Chris@87
|
966 except NameError:
|
Chris@87
|
967 # ref SWIG's NameError: Unknown C global variable
|
Chris@87
|
968 doc = None
|
Chris@87
|
969 if doc is not None:
|
Chris@87
|
970 cache[name] = (doc, kind, index)
|
Chris@87
|
971
|
Chris@87
|
972 return cache
|
Chris@87
|
973
|
Chris@87
|
974 def _getmembers(item):
|
Chris@87
|
975 import inspect
|
Chris@87
|
976 try:
|
Chris@87
|
977 members = inspect.getmembers(item)
|
Chris@87
|
978 except AttributeError:
|
Chris@87
|
979 members = [(x, getattr(item, x)) for x in dir(item)
|
Chris@87
|
980 if hasattr(item, x)]
|
Chris@87
|
981 return members
|
Chris@87
|
982
|
Chris@87
|
983 #-----------------------------------------------------------------------------
|
Chris@87
|
984
|
Chris@87
|
985 # The following SafeEval class and company are adapted from Michael Spencer's
|
Chris@87
|
986 # ASPN Python Cookbook recipe:
|
Chris@87
|
987 # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/364469
|
Chris@87
|
988 # Accordingly it is mostly Copyright 2006 by Michael Spencer.
|
Chris@87
|
989 # The recipe, like most of the other ASPN Python Cookbook recipes was made
|
Chris@87
|
990 # available under the Python license.
|
Chris@87
|
991 # http://www.python.org/license
|
Chris@87
|
992
|
Chris@87
|
993 # It has been modified to:
|
Chris@87
|
994 # * handle unary -/+
|
Chris@87
|
995 # * support True/False/None
|
Chris@87
|
996 # * raise SyntaxError instead of a custom exception.
|
Chris@87
|
997
|
Chris@87
|
998 class SafeEval(object):
|
Chris@87
|
999 """
|
Chris@87
|
1000 Object to evaluate constant string expressions.
|
Chris@87
|
1001
|
Chris@87
|
1002 This includes strings with lists, dicts and tuples using the abstract
|
Chris@87
|
1003 syntax tree created by ``compiler.parse``.
|
Chris@87
|
1004
|
Chris@87
|
1005 For an example of usage, see `safe_eval`.
|
Chris@87
|
1006
|
Chris@87
|
1007 See Also
|
Chris@87
|
1008 --------
|
Chris@87
|
1009 safe_eval
|
Chris@87
|
1010
|
Chris@87
|
1011 """
|
Chris@87
|
1012
|
Chris@87
|
1013 if sys.version_info[0] < 3:
|
Chris@87
|
1014 def visit(self, node, **kw):
|
Chris@87
|
1015 cls = node.__class__
|
Chris@87
|
1016 meth = getattr(self, 'visit'+cls.__name__, self.default)
|
Chris@87
|
1017 return meth(node, **kw)
|
Chris@87
|
1018
|
Chris@87
|
1019 def default(self, node, **kw):
|
Chris@87
|
1020 raise SyntaxError("Unsupported source construct: %s"
|
Chris@87
|
1021 % node.__class__)
|
Chris@87
|
1022
|
Chris@87
|
1023 def visitExpression(self, node, **kw):
|
Chris@87
|
1024 for child in node.getChildNodes():
|
Chris@87
|
1025 return self.visit(child, **kw)
|
Chris@87
|
1026
|
Chris@87
|
1027 def visitConst(self, node, **kw):
|
Chris@87
|
1028 return node.value
|
Chris@87
|
1029
|
Chris@87
|
1030 def visitDict(self, node,**kw):
|
Chris@87
|
1031 return dict(
|
Chris@87
|
1032 [(self.visit(k), self.visit(v)) for k, v in node.items]
|
Chris@87
|
1033 )
|
Chris@87
|
1034
|
Chris@87
|
1035 def visitTuple(self, node, **kw):
|
Chris@87
|
1036 return tuple([self.visit(i) for i in node.nodes])
|
Chris@87
|
1037
|
Chris@87
|
1038 def visitList(self, node, **kw):
|
Chris@87
|
1039 return [self.visit(i) for i in node.nodes]
|
Chris@87
|
1040
|
Chris@87
|
1041 def visitUnaryAdd(self, node, **kw):
|
Chris@87
|
1042 return +self.visit(node.getChildNodes()[0])
|
Chris@87
|
1043
|
Chris@87
|
1044 def visitUnarySub(self, node, **kw):
|
Chris@87
|
1045 return -self.visit(node.getChildNodes()[0])
|
Chris@87
|
1046
|
Chris@87
|
1047 def visitName(self, node, **kw):
|
Chris@87
|
1048 if node.name == 'False':
|
Chris@87
|
1049 return False
|
Chris@87
|
1050 elif node.name == 'True':
|
Chris@87
|
1051 return True
|
Chris@87
|
1052 elif node.name == 'None':
|
Chris@87
|
1053 return None
|
Chris@87
|
1054 else:
|
Chris@87
|
1055 raise SyntaxError("Unknown name: %s" % node.name)
|
Chris@87
|
1056 else:
|
Chris@87
|
1057
|
Chris@87
|
1058 def visit(self, node):
|
Chris@87
|
1059 cls = node.__class__
|
Chris@87
|
1060 meth = getattr(self, 'visit' + cls.__name__, self.default)
|
Chris@87
|
1061 return meth(node)
|
Chris@87
|
1062
|
Chris@87
|
1063 def default(self, node):
|
Chris@87
|
1064 raise SyntaxError("Unsupported source construct: %s"
|
Chris@87
|
1065 % node.__class__)
|
Chris@87
|
1066
|
Chris@87
|
1067 def visitExpression(self, node):
|
Chris@87
|
1068 return self.visit(node.body)
|
Chris@87
|
1069
|
Chris@87
|
1070 def visitNum(self, node):
|
Chris@87
|
1071 return node.n
|
Chris@87
|
1072
|
Chris@87
|
1073 def visitStr(self, node):
|
Chris@87
|
1074 return node.s
|
Chris@87
|
1075
|
Chris@87
|
1076 def visitBytes(self, node):
|
Chris@87
|
1077 return node.s
|
Chris@87
|
1078
|
Chris@87
|
1079 def visitDict(self, node,**kw):
|
Chris@87
|
1080 return dict([(self.visit(k), self.visit(v))
|
Chris@87
|
1081 for k, v in zip(node.keys, node.values)])
|
Chris@87
|
1082
|
Chris@87
|
1083 def visitTuple(self, node):
|
Chris@87
|
1084 return tuple([self.visit(i) for i in node.elts])
|
Chris@87
|
1085
|
Chris@87
|
1086 def visitList(self, node):
|
Chris@87
|
1087 return [self.visit(i) for i in node.elts]
|
Chris@87
|
1088
|
Chris@87
|
1089 def visitUnaryOp(self, node):
|
Chris@87
|
1090 import ast
|
Chris@87
|
1091 if isinstance(node.op, ast.UAdd):
|
Chris@87
|
1092 return +self.visit(node.operand)
|
Chris@87
|
1093 elif isinstance(node.op, ast.USub):
|
Chris@87
|
1094 return -self.visit(node.operand)
|
Chris@87
|
1095 else:
|
Chris@87
|
1096 raise SyntaxError("Unknown unary op: %r" % node.op)
|
Chris@87
|
1097
|
Chris@87
|
1098 def visitName(self, node):
|
Chris@87
|
1099 if node.id == 'False':
|
Chris@87
|
1100 return False
|
Chris@87
|
1101 elif node.id == 'True':
|
Chris@87
|
1102 return True
|
Chris@87
|
1103 elif node.id == 'None':
|
Chris@87
|
1104 return None
|
Chris@87
|
1105 else:
|
Chris@87
|
1106 raise SyntaxError("Unknown name: %s" % node.id)
|
Chris@87
|
1107
|
Chris@87
|
1108 def visitNameConstant(self, node):
|
Chris@87
|
1109 return node.value
|
Chris@87
|
1110
|
Chris@87
|
1111 def safe_eval(source):
|
Chris@87
|
1112 """
|
Chris@87
|
1113 Protected string evaluation.
|
Chris@87
|
1114
|
Chris@87
|
1115 Evaluate a string containing a Python literal expression without
|
Chris@87
|
1116 allowing the execution of arbitrary non-literal code.
|
Chris@87
|
1117
|
Chris@87
|
1118 Parameters
|
Chris@87
|
1119 ----------
|
Chris@87
|
1120 source : str
|
Chris@87
|
1121 The string to evaluate.
|
Chris@87
|
1122
|
Chris@87
|
1123 Returns
|
Chris@87
|
1124 -------
|
Chris@87
|
1125 obj : object
|
Chris@87
|
1126 The result of evaluating `source`.
|
Chris@87
|
1127
|
Chris@87
|
1128 Raises
|
Chris@87
|
1129 ------
|
Chris@87
|
1130 SyntaxError
|
Chris@87
|
1131 If the code has invalid Python syntax, or if it contains
|
Chris@87
|
1132 non-literal code.
|
Chris@87
|
1133
|
Chris@87
|
1134 Examples
|
Chris@87
|
1135 --------
|
Chris@87
|
1136 >>> np.safe_eval('1')
|
Chris@87
|
1137 1
|
Chris@87
|
1138 >>> np.safe_eval('[1, 2, 3]')
|
Chris@87
|
1139 [1, 2, 3]
|
Chris@87
|
1140 >>> np.safe_eval('{"foo": ("bar", 10.0)}')
|
Chris@87
|
1141 {'foo': ('bar', 10.0)}
|
Chris@87
|
1142
|
Chris@87
|
1143 >>> np.safe_eval('import os')
|
Chris@87
|
1144 Traceback (most recent call last):
|
Chris@87
|
1145 ...
|
Chris@87
|
1146 SyntaxError: invalid syntax
|
Chris@87
|
1147
|
Chris@87
|
1148 >>> np.safe_eval('open("/home/user/.ssh/id_dsa").read()')
|
Chris@87
|
1149 Traceback (most recent call last):
|
Chris@87
|
1150 ...
|
Chris@87
|
1151 SyntaxError: Unsupported source construct: compiler.ast.CallFunc
|
Chris@87
|
1152
|
Chris@87
|
1153 """
|
Chris@87
|
1154 # Local imports to speed up numpy's import time.
|
Chris@87
|
1155 import warnings
|
Chris@87
|
1156
|
Chris@87
|
1157 with warnings.catch_warnings():
|
Chris@87
|
1158 # compiler package is deprecated for 3.x, which is already solved
|
Chris@87
|
1159 # here
|
Chris@87
|
1160 warnings.simplefilter('ignore', DeprecationWarning)
|
Chris@87
|
1161 try:
|
Chris@87
|
1162 import compiler
|
Chris@87
|
1163 except ImportError:
|
Chris@87
|
1164 import ast as compiler
|
Chris@87
|
1165
|
Chris@87
|
1166 walker = SafeEval()
|
Chris@87
|
1167 try:
|
Chris@87
|
1168 ast = compiler.parse(source, mode="eval")
|
Chris@87
|
1169 except SyntaxError:
|
Chris@87
|
1170 raise
|
Chris@87
|
1171 try:
|
Chris@87
|
1172 return walker.visit(ast)
|
Chris@87
|
1173 except SyntaxError:
|
Chris@87
|
1174 raise
|
Chris@87
|
1175
|
Chris@87
|
1176 #-----------------------------------------------------------------------------
|