##// END OF EJS Templates
remove accidentally committed print statement
MinRK -
Show More
@@ -1,875 +1,874 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Tools for inspecting Python objects.
2 """Tools for inspecting Python objects.
3
3
4 Uses syntax highlighting for presenting the various information elements.
4 Uses syntax highlighting for presenting the various information elements.
5
5
6 Similar in spirit to the inspect module, but all calls take a name argument to
6 Similar in spirit to the inspect module, but all calls take a name argument to
7 reference the name under which an object is being read.
7 reference the name under which an object is being read.
8 """
8 """
9
9
10 #*****************************************************************************
10 #*****************************************************************************
11 # Copyright (C) 2001-2004 Fernando Perez <fperez@colorado.edu>
11 # Copyright (C) 2001-2004 Fernando Perez <fperez@colorado.edu>
12 #
12 #
13 # Distributed under the terms of the BSD License. The full license is in
13 # Distributed under the terms of the BSD License. The full license is in
14 # the file COPYING, distributed as part of this software.
14 # the file COPYING, distributed as part of this software.
15 #*****************************************************************************
15 #*****************************************************************************
16 from __future__ import print_function
16 from __future__ import print_function
17
17
18 __all__ = ['Inspector','InspectColors']
18 __all__ = ['Inspector','InspectColors']
19
19
20 # stdlib modules
20 # stdlib modules
21 import inspect
21 import inspect
22 import linecache
22 import linecache
23 import os
23 import os
24 import types
24 import types
25 import io as stdlib_io
25 import io as stdlib_io
26
26
27 try:
27 try:
28 from itertools import izip_longest
28 from itertools import izip_longest
29 except ImportError:
29 except ImportError:
30 from itertools import zip_longest as izip_longest
30 from itertools import zip_longest as izip_longest
31
31
32 # IPython's own
32 # IPython's own
33 from IPython.core import page
33 from IPython.core import page
34 from IPython.testing.skipdoctest import skip_doctest_py3
34 from IPython.testing.skipdoctest import skip_doctest_py3
35 from IPython.utils import PyColorize
35 from IPython.utils import PyColorize
36 from IPython.utils import io
36 from IPython.utils import io
37 from IPython.utils import openpy
37 from IPython.utils import openpy
38 from IPython.utils import py3compat
38 from IPython.utils import py3compat
39 from IPython.utils.dir2 import safe_hasattr
39 from IPython.utils.dir2 import safe_hasattr
40 from IPython.utils.text import indent
40 from IPython.utils.text import indent
41 from IPython.utils.wildcard import list_namespace
41 from IPython.utils.wildcard import list_namespace
42 from IPython.utils.coloransi import *
42 from IPython.utils.coloransi import *
43 from IPython.utils.py3compat import cast_unicode, string_types
43 from IPython.utils.py3compat import cast_unicode, string_types
44
44
45 # builtin docstrings to ignore
45 # builtin docstrings to ignore
46 _func_call_docstring = types.FunctionType.__call__.__doc__
46 _func_call_docstring = types.FunctionType.__call__.__doc__
47 _object_init_docstring = object.__init__.__doc__
47 _object_init_docstring = object.__init__.__doc__
48 _builtin_type_docstrings = {
48 _builtin_type_docstrings = {
49 t.__doc__ for t in (types.ModuleType, types.MethodType, types.FunctionType)
49 t.__doc__ for t in (types.ModuleType, types.MethodType, types.FunctionType)
50 }
50 }
51 #****************************************************************************
51 #****************************************************************************
52 # Builtin color schemes
52 # Builtin color schemes
53
53
54 Colors = TermColors # just a shorthand
54 Colors = TermColors # just a shorthand
55
55
56 # Build a few color schemes
56 # Build a few color schemes
57 NoColor = ColorScheme(
57 NoColor = ColorScheme(
58 'NoColor',{
58 'NoColor',{
59 'header' : Colors.NoColor,
59 'header' : Colors.NoColor,
60 'normal' : Colors.NoColor # color off (usu. Colors.Normal)
60 'normal' : Colors.NoColor # color off (usu. Colors.Normal)
61 } )
61 } )
62
62
63 LinuxColors = ColorScheme(
63 LinuxColors = ColorScheme(
64 'Linux',{
64 'Linux',{
65 'header' : Colors.LightRed,
65 'header' : Colors.LightRed,
66 'normal' : Colors.Normal # color off (usu. Colors.Normal)
66 'normal' : Colors.Normal # color off (usu. Colors.Normal)
67 } )
67 } )
68
68
69 LightBGColors = ColorScheme(
69 LightBGColors = ColorScheme(
70 'LightBG',{
70 'LightBG',{
71 'header' : Colors.Red,
71 'header' : Colors.Red,
72 'normal' : Colors.Normal # color off (usu. Colors.Normal)
72 'normal' : Colors.Normal # color off (usu. Colors.Normal)
73 } )
73 } )
74
74
75 # Build table of color schemes (needed by the parser)
75 # Build table of color schemes (needed by the parser)
76 InspectColors = ColorSchemeTable([NoColor,LinuxColors,LightBGColors],
76 InspectColors = ColorSchemeTable([NoColor,LinuxColors,LightBGColors],
77 'Linux')
77 'Linux')
78
78
79 #****************************************************************************
79 #****************************************************************************
80 # Auxiliary functions and objects
80 # Auxiliary functions and objects
81
81
82 # See the messaging spec for the definition of all these fields. This list
82 # See the messaging spec for the definition of all these fields. This list
83 # effectively defines the order of display
83 # effectively defines the order of display
84 info_fields = ['type_name', 'base_class', 'string_form', 'namespace',
84 info_fields = ['type_name', 'base_class', 'string_form', 'namespace',
85 'length', 'file', 'definition', 'docstring', 'source',
85 'length', 'file', 'definition', 'docstring', 'source',
86 'init_definition', 'class_docstring', 'init_docstring',
86 'init_definition', 'class_docstring', 'init_docstring',
87 'call_def', 'call_docstring',
87 'call_def', 'call_docstring',
88 # These won't be printed but will be used to determine how to
88 # These won't be printed but will be used to determine how to
89 # format the object
89 # format the object
90 'ismagic', 'isalias', 'isclass', 'argspec', 'found', 'name'
90 'ismagic', 'isalias', 'isclass', 'argspec', 'found', 'name'
91 ]
91 ]
92
92
93
93
94 def object_info(**kw):
94 def object_info(**kw):
95 """Make an object info dict with all fields present."""
95 """Make an object info dict with all fields present."""
96 infodict = dict(izip_longest(info_fields, [None]))
96 infodict = dict(izip_longest(info_fields, [None]))
97 infodict.update(kw)
97 infodict.update(kw)
98 return infodict
98 return infodict
99
99
100
100
101 def get_encoding(obj):
101 def get_encoding(obj):
102 """Get encoding for python source file defining obj
102 """Get encoding for python source file defining obj
103
103
104 Returns None if obj is not defined in a sourcefile.
104 Returns None if obj is not defined in a sourcefile.
105 """
105 """
106 ofile = find_file(obj)
106 ofile = find_file(obj)
107 # run contents of file through pager starting at line where the object
107 # run contents of file through pager starting at line where the object
108 # is defined, as long as the file isn't binary and is actually on the
108 # is defined, as long as the file isn't binary and is actually on the
109 # filesystem.
109 # filesystem.
110 if ofile is None:
110 if ofile is None:
111 return None
111 return None
112 elif ofile.endswith(('.so', '.dll', '.pyd')):
112 elif ofile.endswith(('.so', '.dll', '.pyd')):
113 return None
113 return None
114 elif not os.path.isfile(ofile):
114 elif not os.path.isfile(ofile):
115 return None
115 return None
116 else:
116 else:
117 # Print only text files, not extension binaries. Note that
117 # Print only text files, not extension binaries. Note that
118 # getsourcelines returns lineno with 1-offset and page() uses
118 # getsourcelines returns lineno with 1-offset and page() uses
119 # 0-offset, so we must adjust.
119 # 0-offset, so we must adjust.
120 buffer = stdlib_io.open(ofile, 'rb') # Tweaked to use io.open for Python 2
120 buffer = stdlib_io.open(ofile, 'rb') # Tweaked to use io.open for Python 2
121 encoding, lines = openpy.detect_encoding(buffer.readline)
121 encoding, lines = openpy.detect_encoding(buffer.readline)
122 return encoding
122 return encoding
123
123
124 def getdoc(obj):
124 def getdoc(obj):
125 """Stable wrapper around inspect.getdoc.
125 """Stable wrapper around inspect.getdoc.
126
126
127 This can't crash because of attribute problems.
127 This can't crash because of attribute problems.
128
128
129 It also attempts to call a getdoc() method on the given object. This
129 It also attempts to call a getdoc() method on the given object. This
130 allows objects which provide their docstrings via non-standard mechanisms
130 allows objects which provide their docstrings via non-standard mechanisms
131 (like Pyro proxies) to still be inspected by ipython's ? system."""
131 (like Pyro proxies) to still be inspected by ipython's ? system."""
132 # Allow objects to offer customized documentation via a getdoc method:
132 # Allow objects to offer customized documentation via a getdoc method:
133 try:
133 try:
134 ds = obj.getdoc()
134 ds = obj.getdoc()
135 except Exception:
135 except Exception:
136 pass
136 pass
137 else:
137 else:
138 # if we get extra info, we add it to the normal docstring.
138 # if we get extra info, we add it to the normal docstring.
139 if isinstance(ds, string_types):
139 if isinstance(ds, string_types):
140 return inspect.cleandoc(ds)
140 return inspect.cleandoc(ds)
141
141
142 try:
142 try:
143 docstr = inspect.getdoc(obj)
143 docstr = inspect.getdoc(obj)
144 encoding = get_encoding(obj)
144 encoding = get_encoding(obj)
145 return py3compat.cast_unicode(docstr, encoding=encoding)
145 return py3compat.cast_unicode(docstr, encoding=encoding)
146 except Exception:
146 except Exception:
147 # Harden against an inspect failure, which can occur with
147 # Harden against an inspect failure, which can occur with
148 # SWIG-wrapped extensions.
148 # SWIG-wrapped extensions.
149 raise
149 raise
150 return None
150 return None
151
151
152
152
153 def getsource(obj,is_binary=False):
153 def getsource(obj,is_binary=False):
154 """Wrapper around inspect.getsource.
154 """Wrapper around inspect.getsource.
155
155
156 This can be modified by other projects to provide customized source
156 This can be modified by other projects to provide customized source
157 extraction.
157 extraction.
158
158
159 Inputs:
159 Inputs:
160
160
161 - obj: an object whose source code we will attempt to extract.
161 - obj: an object whose source code we will attempt to extract.
162
162
163 Optional inputs:
163 Optional inputs:
164
164
165 - is_binary: whether the object is known to come from a binary source.
165 - is_binary: whether the object is known to come from a binary source.
166 This implementation will skip returning any output for binary objects, but
166 This implementation will skip returning any output for binary objects, but
167 custom extractors may know how to meaningfully process them."""
167 custom extractors may know how to meaningfully process them."""
168
168
169 if is_binary:
169 if is_binary:
170 return None
170 return None
171 else:
171 else:
172 # get source if obj was decorated with @decorator
172 # get source if obj was decorated with @decorator
173 if hasattr(obj,"__wrapped__"):
173 if hasattr(obj,"__wrapped__"):
174 obj = obj.__wrapped__
174 obj = obj.__wrapped__
175 try:
175 try:
176 src = inspect.getsource(obj)
176 src = inspect.getsource(obj)
177 except TypeError:
177 except TypeError:
178 if hasattr(obj,'__class__'):
178 if hasattr(obj,'__class__'):
179 src = inspect.getsource(obj.__class__)
179 src = inspect.getsource(obj.__class__)
180 encoding = get_encoding(obj)
180 encoding = get_encoding(obj)
181 return cast_unicode(src, encoding=encoding)
181 return cast_unicode(src, encoding=encoding)
182
182
183 def getargspec(obj):
183 def getargspec(obj):
184 """Get the names and default values of a function's arguments.
184 """Get the names and default values of a function's arguments.
185
185
186 A tuple of four things is returned: (args, varargs, varkw, defaults).
186 A tuple of four things is returned: (args, varargs, varkw, defaults).
187 'args' is a list of the argument names (it may contain nested lists).
187 'args' is a list of the argument names (it may contain nested lists).
188 'varargs' and 'varkw' are the names of the * and ** arguments or None.
188 'varargs' and 'varkw' are the names of the * and ** arguments or None.
189 'defaults' is an n-tuple of the default values of the last n arguments.
189 'defaults' is an n-tuple of the default values of the last n arguments.
190
190
191 Modified version of inspect.getargspec from the Python Standard
191 Modified version of inspect.getargspec from the Python Standard
192 Library."""
192 Library."""
193
193
194 if inspect.isfunction(obj):
194 if inspect.isfunction(obj):
195 func_obj = obj
195 func_obj = obj
196 elif inspect.ismethod(obj):
196 elif inspect.ismethod(obj):
197 func_obj = obj.__func__
197 func_obj = obj.__func__
198 elif hasattr(obj, '__call__'):
198 elif hasattr(obj, '__call__'):
199 func_obj = obj.__call__
199 func_obj = obj.__call__
200 else:
200 else:
201 raise TypeError('arg is not a Python function')
201 raise TypeError('arg is not a Python function')
202 args, varargs, varkw = inspect.getargs(func_obj.__code__)
202 args, varargs, varkw = inspect.getargs(func_obj.__code__)
203 return args, varargs, varkw, func_obj.__defaults__
203 return args, varargs, varkw, func_obj.__defaults__
204
204
205
205
206 def format_argspec(argspec):
206 def format_argspec(argspec):
207 """Format argspect, convenience wrapper around inspect's.
207 """Format argspect, convenience wrapper around inspect's.
208
208
209 This takes a dict instead of ordered arguments and calls
209 This takes a dict instead of ordered arguments and calls
210 inspect.format_argspec with the arguments in the necessary order.
210 inspect.format_argspec with the arguments in the necessary order.
211 """
211 """
212 return inspect.formatargspec(argspec['args'], argspec['varargs'],
212 return inspect.formatargspec(argspec['args'], argspec['varargs'],
213 argspec['varkw'], argspec['defaults'])
213 argspec['varkw'], argspec['defaults'])
214
214
215
215
216 def call_tip(oinfo, format_call=True):
216 def call_tip(oinfo, format_call=True):
217 """Extract call tip data from an oinfo dict.
217 """Extract call tip data from an oinfo dict.
218
218
219 Parameters
219 Parameters
220 ----------
220 ----------
221 oinfo : dict
221 oinfo : dict
222
222
223 format_call : bool, optional
223 format_call : bool, optional
224 If True, the call line is formatted and returned as a string. If not, a
224 If True, the call line is formatted and returned as a string. If not, a
225 tuple of (name, argspec) is returned.
225 tuple of (name, argspec) is returned.
226
226
227 Returns
227 Returns
228 -------
228 -------
229 call_info : None, str or (str, dict) tuple.
229 call_info : None, str or (str, dict) tuple.
230 When format_call is True, the whole call information is formattted as a
230 When format_call is True, the whole call information is formattted as a
231 single string. Otherwise, the object's name and its argspec dict are
231 single string. Otherwise, the object's name and its argspec dict are
232 returned. If no call information is available, None is returned.
232 returned. If no call information is available, None is returned.
233
233
234 docstring : str or None
234 docstring : str or None
235 The most relevant docstring for calling purposes is returned, if
235 The most relevant docstring for calling purposes is returned, if
236 available. The priority is: call docstring for callable instances, then
236 available. The priority is: call docstring for callable instances, then
237 constructor docstring for classes, then main object's docstring otherwise
237 constructor docstring for classes, then main object's docstring otherwise
238 (regular functions).
238 (regular functions).
239 """
239 """
240 # Get call definition
240 # Get call definition
241 argspec = oinfo.get('argspec')
241 argspec = oinfo.get('argspec')
242 if argspec is None:
242 if argspec is None:
243 call_line = None
243 call_line = None
244 else:
244 else:
245 # Callable objects will have 'self' as their first argument, prune
245 # Callable objects will have 'self' as their first argument, prune
246 # it out if it's there for clarity (since users do *not* pass an
246 # it out if it's there for clarity (since users do *not* pass an
247 # extra first argument explicitly).
247 # extra first argument explicitly).
248 try:
248 try:
249 has_self = argspec['args'][0] == 'self'
249 has_self = argspec['args'][0] == 'self'
250 except (KeyError, IndexError):
250 except (KeyError, IndexError):
251 pass
251 pass
252 else:
252 else:
253 if has_self:
253 if has_self:
254 argspec['args'] = argspec['args'][1:]
254 argspec['args'] = argspec['args'][1:]
255
255
256 call_line = oinfo['name']+format_argspec(argspec)
256 call_line = oinfo['name']+format_argspec(argspec)
257
257
258 # Now get docstring.
258 # Now get docstring.
259 # The priority is: call docstring, constructor docstring, main one.
259 # The priority is: call docstring, constructor docstring, main one.
260 doc = oinfo.get('call_docstring')
260 doc = oinfo.get('call_docstring')
261 if doc is None:
261 if doc is None:
262 doc = oinfo.get('init_docstring')
262 doc = oinfo.get('init_docstring')
263 if doc is None:
263 if doc is None:
264 doc = oinfo.get('docstring','')
264 doc = oinfo.get('docstring','')
265
265
266 return call_line, doc
266 return call_line, doc
267
267
268
268
269 def find_file(obj):
269 def find_file(obj):
270 """Find the absolute path to the file where an object was defined.
270 """Find the absolute path to the file where an object was defined.
271
271
272 This is essentially a robust wrapper around `inspect.getabsfile`.
272 This is essentially a robust wrapper around `inspect.getabsfile`.
273
273
274 Returns None if no file can be found.
274 Returns None if no file can be found.
275
275
276 Parameters
276 Parameters
277 ----------
277 ----------
278 obj : any Python object
278 obj : any Python object
279
279
280 Returns
280 Returns
281 -------
281 -------
282 fname : str
282 fname : str
283 The absolute path to the file where the object was defined.
283 The absolute path to the file where the object was defined.
284 """
284 """
285 # get source if obj was decorated with @decorator
285 # get source if obj was decorated with @decorator
286 if safe_hasattr(obj, '__wrapped__'):
286 if safe_hasattr(obj, '__wrapped__'):
287 obj = obj.__wrapped__
287 obj = obj.__wrapped__
288
288
289 fname = None
289 fname = None
290 try:
290 try:
291 fname = inspect.getabsfile(obj)
291 fname = inspect.getabsfile(obj)
292 except TypeError:
292 except TypeError:
293 # For an instance, the file that matters is where its class was
293 # For an instance, the file that matters is where its class was
294 # declared.
294 # declared.
295 if hasattr(obj, '__class__'):
295 if hasattr(obj, '__class__'):
296 try:
296 try:
297 fname = inspect.getabsfile(obj.__class__)
297 fname = inspect.getabsfile(obj.__class__)
298 except TypeError:
298 except TypeError:
299 # Can happen for builtins
299 # Can happen for builtins
300 pass
300 pass
301 except:
301 except:
302 pass
302 pass
303 return cast_unicode(fname)
303 return cast_unicode(fname)
304
304
305
305
306 def find_source_lines(obj):
306 def find_source_lines(obj):
307 """Find the line number in a file where an object was defined.
307 """Find the line number in a file where an object was defined.
308
308
309 This is essentially a robust wrapper around `inspect.getsourcelines`.
309 This is essentially a robust wrapper around `inspect.getsourcelines`.
310
310
311 Returns None if no file can be found.
311 Returns None if no file can be found.
312
312
313 Parameters
313 Parameters
314 ----------
314 ----------
315 obj : any Python object
315 obj : any Python object
316
316
317 Returns
317 Returns
318 -------
318 -------
319 lineno : int
319 lineno : int
320 The line number where the object definition starts.
320 The line number where the object definition starts.
321 """
321 """
322 # get source if obj was decorated with @decorator
322 # get source if obj was decorated with @decorator
323 if safe_hasattr(obj, '__wrapped__'):
323 if safe_hasattr(obj, '__wrapped__'):
324 obj = obj.__wrapped__
324 obj = obj.__wrapped__
325
325
326 try:
326 try:
327 try:
327 try:
328 lineno = inspect.getsourcelines(obj)[1]
328 lineno = inspect.getsourcelines(obj)[1]
329 except TypeError:
329 except TypeError:
330 # For instances, try the class object like getsource() does
330 # For instances, try the class object like getsource() does
331 if hasattr(obj, '__class__'):
331 if hasattr(obj, '__class__'):
332 lineno = inspect.getsourcelines(obj.__class__)[1]
332 lineno = inspect.getsourcelines(obj.__class__)[1]
333 else:
333 else:
334 lineno = None
334 lineno = None
335 except:
335 except:
336 return None
336 return None
337
337
338 return lineno
338 return lineno
339
339
340
340
341 class Inspector:
341 class Inspector:
342 def __init__(self, color_table=InspectColors,
342 def __init__(self, color_table=InspectColors,
343 code_color_table=PyColorize.ANSICodeColors,
343 code_color_table=PyColorize.ANSICodeColors,
344 scheme='NoColor',
344 scheme='NoColor',
345 str_detail_level=0):
345 str_detail_level=0):
346 self.color_table = color_table
346 self.color_table = color_table
347 self.parser = PyColorize.Parser(code_color_table,out='str')
347 self.parser = PyColorize.Parser(code_color_table,out='str')
348 self.format = self.parser.format
348 self.format = self.parser.format
349 self.str_detail_level = str_detail_level
349 self.str_detail_level = str_detail_level
350 self.set_active_scheme(scheme)
350 self.set_active_scheme(scheme)
351
351
352 def _getdef(self,obj,oname=''):
352 def _getdef(self,obj,oname=''):
353 """Return the call signature for any callable object.
353 """Return the call signature for any callable object.
354
354
355 If any exception is generated, None is returned instead and the
355 If any exception is generated, None is returned instead and the
356 exception is suppressed."""
356 exception is suppressed."""
357
357
358 try:
358 try:
359 hdef = oname + inspect.formatargspec(*getargspec(obj))
359 hdef = oname + inspect.formatargspec(*getargspec(obj))
360 return cast_unicode(hdef)
360 return cast_unicode(hdef)
361 except:
361 except:
362 return None
362 return None
363
363
364 def __head(self,h):
364 def __head(self,h):
365 """Return a header string with proper colors."""
365 """Return a header string with proper colors."""
366 return '%s%s%s' % (self.color_table.active_colors.header,h,
366 return '%s%s%s' % (self.color_table.active_colors.header,h,
367 self.color_table.active_colors.normal)
367 self.color_table.active_colors.normal)
368
368
369 def set_active_scheme(self, scheme):
369 def set_active_scheme(self, scheme):
370 self.color_table.set_active_scheme(scheme)
370 self.color_table.set_active_scheme(scheme)
371 self.parser.color_table.set_active_scheme(scheme)
371 self.parser.color_table.set_active_scheme(scheme)
372
372
373 def noinfo(self, msg, oname):
373 def noinfo(self, msg, oname):
374 """Generic message when no information is found."""
374 """Generic message when no information is found."""
375 print('No %s found' % msg, end=' ')
375 print('No %s found' % msg, end=' ')
376 if oname:
376 if oname:
377 print('for %s' % oname)
377 print('for %s' % oname)
378 else:
378 else:
379 print()
379 print()
380
380
381 def pdef(self, obj, oname=''):
381 def pdef(self, obj, oname=''):
382 """Print the call signature for any callable object.
382 """Print the call signature for any callable object.
383
383
384 If the object is a class, print the constructor information."""
384 If the object is a class, print the constructor information."""
385
385
386 if not callable(obj):
386 if not callable(obj):
387 print('Object is not callable.')
387 print('Object is not callable.')
388 return
388 return
389
389
390 header = ''
390 header = ''
391
391
392 if inspect.isclass(obj):
392 if inspect.isclass(obj):
393 header = self.__head('Class constructor information:\n')
393 header = self.__head('Class constructor information:\n')
394 obj = obj.__init__
394 obj = obj.__init__
395 elif (not py3compat.PY3) and type(obj) is types.InstanceType:
395 elif (not py3compat.PY3) and type(obj) is types.InstanceType:
396 obj = obj.__call__
396 obj = obj.__call__
397
397
398 output = self._getdef(obj,oname)
398 output = self._getdef(obj,oname)
399 if output is None:
399 if output is None:
400 self.noinfo('definition header',oname)
400 self.noinfo('definition header',oname)
401 else:
401 else:
402 print(header,self.format(output), end=' ', file=io.stdout)
402 print(header,self.format(output), end=' ', file=io.stdout)
403
403
404 # In Python 3, all classes are new-style, so they all have __init__.
404 # In Python 3, all classes are new-style, so they all have __init__.
405 @skip_doctest_py3
405 @skip_doctest_py3
406 def pdoc(self,obj,oname='',formatter = None):
406 def pdoc(self,obj,oname='',formatter = None):
407 """Print the docstring for any object.
407 """Print the docstring for any object.
408
408
409 Optional:
409 Optional:
410 -formatter: a function to run the docstring through for specially
410 -formatter: a function to run the docstring through for specially
411 formatted docstrings.
411 formatted docstrings.
412
412
413 Examples
413 Examples
414 --------
414 --------
415
415
416 In [1]: class NoInit:
416 In [1]: class NoInit:
417 ...: pass
417 ...: pass
418
418
419 In [2]: class NoDoc:
419 In [2]: class NoDoc:
420 ...: def __init__(self):
420 ...: def __init__(self):
421 ...: pass
421 ...: pass
422
422
423 In [3]: %pdoc NoDoc
423 In [3]: %pdoc NoDoc
424 No documentation found for NoDoc
424 No documentation found for NoDoc
425
425
426 In [4]: %pdoc NoInit
426 In [4]: %pdoc NoInit
427 No documentation found for NoInit
427 No documentation found for NoInit
428
428
429 In [5]: obj = NoInit()
429 In [5]: obj = NoInit()
430
430
431 In [6]: %pdoc obj
431 In [6]: %pdoc obj
432 No documentation found for obj
432 No documentation found for obj
433
433
434 In [5]: obj2 = NoDoc()
434 In [5]: obj2 = NoDoc()
435
435
436 In [6]: %pdoc obj2
436 In [6]: %pdoc obj2
437 No documentation found for obj2
437 No documentation found for obj2
438 """
438 """
439
439
440 head = self.__head # For convenience
440 head = self.__head # For convenience
441 lines = []
441 lines = []
442 ds = getdoc(obj)
442 ds = getdoc(obj)
443 if formatter:
443 if formatter:
444 ds = formatter(ds)
444 ds = formatter(ds)
445 if ds:
445 if ds:
446 lines.append(head("Class Docstring:"))
446 lines.append(head("Class Docstring:"))
447 lines.append(indent(ds))
447 lines.append(indent(ds))
448 if inspect.isclass(obj) and hasattr(obj, '__init__'):
448 if inspect.isclass(obj) and hasattr(obj, '__init__'):
449 init_ds = getdoc(obj.__init__)
449 init_ds = getdoc(obj.__init__)
450 if init_ds is not None:
450 if init_ds is not None:
451 lines.append(head("Constructor Docstring:"))
451 lines.append(head("Constructor Docstring:"))
452 lines.append(indent(init_ds))
452 lines.append(indent(init_ds))
453 elif hasattr(obj,'__call__'):
453 elif hasattr(obj,'__call__'):
454 call_ds = getdoc(obj.__call__)
454 call_ds = getdoc(obj.__call__)
455 if call_ds:
455 if call_ds:
456 lines.append(head("Calling Docstring:"))
456 lines.append(head("Calling Docstring:"))
457 lines.append(indent(call_ds))
457 lines.append(indent(call_ds))
458
458
459 if not lines:
459 if not lines:
460 self.noinfo('documentation',oname)
460 self.noinfo('documentation',oname)
461 else:
461 else:
462 page.page('\n'.join(lines))
462 page.page('\n'.join(lines))
463
463
464 def psource(self,obj,oname=''):
464 def psource(self,obj,oname=''):
465 """Print the source code for an object."""
465 """Print the source code for an object."""
466
466
467 # Flush the source cache because inspect can return out-of-date source
467 # Flush the source cache because inspect can return out-of-date source
468 linecache.checkcache()
468 linecache.checkcache()
469 try:
469 try:
470 src = getsource(obj)
470 src = getsource(obj)
471 except:
471 except:
472 self.noinfo('source',oname)
472 self.noinfo('source',oname)
473 else:
473 else:
474 page.page(self.format(src))
474 page.page(self.format(src))
475
475
476 def pfile(self, obj, oname=''):
476 def pfile(self, obj, oname=''):
477 """Show the whole file where an object was defined."""
477 """Show the whole file where an object was defined."""
478
478
479 lineno = find_source_lines(obj)
479 lineno = find_source_lines(obj)
480 if lineno is None:
480 if lineno is None:
481 self.noinfo('file', oname)
481 self.noinfo('file', oname)
482 return
482 return
483
483
484 ofile = find_file(obj)
484 ofile = find_file(obj)
485 # run contents of file through pager starting at line where the object
485 # run contents of file through pager starting at line where the object
486 # is defined, as long as the file isn't binary and is actually on the
486 # is defined, as long as the file isn't binary and is actually on the
487 # filesystem.
487 # filesystem.
488 if ofile.endswith(('.so', '.dll', '.pyd')):
488 if ofile.endswith(('.so', '.dll', '.pyd')):
489 print('File %r is binary, not printing.' % ofile)
489 print('File %r is binary, not printing.' % ofile)
490 elif not os.path.isfile(ofile):
490 elif not os.path.isfile(ofile):
491 print('File %r does not exist, not printing.' % ofile)
491 print('File %r does not exist, not printing.' % ofile)
492 else:
492 else:
493 # Print only text files, not extension binaries. Note that
493 # Print only text files, not extension binaries. Note that
494 # getsourcelines returns lineno with 1-offset and page() uses
494 # getsourcelines returns lineno with 1-offset and page() uses
495 # 0-offset, so we must adjust.
495 # 0-offset, so we must adjust.
496 page.page(self.format(openpy.read_py_file(ofile, skip_encoding_cookie=False)), lineno - 1)
496 page.page(self.format(openpy.read_py_file(ofile, skip_encoding_cookie=False)), lineno - 1)
497
497
498 def _format_fields(self, fields, title_width=12):
498 def _format_fields(self, fields, title_width=12):
499 """Formats a list of fields for display.
499 """Formats a list of fields for display.
500
500
501 Parameters
501 Parameters
502 ----------
502 ----------
503 fields : list
503 fields : list
504 A list of 2-tuples: (field_title, field_content)
504 A list of 2-tuples: (field_title, field_content)
505 title_width : int
505 title_width : int
506 How many characters to pad titles to. Default 12.
506 How many characters to pad titles to. Default 12.
507 """
507 """
508 out = []
508 out = []
509 header = self.__head
509 header = self.__head
510 for title, content in fields:
510 for title, content in fields:
511 if len(content.splitlines()) > 1:
511 if len(content.splitlines()) > 1:
512 title = header(title + ":") + "\n"
512 title = header(title + ":") + "\n"
513 else:
513 else:
514 title = header((title+":").ljust(title_width))
514 title = header((title+":").ljust(title_width))
515 out.append(cast_unicode(title) + cast_unicode(content))
515 out.append(cast_unicode(title) + cast_unicode(content))
516 return "\n".join(out)
516 return "\n".join(out)
517
517
518 # The fields to be displayed by pinfo: (fancy_name, key_in_info_dict)
518 # The fields to be displayed by pinfo: (fancy_name, key_in_info_dict)
519 pinfo_fields1 = [("Type", "type_name"),
519 pinfo_fields1 = [("Type", "type_name"),
520 ]
520 ]
521
521
522 pinfo_fields2 = [("String Form", "string_form"),
522 pinfo_fields2 = [("String Form", "string_form"),
523 ]
523 ]
524
524
525 pinfo_fields3 = [("Length", "length"),
525 pinfo_fields3 = [("Length", "length"),
526 ("File", "file"),
526 ("File", "file"),
527 ("Definition", "definition"),
527 ("Definition", "definition"),
528 ]
528 ]
529
529
530 pinfo_fields_obj = [("Class Docstring", "class_docstring"),
530 pinfo_fields_obj = [("Class Docstring", "class_docstring"),
531 ("Constructor Docstring","init_docstring"),
531 ("Constructor Docstring","init_docstring"),
532 ("Call def", "call_def"),
532 ("Call def", "call_def"),
533 ("Call docstring", "call_docstring")]
533 ("Call docstring", "call_docstring")]
534
534
535 def pinfo(self,obj,oname='',formatter=None,info=None,detail_level=0):
535 def pinfo(self,obj,oname='',formatter=None,info=None,detail_level=0):
536 """Show detailed information about an object.
536 """Show detailed information about an object.
537
537
538 Optional arguments:
538 Optional arguments:
539
539
540 - oname: name of the variable pointing to the object.
540 - oname: name of the variable pointing to the object.
541
541
542 - formatter: special formatter for docstrings (see pdoc)
542 - formatter: special formatter for docstrings (see pdoc)
543
543
544 - info: a structure with some information fields which may have been
544 - info: a structure with some information fields which may have been
545 precomputed already.
545 precomputed already.
546
546
547 - detail_level: if set to 1, more information is given.
547 - detail_level: if set to 1, more information is given.
548 """
548 """
549 info = self.info(obj, oname=oname, formatter=formatter,
549 info = self.info(obj, oname=oname, formatter=formatter,
550 info=info, detail_level=detail_level)
550 info=info, detail_level=detail_level)
551 displayfields = []
551 displayfields = []
552 def add_fields(fields):
552 def add_fields(fields):
553 for title, key in fields:
553 for title, key in fields:
554 field = info[key]
554 field = info[key]
555 if field is not None:
555 if field is not None:
556 displayfields.append((title, field.rstrip()))
556 displayfields.append((title, field.rstrip()))
557
557
558 add_fields(self.pinfo_fields1)
558 add_fields(self.pinfo_fields1)
559
559
560 # Base class for old-style instances
560 # Base class for old-style instances
561 if (not py3compat.PY3) and isinstance(obj, types.InstanceType) and info['base_class']:
561 if (not py3compat.PY3) and isinstance(obj, types.InstanceType) and info['base_class']:
562 displayfields.append(("Base Class", info['base_class'].rstrip()))
562 displayfields.append(("Base Class", info['base_class'].rstrip()))
563
563
564 add_fields(self.pinfo_fields2)
564 add_fields(self.pinfo_fields2)
565
565
566 # Namespace
566 # Namespace
567 if info['namespace'] != 'Interactive':
567 if info['namespace'] != 'Interactive':
568 displayfields.append(("Namespace", info['namespace'].rstrip()))
568 displayfields.append(("Namespace", info['namespace'].rstrip()))
569
569
570 add_fields(self.pinfo_fields3)
570 add_fields(self.pinfo_fields3)
571
571
572 # Source or docstring, depending on detail level and whether
572 # Source or docstring, depending on detail level and whether
573 # source found.
573 # source found.
574 if detail_level > 0 and info['source'] is not None:
574 if detail_level > 0 and info['source'] is not None:
575 displayfields.append(("Source",
575 displayfields.append(("Source",
576 self.format(cast_unicode(info['source']))))
576 self.format(cast_unicode(info['source']))))
577 elif info['docstring'] is not None:
577 elif info['docstring'] is not None:
578 displayfields.append(("Docstring", info["docstring"]))
578 displayfields.append(("Docstring", info["docstring"]))
579
579
580 # Constructor info for classes
580 # Constructor info for classes
581 if info['isclass']:
581 if info['isclass']:
582 if info['init_definition'] or info['init_docstring']:
582 if info['init_definition'] or info['init_docstring']:
583 displayfields.append(("Constructor information", ""))
583 displayfields.append(("Constructor information", ""))
584 if info['init_definition'] is not None:
584 if info['init_definition'] is not None:
585 displayfields.append((" Definition",
585 displayfields.append((" Definition",
586 info['init_definition'].rstrip()))
586 info['init_definition'].rstrip()))
587 if info['init_docstring'] is not None:
587 if info['init_docstring'] is not None:
588 displayfields.append((" Docstring",
588 displayfields.append((" Docstring",
589 indent(info['init_docstring'])))
589 indent(info['init_docstring'])))
590
590
591 # Info for objects:
591 # Info for objects:
592 else:
592 else:
593 add_fields(self.pinfo_fields_obj)
593 add_fields(self.pinfo_fields_obj)
594
594
595 # Finally send to printer/pager:
595 # Finally send to printer/pager:
596 if displayfields:
596 if displayfields:
597 page.page(self._format_fields(displayfields))
597 page.page(self._format_fields(displayfields))
598
598
599 def info(self, obj, oname='', formatter=None, info=None, detail_level=0):
599 def info(self, obj, oname='', formatter=None, info=None, detail_level=0):
600 """Compute a dict with detailed information about an object.
600 """Compute a dict with detailed information about an object.
601
601
602 Optional arguments:
602 Optional arguments:
603
603
604 - oname: name of the variable pointing to the object.
604 - oname: name of the variable pointing to the object.
605
605
606 - formatter: special formatter for docstrings (see pdoc)
606 - formatter: special formatter for docstrings (see pdoc)
607
607
608 - info: a structure with some information fields which may have been
608 - info: a structure with some information fields which may have been
609 precomputed already.
609 precomputed already.
610
610
611 - detail_level: if set to 1, more information is given.
611 - detail_level: if set to 1, more information is given.
612 """
612 """
613
613
614 obj_type = type(obj)
614 obj_type = type(obj)
615
615
616 header = self.__head
616 header = self.__head
617 if info is None:
617 if info is None:
618 ismagic = 0
618 ismagic = 0
619 isalias = 0
619 isalias = 0
620 ospace = ''
620 ospace = ''
621 else:
621 else:
622 ismagic = info.ismagic
622 ismagic = info.ismagic
623 isalias = info.isalias
623 isalias = info.isalias
624 ospace = info.namespace
624 ospace = info.namespace
625
625
626 # Get docstring, special-casing aliases:
626 # Get docstring, special-casing aliases:
627 if isalias:
627 if isalias:
628 if not callable(obj):
628 if not callable(obj):
629 try:
629 try:
630 ds = "Alias to the system command:\n %s" % obj[1]
630 ds = "Alias to the system command:\n %s" % obj[1]
631 except:
631 except:
632 ds = "Alias: " + str(obj)
632 ds = "Alias: " + str(obj)
633 else:
633 else:
634 ds = "Alias to " + str(obj)
634 ds = "Alias to " + str(obj)
635 if obj.__doc__:
635 if obj.__doc__:
636 ds += "\nDocstring:\n" + obj.__doc__
636 ds += "\nDocstring:\n" + obj.__doc__
637 else:
637 else:
638 ds = getdoc(obj)
638 ds = getdoc(obj)
639 if ds is None:
639 if ds is None:
640 ds = '<no docstring>'
640 ds = '<no docstring>'
641 if formatter is not None:
641 if formatter is not None:
642 ds = formatter(ds)
642 ds = formatter(ds)
643
643
644 # store output in a dict, we initialize it here and fill it as we go
644 # store output in a dict, we initialize it here and fill it as we go
645 out = dict(name=oname, found=True, isalias=isalias, ismagic=ismagic)
645 out = dict(name=oname, found=True, isalias=isalias, ismagic=ismagic)
646
646
647 string_max = 200 # max size of strings to show (snipped if longer)
647 string_max = 200 # max size of strings to show (snipped if longer)
648 shalf = int((string_max -5)/2)
648 shalf = int((string_max -5)/2)
649
649
650 if ismagic:
650 if ismagic:
651 obj_type_name = 'Magic function'
651 obj_type_name = 'Magic function'
652 elif isalias:
652 elif isalias:
653 obj_type_name = 'System alias'
653 obj_type_name = 'System alias'
654 else:
654 else:
655 obj_type_name = obj_type.__name__
655 obj_type_name = obj_type.__name__
656 out['type_name'] = obj_type_name
656 out['type_name'] = obj_type_name
657
657
658 try:
658 try:
659 bclass = obj.__class__
659 bclass = obj.__class__
660 out['base_class'] = str(bclass)
660 out['base_class'] = str(bclass)
661 except: pass
661 except: pass
662
662
663 # String form, but snip if too long in ? form (full in ??)
663 # String form, but snip if too long in ? form (full in ??)
664 if detail_level >= self.str_detail_level:
664 if detail_level >= self.str_detail_level:
665 try:
665 try:
666 ostr = str(obj)
666 ostr = str(obj)
667 str_head = 'string_form'
667 str_head = 'string_form'
668 if not detail_level and len(ostr)>string_max:
668 if not detail_level and len(ostr)>string_max:
669 ostr = ostr[:shalf] + ' <...> ' + ostr[-shalf:]
669 ostr = ostr[:shalf] + ' <...> ' + ostr[-shalf:]
670 ostr = ("\n" + " " * len(str_head.expandtabs())).\
670 ostr = ("\n" + " " * len(str_head.expandtabs())).\
671 join(q.strip() for q in ostr.split("\n"))
671 join(q.strip() for q in ostr.split("\n"))
672 out[str_head] = ostr
672 out[str_head] = ostr
673 except:
673 except:
674 pass
674 pass
675
675
676 if ospace:
676 if ospace:
677 out['namespace'] = ospace
677 out['namespace'] = ospace
678
678
679 # Length (for strings and lists)
679 # Length (for strings and lists)
680 try:
680 try:
681 out['length'] = str(len(obj))
681 out['length'] = str(len(obj))
682 except: pass
682 except: pass
683
683
684 # Filename where object was defined
684 # Filename where object was defined
685 binary_file = False
685 binary_file = False
686 fname = find_file(obj)
686 fname = find_file(obj)
687 if fname is None:
687 if fname is None:
688 # if anything goes wrong, we don't want to show source, so it's as
688 # if anything goes wrong, we don't want to show source, so it's as
689 # if the file was binary
689 # if the file was binary
690 binary_file = True
690 binary_file = True
691 else:
691 else:
692 if fname.endswith(('.so', '.dll', '.pyd')):
692 if fname.endswith(('.so', '.dll', '.pyd')):
693 binary_file = True
693 binary_file = True
694 elif fname.endswith('<string>'):
694 elif fname.endswith('<string>'):
695 fname = 'Dynamically generated function. No source code available.'
695 fname = 'Dynamically generated function. No source code available.'
696 out['file'] = fname
696 out['file'] = fname
697
697
698 # reconstruct the function definition and print it:
698 # reconstruct the function definition and print it:
699 defln = self._getdef(obj, oname)
699 defln = self._getdef(obj, oname)
700 if defln:
700 if defln:
701 out['definition'] = self.format(defln)
701 out['definition'] = self.format(defln)
702
702
703 # Docstrings only in detail 0 mode, since source contains them (we
703 # Docstrings only in detail 0 mode, since source contains them (we
704 # avoid repetitions). If source fails, we add them back, see below.
704 # avoid repetitions). If source fails, we add them back, see below.
705 if ds and detail_level == 0:
705 if ds and detail_level == 0:
706 out['docstring'] = ds
706 out['docstring'] = ds
707
707
708 # Original source code for any callable
708 # Original source code for any callable
709 if detail_level:
709 if detail_level:
710 # Flush the source cache because inspect can return out-of-date
710 # Flush the source cache because inspect can return out-of-date
711 # source
711 # source
712 linecache.checkcache()
712 linecache.checkcache()
713 source = None
713 source = None
714 try:
714 try:
715 try:
715 try:
716 source = getsource(obj, binary_file)
716 source = getsource(obj, binary_file)
717 except TypeError:
717 except TypeError:
718 if hasattr(obj, '__class__'):
718 if hasattr(obj, '__class__'):
719 source = getsource(obj.__class__, binary_file)
719 source = getsource(obj.__class__, binary_file)
720 if source is not None:
720 if source is not None:
721 out['source'] = source.rstrip()
721 out['source'] = source.rstrip()
722 except Exception:
722 except Exception:
723 pass
723 pass
724
724
725 if ds and source is None:
725 if ds and source is None:
726 out['docstring'] = ds
726 out['docstring'] = ds
727
727
728
728
729 # Constructor docstring for classes
729 # Constructor docstring for classes
730 if inspect.isclass(obj):
730 if inspect.isclass(obj):
731 out['isclass'] = True
731 out['isclass'] = True
732 # reconstruct the function definition and print it:
732 # reconstruct the function definition and print it:
733 try:
733 try:
734 obj_init = obj.__init__
734 obj_init = obj.__init__
735 except AttributeError:
735 except AttributeError:
736 init_def = init_ds = None
736 init_def = init_ds = None
737 else:
737 else:
738 init_def = self._getdef(obj_init,oname)
738 init_def = self._getdef(obj_init,oname)
739 init_ds = getdoc(obj_init)
739 init_ds = getdoc(obj_init)
740 # Skip Python's auto-generated docstrings
740 # Skip Python's auto-generated docstrings
741 print(init_ds)
742 if init_ds == _object_init_docstring:
741 if init_ds == _object_init_docstring:
743 init_ds = None
742 init_ds = None
744
743
745 if init_def or init_ds:
744 if init_def or init_ds:
746 if init_def:
745 if init_def:
747 out['init_definition'] = self.format(init_def)
746 out['init_definition'] = self.format(init_def)
748 if init_ds:
747 if init_ds:
749 out['init_docstring'] = init_ds
748 out['init_docstring'] = init_ds
750
749
751 # and class docstring for instances:
750 # and class docstring for instances:
752 else:
751 else:
753 # First, check whether the instance docstring is identical to the
752 # First, check whether the instance docstring is identical to the
754 # class one, and print it separately if they don't coincide. In
753 # class one, and print it separately if they don't coincide. In
755 # most cases they will, but it's nice to print all the info for
754 # most cases they will, but it's nice to print all the info for
756 # objects which use instance-customized docstrings.
755 # objects which use instance-customized docstrings.
757 if ds:
756 if ds:
758 try:
757 try:
759 cls = getattr(obj,'__class__')
758 cls = getattr(obj,'__class__')
760 except:
759 except:
761 class_ds = None
760 class_ds = None
762 else:
761 else:
763 class_ds = getdoc(cls)
762 class_ds = getdoc(cls)
764 # Skip Python's auto-generated docstrings
763 # Skip Python's auto-generated docstrings
765 if class_ds in _builtin_type_docstrings:
764 if class_ds in _builtin_type_docstrings:
766 class_ds = None
765 class_ds = None
767 if class_ds and ds != class_ds:
766 if class_ds and ds != class_ds:
768 out['class_docstring'] = class_ds
767 out['class_docstring'] = class_ds
769
768
770 # Next, try to show constructor docstrings
769 # Next, try to show constructor docstrings
771 try:
770 try:
772 init_ds = getdoc(obj.__init__)
771 init_ds = getdoc(obj.__init__)
773 # Skip Python's auto-generated docstrings
772 # Skip Python's auto-generated docstrings
774 if init_ds == _object_init_docstring:
773 if init_ds == _object_init_docstring:
775 init_ds = None
774 init_ds = None
776 except AttributeError:
775 except AttributeError:
777 init_ds = None
776 init_ds = None
778 if init_ds:
777 if init_ds:
779 out['init_docstring'] = init_ds
778 out['init_docstring'] = init_ds
780
779
781 # Call form docstring for callable instances
780 # Call form docstring for callable instances
782 if safe_hasattr(obj, '__call__'):
781 if safe_hasattr(obj, '__call__'):
783 call_def = self._getdef(obj.__call__, oname)
782 call_def = self._getdef(obj.__call__, oname)
784 if call_def is not None:
783 if call_def is not None:
785 out['call_def'] = self.format(call_def)
784 out['call_def'] = self.format(call_def)
786 call_ds = getdoc(obj.__call__)
785 call_ds = getdoc(obj.__call__)
787 # Skip Python's auto-generated docstrings
786 # Skip Python's auto-generated docstrings
788 if call_ds == _func_call_docstring:
787 if call_ds == _func_call_docstring:
789 call_ds = None
788 call_ds = None
790 if call_ds:
789 if call_ds:
791 out['call_docstring'] = call_ds
790 out['call_docstring'] = call_ds
792
791
793 # Compute the object's argspec as a callable. The key is to decide
792 # Compute the object's argspec as a callable. The key is to decide
794 # whether to pull it from the object itself, from its __init__ or
793 # whether to pull it from the object itself, from its __init__ or
795 # from its __call__ method.
794 # from its __call__ method.
796
795
797 if inspect.isclass(obj):
796 if inspect.isclass(obj):
798 # Old-style classes need not have an __init__
797 # Old-style classes need not have an __init__
799 callable_obj = getattr(obj, "__init__", None)
798 callable_obj = getattr(obj, "__init__", None)
800 elif callable(obj):
799 elif callable(obj):
801 callable_obj = obj
800 callable_obj = obj
802 else:
801 else:
803 callable_obj = None
802 callable_obj = None
804
803
805 if callable_obj:
804 if callable_obj:
806 try:
805 try:
807 args, varargs, varkw, defaults = getargspec(callable_obj)
806 args, varargs, varkw, defaults = getargspec(callable_obj)
808 except (TypeError, AttributeError):
807 except (TypeError, AttributeError):
809 # For extensions/builtins we can't retrieve the argspec
808 # For extensions/builtins we can't retrieve the argspec
810 pass
809 pass
811 else:
810 else:
812 out['argspec'] = dict(args=args, varargs=varargs,
811 out['argspec'] = dict(args=args, varargs=varargs,
813 varkw=varkw, defaults=defaults)
812 varkw=varkw, defaults=defaults)
814
813
815 return object_info(**out)
814 return object_info(**out)
816
815
817
816
818 def psearch(self,pattern,ns_table,ns_search=[],
817 def psearch(self,pattern,ns_table,ns_search=[],
819 ignore_case=False,show_all=False):
818 ignore_case=False,show_all=False):
820 """Search namespaces with wildcards for objects.
819 """Search namespaces with wildcards for objects.
821
820
822 Arguments:
821 Arguments:
823
822
824 - pattern: string containing shell-like wildcards to use in namespace
823 - pattern: string containing shell-like wildcards to use in namespace
825 searches and optionally a type specification to narrow the search to
824 searches and optionally a type specification to narrow the search to
826 objects of that type.
825 objects of that type.
827
826
828 - ns_table: dict of name->namespaces for search.
827 - ns_table: dict of name->namespaces for search.
829
828
830 Optional arguments:
829 Optional arguments:
831
830
832 - ns_search: list of namespace names to include in search.
831 - ns_search: list of namespace names to include in search.
833
832
834 - ignore_case(False): make the search case-insensitive.
833 - ignore_case(False): make the search case-insensitive.
835
834
836 - show_all(False): show all names, including those starting with
835 - show_all(False): show all names, including those starting with
837 underscores.
836 underscores.
838 """
837 """
839 #print 'ps pattern:<%r>' % pattern # dbg
838 #print 'ps pattern:<%r>' % pattern # dbg
840
839
841 # defaults
840 # defaults
842 type_pattern = 'all'
841 type_pattern = 'all'
843 filter = ''
842 filter = ''
844
843
845 cmds = pattern.split()
844 cmds = pattern.split()
846 len_cmds = len(cmds)
845 len_cmds = len(cmds)
847 if len_cmds == 1:
846 if len_cmds == 1:
848 # Only filter pattern given
847 # Only filter pattern given
849 filter = cmds[0]
848 filter = cmds[0]
850 elif len_cmds == 2:
849 elif len_cmds == 2:
851 # Both filter and type specified
850 # Both filter and type specified
852 filter,type_pattern = cmds
851 filter,type_pattern = cmds
853 else:
852 else:
854 raise ValueError('invalid argument string for psearch: <%s>' %
853 raise ValueError('invalid argument string for psearch: <%s>' %
855 pattern)
854 pattern)
856
855
857 # filter search namespaces
856 # filter search namespaces
858 for name in ns_search:
857 for name in ns_search:
859 if name not in ns_table:
858 if name not in ns_table:
860 raise ValueError('invalid namespace <%s>. Valid names: %s' %
859 raise ValueError('invalid namespace <%s>. Valid names: %s' %
861 (name,ns_table.keys()))
860 (name,ns_table.keys()))
862
861
863 #print 'type_pattern:',type_pattern # dbg
862 #print 'type_pattern:',type_pattern # dbg
864 search_result, namespaces_seen = set(), set()
863 search_result, namespaces_seen = set(), set()
865 for ns_name in ns_search:
864 for ns_name in ns_search:
866 ns = ns_table[ns_name]
865 ns = ns_table[ns_name]
867 # Normally, locals and globals are the same, so we just check one.
866 # Normally, locals and globals are the same, so we just check one.
868 if id(ns) in namespaces_seen:
867 if id(ns) in namespaces_seen:
869 continue
868 continue
870 namespaces_seen.add(id(ns))
869 namespaces_seen.add(id(ns))
871 tmp_res = list_namespace(ns, type_pattern, filter,
870 tmp_res = list_namespace(ns, type_pattern, filter,
872 ignore_case=ignore_case, show_all=show_all)
871 ignore_case=ignore_case, show_all=show_all)
873 search_result.update(tmp_res)
872 search_result.update(tmp_res)
874
873
875 page.page('\n'.join(sorted(search_result)))
874 page.page('\n'.join(sorted(search_result)))
General Comments 0
You need to be logged in to leave comments. Login now