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