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