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