##// END OF EJS Templates
'Call def' -> 'Call signature'
Thomas Kluyver -
Show More
@@ -1,924 +1,924 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 add_fields([("Docstring", "docstring"),
575 ("File", "file")
575 ("File", "file")
576 ])
576 ])
577
577
578 elif info['isclass'] or is_simple_callable(obj):
578 elif info['isclass'] or is_simple_callable(obj):
579 # Functions, methods, classes
579 # Functions, methods, classes
580 add_fields([("Signature", "definition"),
580 add_fields([("Signature", "definition"),
581 ("Init signature", "init_definition"),
581 ("Init signature", "init_definition"),
582 ])
582 ])
583 if detail_level > 0 and info['source'] is not None:
583 if detail_level > 0 and info['source'] is not None:
584 add_fields([("Source", "source")])
584 add_fields([("Source", "source")])
585 else:
585 else:
586 add_fields([("Docstring", "docstring"),
586 add_fields([("Docstring", "docstring"),
587 ("Init docstring", "init_docstring"),
587 ("Init docstring", "init_docstring"),
588 ])
588 ])
589
589
590 add_fields([('File', 'file'),
590 add_fields([('File', 'file'),
591 ('Type', 'type_name'),
591 ('Type', 'type_name'),
592 ])
592 ])
593
593
594 else:
594 else:
595 # General Python objects
595 # General Python objects
596 add_fields([("Type", "type_name")])
596 add_fields([("Type", "type_name")])
597
597
598 # Base class for old-style instances
598 # Base class for old-style instances
599 if (not py3compat.PY3) and isinstance(obj, types.InstanceType) and info['base_class']:
599 if (not py3compat.PY3) and isinstance(obj, types.InstanceType) and info['base_class']:
600 displayfields.append(("Base Class", info['base_class'].rstrip()))
600 displayfields.append(("Base Class", info['base_class'].rstrip()))
601
601
602 add_fields([("String form", "string_form")])
602 add_fields([("String form", "string_form")])
603
603
604 # Namespace
604 # Namespace
605 if info['namespace'] != 'Interactive':
605 if info['namespace'] != 'Interactive':
606 displayfields.append(("Namespace", info['namespace'].rstrip()))
606 displayfields.append(("Namespace", info['namespace'].rstrip()))
607
607
608 add_fields([("Length", "length"),
608 add_fields([("Length", "length"),
609 ("File", "file"),
609 ("File", "file"),
610 ("Definition", "definition"),
610 ("Definition", "definition"),
611 ])
611 ])
612
612
613 # Source or docstring, depending on detail level and whether
613 # Source or docstring, depending on detail level and whether
614 # source found.
614 # source found.
615 if detail_level > 0 and info['source'] is not None:
615 if detail_level > 0 and info['source'] is not None:
616 displayfields.append(("Source",
616 displayfields.append(("Source",
617 self.format(cast_unicode(info['source']))))
617 self.format(cast_unicode(info['source']))))
618 elif info['docstring'] is not None:
618 elif info['docstring'] is not None:
619 displayfields.append(("Docstring", info["docstring"]))
619 displayfields.append(("Docstring", info["docstring"]))
620
620
621 add_fields([("Class docstring", "class_docstring"),
621 add_fields([("Class docstring", "class_docstring"),
622 ("Init docstring", "init_docstring"),
622 ("Init docstring", "init_docstring"),
623 ("Call def", "call_def"),
623 ("Call signature", "call_def"),
624 ("Call docstring", "call_docstring")])
624 ("Call docstring", "call_docstring")])
625
625
626 if displayfields:
626 if displayfields:
627 return self._format_fields(displayfields)
627 return self._format_fields(displayfields)
628 else:
628 else:
629 return u''
629 return u''
630
630
631 def pinfo(self, obj, oname='', formatter=None, info=None, detail_level=0):
631 def pinfo(self, obj, oname='', formatter=None, info=None, detail_level=0):
632 """Show detailed information about an object.
632 """Show detailed information about an object.
633
633
634 Optional arguments:
634 Optional arguments:
635
635
636 - oname: name of the variable pointing to the object.
636 - oname: name of the variable pointing to the object.
637
637
638 - formatter: special formatter for docstrings (see pdoc)
638 - formatter: special formatter for docstrings (see pdoc)
639
639
640 - info: a structure with some information fields which may have been
640 - info: a structure with some information fields which may have been
641 precomputed already.
641 precomputed already.
642
642
643 - detail_level: if set to 1, more information is given.
643 - detail_level: if set to 1, more information is given.
644 """
644 """
645 text = self._format_info(obj, oname, formatter, info, detail_level)
645 text = self._format_info(obj, oname, formatter, info, detail_level)
646 if text:
646 if text:
647 page.page(text)
647 page.page(text)
648
648
649 def info(self, obj, oname='', formatter=None, info=None, detail_level=0):
649 def info(self, obj, oname='', formatter=None, info=None, detail_level=0):
650 """Compute a dict with detailed information about an object.
650 """Compute a dict with detailed information about an object.
651
651
652 Optional arguments:
652 Optional arguments:
653
653
654 - oname: name of the variable pointing to the object.
654 - oname: name of the variable pointing to the object.
655
655
656 - formatter: special formatter for docstrings (see pdoc)
656 - formatter: special formatter for docstrings (see pdoc)
657
657
658 - info: a structure with some information fields which may have been
658 - info: a structure with some information fields which may have been
659 precomputed already.
659 precomputed already.
660
660
661 - detail_level: if set to 1, more information is given.
661 - detail_level: if set to 1, more information is given.
662 """
662 """
663
663
664 obj_type = type(obj)
664 obj_type = type(obj)
665
665
666 if info is None:
666 if info is None:
667 ismagic = 0
667 ismagic = 0
668 isalias = 0
668 isalias = 0
669 ospace = ''
669 ospace = ''
670 else:
670 else:
671 ismagic = info.ismagic
671 ismagic = info.ismagic
672 isalias = info.isalias
672 isalias = info.isalias
673 ospace = info.namespace
673 ospace = info.namespace
674
674
675 # Get docstring, special-casing aliases:
675 # Get docstring, special-casing aliases:
676 if isalias:
676 if isalias:
677 if not callable(obj):
677 if not callable(obj):
678 try:
678 try:
679 ds = "Alias to the system command:\n %s" % obj[1]
679 ds = "Alias to the system command:\n %s" % obj[1]
680 except:
680 except:
681 ds = "Alias: " + str(obj)
681 ds = "Alias: " + str(obj)
682 else:
682 else:
683 ds = "Alias to " + str(obj)
683 ds = "Alias to " + str(obj)
684 if obj.__doc__:
684 if obj.__doc__:
685 ds += "\nDocstring:\n" + obj.__doc__
685 ds += "\nDocstring:\n" + obj.__doc__
686 else:
686 else:
687 ds = getdoc(obj)
687 ds = getdoc(obj)
688 if ds is None:
688 if ds is None:
689 ds = '<no docstring>'
689 ds = '<no docstring>'
690 if formatter is not None:
690 if formatter is not None:
691 ds = formatter(ds)
691 ds = formatter(ds)
692
692
693 # store output in a dict, we initialize it here and fill it as we go
693 # 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)
694 out = dict(name=oname, found=True, isalias=isalias, ismagic=ismagic)
695
695
696 string_max = 200 # max size of strings to show (snipped if longer)
696 string_max = 200 # max size of strings to show (snipped if longer)
697 shalf = int((string_max -5)/2)
697 shalf = int((string_max -5)/2)
698
698
699 if ismagic:
699 if ismagic:
700 obj_type_name = 'Magic function'
700 obj_type_name = 'Magic function'
701 elif isalias:
701 elif isalias:
702 obj_type_name = 'System alias'
702 obj_type_name = 'System alias'
703 else:
703 else:
704 obj_type_name = obj_type.__name__
704 obj_type_name = obj_type.__name__
705 out['type_name'] = obj_type_name
705 out['type_name'] = obj_type_name
706
706
707 try:
707 try:
708 bclass = obj.__class__
708 bclass = obj.__class__
709 out['base_class'] = str(bclass)
709 out['base_class'] = str(bclass)
710 except: pass
710 except: pass
711
711
712 # String form, but snip if too long in ? form (full in ??)
712 # String form, but snip if too long in ? form (full in ??)
713 if detail_level >= self.str_detail_level:
713 if detail_level >= self.str_detail_level:
714 try:
714 try:
715 ostr = str(obj)
715 ostr = str(obj)
716 str_head = 'string_form'
716 str_head = 'string_form'
717 if not detail_level and len(ostr)>string_max:
717 if not detail_level and len(ostr)>string_max:
718 ostr = ostr[:shalf] + ' <...> ' + ostr[-shalf:]
718 ostr = ostr[:shalf] + ' <...> ' + ostr[-shalf:]
719 ostr = ("\n" + " " * len(str_head.expandtabs())).\
719 ostr = ("\n" + " " * len(str_head.expandtabs())).\
720 join(q.strip() for q in ostr.split("\n"))
720 join(q.strip() for q in ostr.split("\n"))
721 out[str_head] = ostr
721 out[str_head] = ostr
722 except:
722 except:
723 pass
723 pass
724
724
725 if ospace:
725 if ospace:
726 out['namespace'] = ospace
726 out['namespace'] = ospace
727
727
728 # Length (for strings and lists)
728 # Length (for strings and lists)
729 try:
729 try:
730 out['length'] = str(len(obj))
730 out['length'] = str(len(obj))
731 except: pass
731 except: pass
732
732
733 # Filename where object was defined
733 # Filename where object was defined
734 binary_file = False
734 binary_file = False
735 fname = find_file(obj)
735 fname = find_file(obj)
736 if fname is None:
736 if fname is None:
737 # if anything goes wrong, we don't want to show source, so it's as
737 # if anything goes wrong, we don't want to show source, so it's as
738 # if the file was binary
738 # if the file was binary
739 binary_file = True
739 binary_file = True
740 else:
740 else:
741 if fname.endswith(('.so', '.dll', '.pyd')):
741 if fname.endswith(('.so', '.dll', '.pyd')):
742 binary_file = True
742 binary_file = True
743 elif fname.endswith('<string>'):
743 elif fname.endswith('<string>'):
744 fname = 'Dynamically generated function. No source code available.'
744 fname = 'Dynamically generated function. No source code available.'
745 out['file'] = compress_user(fname)
745 out['file'] = compress_user(fname)
746
746
747 # Original source code for a callable, class or property.
747 # Original source code for a callable, class or property.
748 if detail_level:
748 if detail_level:
749 # Flush the source cache because inspect can return out-of-date
749 # Flush the source cache because inspect can return out-of-date
750 # source
750 # source
751 linecache.checkcache()
751 linecache.checkcache()
752 try:
752 try:
753 if isinstance(obj, property) or not binary_file:
753 if isinstance(obj, property) or not binary_file:
754 src = getsource(obj, oname)
754 src = getsource(obj, oname)
755 if src is not None:
755 if src is not None:
756 src = src.rstrip()
756 src = src.rstrip()
757 out['source'] = src
757 out['source'] = src
758
758
759 except Exception:
759 except Exception:
760 pass
760 pass
761
761
762 # Add docstring only if no source is to be shown (avoid repetitions).
762 # Add docstring only if no source is to be shown (avoid repetitions).
763 if ds and out.get('source', None) is None:
763 if ds and out.get('source', None) is None:
764 out['docstring'] = ds
764 out['docstring'] = ds
765
765
766 # Constructor docstring for classes
766 # Constructor docstring for classes
767 if inspect.isclass(obj):
767 if inspect.isclass(obj):
768 out['isclass'] = True
768 out['isclass'] = True
769 # reconstruct the function definition and print it:
769 # reconstruct the function definition and print it:
770 try:
770 try:
771 obj_init = obj.__init__
771 obj_init = obj.__init__
772 except AttributeError:
772 except AttributeError:
773 init_def = init_ds = None
773 init_def = init_ds = None
774 else:
774 else:
775 init_def = self._getdef(obj_init,oname)
775 init_def = self._getdef(obj_init,oname)
776 init_ds = getdoc(obj_init)
776 init_ds = getdoc(obj_init)
777 # Skip Python's auto-generated docstrings
777 # Skip Python's auto-generated docstrings
778 if init_ds == _object_init_docstring:
778 if init_ds == _object_init_docstring:
779 init_ds = None
779 init_ds = None
780
780
781 if init_def or init_ds:
781 if init_def or init_ds:
782 if init_def:
782 if init_def:
783 out['init_definition'] = self.format(init_def)
783 out['init_definition'] = self.format(init_def)
784 if init_ds:
784 if init_ds:
785 out['init_docstring'] = init_ds
785 out['init_docstring'] = init_ds
786
786
787 # and class docstring for instances:
787 # and class docstring for instances:
788 else:
788 else:
789 # reconstruct the function definition and print it:
789 # reconstruct the function definition and print it:
790 defln = self._getdef(obj, oname)
790 defln = self._getdef(obj, oname)
791 if defln:
791 if defln:
792 out['definition'] = self.format(defln)
792 out['definition'] = self.format(defln)
793
793
794 # First, check whether the instance docstring is identical to the
794 # First, check whether the instance docstring is identical to the
795 # class one, and print it separately if they don't coincide. In
795 # 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
796 # most cases they will, but it's nice to print all the info for
797 # objects which use instance-customized docstrings.
797 # objects which use instance-customized docstrings.
798 if ds:
798 if ds:
799 try:
799 try:
800 cls = getattr(obj,'__class__')
800 cls = getattr(obj,'__class__')
801 except:
801 except:
802 class_ds = None
802 class_ds = None
803 else:
803 else:
804 class_ds = getdoc(cls)
804 class_ds = getdoc(cls)
805 # Skip Python's auto-generated docstrings
805 # Skip Python's auto-generated docstrings
806 if class_ds in _builtin_type_docstrings:
806 if class_ds in _builtin_type_docstrings:
807 class_ds = None
807 class_ds = None
808 if class_ds and ds != class_ds:
808 if class_ds and ds != class_ds:
809 out['class_docstring'] = class_ds
809 out['class_docstring'] = class_ds
810
810
811 # Next, try to show constructor docstrings
811 # Next, try to show constructor docstrings
812 try:
812 try:
813 init_ds = getdoc(obj.__init__)
813 init_ds = getdoc(obj.__init__)
814 # Skip Python's auto-generated docstrings
814 # Skip Python's auto-generated docstrings
815 if init_ds == _object_init_docstring:
815 if init_ds == _object_init_docstring:
816 init_ds = None
816 init_ds = None
817 except AttributeError:
817 except AttributeError:
818 init_ds = None
818 init_ds = None
819 if init_ds:
819 if init_ds:
820 out['init_docstring'] = init_ds
820 out['init_docstring'] = init_ds
821
821
822 # Call form docstring for callable instances
822 # Call form docstring for callable instances
823 if safe_hasattr(obj, '__call__') and not is_simple_callable(obj):
823 if safe_hasattr(obj, '__call__') and not is_simple_callable(obj):
824 call_def = self._getdef(obj.__call__, oname)
824 call_def = self._getdef(obj.__call__, oname)
825 if call_def:
825 if call_def:
826 call_def = self.format(call_def)
826 call_def = self.format(call_def)
827 # it may never be the case that call def and definition differ,
827 # it may never be the case that call def and definition differ,
828 # but don't include the same signature twice
828 # but don't include the same signature twice
829 if call_def != out.get('definition'):
829 if call_def != out.get('definition'):
830 out['call_def'] = call_def
830 out['call_def'] = call_def
831 call_ds = getdoc(obj.__call__)
831 call_ds = getdoc(obj.__call__)
832 # Skip Python's auto-generated docstrings
832 # Skip Python's auto-generated docstrings
833 if call_ds == _func_call_docstring:
833 if call_ds == _func_call_docstring:
834 call_ds = None
834 call_ds = None
835 if call_ds:
835 if call_ds:
836 out['call_docstring'] = call_ds
836 out['call_docstring'] = call_ds
837
837
838 # Compute the object's argspec as a callable. The key is to decide
838 # 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
839 # whether to pull it from the object itself, from its __init__ or
840 # from its __call__ method.
840 # from its __call__ method.
841
841
842 if inspect.isclass(obj):
842 if inspect.isclass(obj):
843 # Old-style classes need not have an __init__
843 # Old-style classes need not have an __init__
844 callable_obj = getattr(obj, "__init__", None)
844 callable_obj = getattr(obj, "__init__", None)
845 elif callable(obj):
845 elif callable(obj):
846 callable_obj = obj
846 callable_obj = obj
847 else:
847 else:
848 callable_obj = None
848 callable_obj = None
849
849
850 if callable_obj:
850 if callable_obj:
851 try:
851 try:
852 argspec = getargspec(callable_obj)
852 argspec = getargspec(callable_obj)
853 except (TypeError, AttributeError):
853 except (TypeError, AttributeError):
854 # For extensions/builtins we can't retrieve the argspec
854 # For extensions/builtins we can't retrieve the argspec
855 pass
855 pass
856 else:
856 else:
857 # named tuples' _asdict() method returns an OrderedDict, but we
857 # named tuples' _asdict() method returns an OrderedDict, but we
858 # we want a normal
858 # we want a normal
859 out['argspec'] = argspec_dict = dict(argspec._asdict())
859 out['argspec'] = argspec_dict = dict(argspec._asdict())
860 # We called this varkw before argspec became a named tuple.
860 # We called this varkw before argspec became a named tuple.
861 # With getfullargspec it's also called varkw.
861 # With getfullargspec it's also called varkw.
862 if 'varkw' not in argspec_dict:
862 if 'varkw' not in argspec_dict:
863 argspec_dict['varkw'] = argspec_dict.pop('keywords')
863 argspec_dict['varkw'] = argspec_dict.pop('keywords')
864
864
865 return object_info(**out)
865 return object_info(**out)
866
866
867 def psearch(self,pattern,ns_table,ns_search=[],
867 def psearch(self,pattern,ns_table,ns_search=[],
868 ignore_case=False,show_all=False):
868 ignore_case=False,show_all=False):
869 """Search namespaces with wildcards for objects.
869 """Search namespaces with wildcards for objects.
870
870
871 Arguments:
871 Arguments:
872
872
873 - pattern: string containing shell-like wildcards to use in namespace
873 - pattern: string containing shell-like wildcards to use in namespace
874 searches and optionally a type specification to narrow the search to
874 searches and optionally a type specification to narrow the search to
875 objects of that type.
875 objects of that type.
876
876
877 - ns_table: dict of name->namespaces for search.
877 - ns_table: dict of name->namespaces for search.
878
878
879 Optional arguments:
879 Optional arguments:
880
880
881 - ns_search: list of namespace names to include in search.
881 - ns_search: list of namespace names to include in search.
882
882
883 - ignore_case(False): make the search case-insensitive.
883 - ignore_case(False): make the search case-insensitive.
884
884
885 - show_all(False): show all names, including those starting with
885 - show_all(False): show all names, including those starting with
886 underscores.
886 underscores.
887 """
887 """
888 #print 'ps pattern:<%r>' % pattern # dbg
888 #print 'ps pattern:<%r>' % pattern # dbg
889
889
890 # defaults
890 # defaults
891 type_pattern = 'all'
891 type_pattern = 'all'
892 filter = ''
892 filter = ''
893
893
894 cmds = pattern.split()
894 cmds = pattern.split()
895 len_cmds = len(cmds)
895 len_cmds = len(cmds)
896 if len_cmds == 1:
896 if len_cmds == 1:
897 # Only filter pattern given
897 # Only filter pattern given
898 filter = cmds[0]
898 filter = cmds[0]
899 elif len_cmds == 2:
899 elif len_cmds == 2:
900 # Both filter and type specified
900 # Both filter and type specified
901 filter,type_pattern = cmds
901 filter,type_pattern = cmds
902 else:
902 else:
903 raise ValueError('invalid argument string for psearch: <%s>' %
903 raise ValueError('invalid argument string for psearch: <%s>' %
904 pattern)
904 pattern)
905
905
906 # filter search namespaces
906 # filter search namespaces
907 for name in ns_search:
907 for name in ns_search:
908 if name not in ns_table:
908 if name not in ns_table:
909 raise ValueError('invalid namespace <%s>. Valid names: %s' %
909 raise ValueError('invalid namespace <%s>. Valid names: %s' %
910 (name,ns_table.keys()))
910 (name,ns_table.keys()))
911
911
912 #print 'type_pattern:',type_pattern # dbg
912 #print 'type_pattern:',type_pattern # dbg
913 search_result, namespaces_seen = set(), set()
913 search_result, namespaces_seen = set(), set()
914 for ns_name in ns_search:
914 for ns_name in ns_search:
915 ns = ns_table[ns_name]
915 ns = ns_table[ns_name]
916 # Normally, locals and globals are the same, so we just check one.
916 # Normally, locals and globals are the same, so we just check one.
917 if id(ns) in namespaces_seen:
917 if id(ns) in namespaces_seen:
918 continue
918 continue
919 namespaces_seen.add(id(ns))
919 namespaces_seen.add(id(ns))
920 tmp_res = list_namespace(ns, type_pattern, filter,
920 tmp_res = list_namespace(ns, type_pattern, filter,
921 ignore_case=ignore_case, show_all=show_all)
921 ignore_case=ignore_case, show_all=show_all)
922 search_result.update(tmp_res)
922 search_result.update(tmp_res)
923
923
924 page.page('\n'.join(sorted(search_result)))
924 page.page('\n'.join(sorted(search_result)))
General Comments 0
You need to be logged in to leave comments. Login now