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