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