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