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