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