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