##// END OF EJS Templates
add object_inspect_text...
MinRK -
Show More

The requested changes are too big and content was truncated. Show full diff

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