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