##// END OF EJS Templates
Update signature presentation in pinfo classes...
MinRK -
Show More
@@ -1,877 +1,882 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 #*****************************************************************************
10 #*****************************************************************************
11 # Copyright (C) 2001-2004 Fernando Perez <fperez@colorado.edu>
11 # Copyright (C) 2001-2004 Fernando Perez <fperez@colorado.edu>
12 #
12 #
13 # Distributed under the terms of the BSD License. The full license is in
13 # Distributed under the terms of the BSD License. The full license is in
14 # the file COPYING, distributed as part of this software.
14 # the file COPYING, distributed as part of this software.
15 #*****************************************************************************
15 #*****************************************************************************
16 from __future__ import print_function
16 from __future__ import print_function
17
17
18 __all__ = ['Inspector','InspectColors']
18 __all__ = ['Inspector','InspectColors']
19
19
20 # stdlib modules
20 # stdlib modules
21 import inspect
21 import inspect
22 import linecache
22 import linecache
23 import os
23 import os
24 import types
24 import types
25 import io as stdlib_io
25 import io as stdlib_io
26
26
27 try:
27 try:
28 from itertools import izip_longest
28 from itertools import izip_longest
29 except ImportError:
29 except ImportError:
30 from itertools import zip_longest as izip_longest
30 from itertools import zip_longest as izip_longest
31
31
32 # IPython's own
32 # IPython's own
33 from IPython.core import page
33 from IPython.core import page
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 io
36 from IPython.utils import io
37 from IPython.utils import openpy
37 from IPython.utils import openpy
38 from IPython.utils import py3compat
38 from IPython.utils import py3compat
39 from IPython.utils.dir2 import safe_hasattr
39 from IPython.utils.dir2 import safe_hasattr
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
44
45 # builtin docstrings to ignore
45 # builtin docstrings to ignore
46 _func_call_docstring = types.FunctionType.__call__.__doc__
46 _func_call_docstring = types.FunctionType.__call__.__doc__
47 _object_init_docstring = object.__init__.__doc__
47 _object_init_docstring = object.__init__.__doc__
48 _builtin_type_docstrings = {
48 _builtin_type_docstrings = {
49 t.__doc__ for t in (types.ModuleType, types.MethodType, types.FunctionType)
49 t.__doc__ for t in (types.ModuleType, types.MethodType, types.FunctionType)
50 }
50 }
51
51
52 _builtin_func_type = type(all)
52 _builtin_func_type = type(all)
53 _builtin_meth_type = type(str.upper) # Bound methods have the same type as builtin functions
53 _builtin_meth_type = type(str.upper) # Bound methods have the same type as builtin functions
54 #****************************************************************************
54 #****************************************************************************
55 # Builtin color schemes
55 # Builtin color schemes
56
56
57 Colors = TermColors # just a shorthand
57 Colors = TermColors # just a shorthand
58
58
59 # Build a few color schemes
59 # Build a few color schemes
60 NoColor = ColorScheme(
60 NoColor = ColorScheme(
61 'NoColor',{
61 'NoColor',{
62 'header' : Colors.NoColor,
62 'header' : Colors.NoColor,
63 'normal' : Colors.NoColor # color off (usu. Colors.Normal)
63 'normal' : Colors.NoColor # color off (usu. Colors.Normal)
64 } )
64 } )
65
65
66 LinuxColors = ColorScheme(
66 LinuxColors = ColorScheme(
67 'Linux',{
67 'Linux',{
68 'header' : Colors.LightRed,
68 'header' : Colors.LightRed,
69 'normal' : Colors.Normal # color off (usu. Colors.Normal)
69 'normal' : Colors.Normal # color off (usu. Colors.Normal)
70 } )
70 } )
71
71
72 LightBGColors = ColorScheme(
72 LightBGColors = ColorScheme(
73 'LightBG',{
73 'LightBG',{
74 'header' : Colors.Red,
74 'header' : Colors.Red,
75 'normal' : Colors.Normal # color off (usu. Colors.Normal)
75 'normal' : Colors.Normal # color off (usu. Colors.Normal)
76 } )
76 } )
77
77
78 # Build table of color schemes (needed by the parser)
78 # Build table of color schemes (needed by the parser)
79 InspectColors = ColorSchemeTable([NoColor,LinuxColors,LightBGColors],
79 InspectColors = ColorSchemeTable([NoColor,LinuxColors,LightBGColors],
80 'Linux')
80 'Linux')
81
81
82 #****************************************************************************
82 #****************************************************************************
83 # Auxiliary functions and objects
83 # Auxiliary functions and objects
84
84
85 # See the messaging spec for the definition of all these fields. This list
85 # See the messaging spec for the definition of all these fields. This list
86 # effectively defines the order of display
86 # effectively defines the order of display
87 info_fields = ['type_name', 'base_class', 'string_form', 'namespace',
87 info_fields = ['type_name', 'base_class', 'string_form', 'namespace',
88 'length', 'file', 'definition', 'docstring', 'source',
88 'length', 'file', 'definition', 'docstring', 'source',
89 'init_definition', 'class_docstring', 'init_docstring',
89 'init_definition', 'class_docstring', 'init_docstring',
90 'call_def', 'call_docstring',
90 'call_def', 'call_docstring',
91 # These won't be printed but will be used to determine how to
91 # These won't be printed but will be used to determine how to
92 # format the object
92 # format the object
93 'ismagic', 'isalias', 'isclass', 'argspec', 'found', 'name'
93 'ismagic', 'isalias', 'isclass', 'argspec', 'found', 'name'
94 ]
94 ]
95
95
96
96
97 def object_info(**kw):
97 def object_info(**kw):
98 """Make an object info dict with all fields present."""
98 """Make an object info dict with all fields present."""
99 infodict = dict(izip_longest(info_fields, [None]))
99 infodict = dict(izip_longest(info_fields, [None]))
100 infodict.update(kw)
100 infodict.update(kw)
101 return infodict
101 return infodict
102
102
103
103
104 def get_encoding(obj):
104 def get_encoding(obj):
105 """Get encoding for python source file defining obj
105 """Get encoding for python source file defining obj
106
106
107 Returns None if obj is not defined in a sourcefile.
107 Returns None if obj is not defined in a sourcefile.
108 """
108 """
109 ofile = find_file(obj)
109 ofile = find_file(obj)
110 # run contents of file through pager starting at line where the object
110 # run contents of file through pager starting at line where the object
111 # is defined, as long as the file isn't binary and is actually on the
111 # is defined, as long as the file isn't binary and is actually on the
112 # filesystem.
112 # filesystem.
113 if ofile is None:
113 if ofile is None:
114 return None
114 return None
115 elif ofile.endswith(('.so', '.dll', '.pyd')):
115 elif ofile.endswith(('.so', '.dll', '.pyd')):
116 return None
116 return None
117 elif not os.path.isfile(ofile):
117 elif not os.path.isfile(ofile):
118 return None
118 return None
119 else:
119 else:
120 # Print only text files, not extension binaries. Note that
120 # Print only text files, not extension binaries. Note that
121 # getsourcelines returns lineno with 1-offset and page() uses
121 # getsourcelines returns lineno with 1-offset and page() uses
122 # 0-offset, so we must adjust.
122 # 0-offset, so we must adjust.
123 with stdlib_io.open(ofile, 'rb') as buffer: # Tweaked to use io.open for Python 2
123 with stdlib_io.open(ofile, 'rb') as buffer: # Tweaked to use io.open for Python 2
124 encoding, lines = openpy.detect_encoding(buffer.readline)
124 encoding, lines = openpy.detect_encoding(buffer.readline)
125 return encoding
125 return encoding
126
126
127 def getdoc(obj):
127 def getdoc(obj):
128 """Stable wrapper around inspect.getdoc.
128 """Stable wrapper around inspect.getdoc.
129
129
130 This can't crash because of attribute problems.
130 This can't crash because of attribute problems.
131
131
132 It also attempts to call a getdoc() method on the given object. This
132 It also attempts to call a getdoc() method on the given object. This
133 allows objects which provide their docstrings via non-standard mechanisms
133 allows objects which provide their docstrings via non-standard mechanisms
134 (like Pyro proxies) to still be inspected by ipython's ? system."""
134 (like Pyro proxies) to still be inspected by ipython's ? system."""
135 # Allow objects to offer customized documentation via a getdoc method:
135 # Allow objects to offer customized documentation via a getdoc method:
136 try:
136 try:
137 ds = obj.getdoc()
137 ds = obj.getdoc()
138 except Exception:
138 except Exception:
139 pass
139 pass
140 else:
140 else:
141 # if we get extra info, we add it to the normal docstring.
141 # if we get extra info, we add it to the normal docstring.
142 if isinstance(ds, string_types):
142 if isinstance(ds, string_types):
143 return inspect.cleandoc(ds)
143 return inspect.cleandoc(ds)
144
144
145 try:
145 try:
146 docstr = inspect.getdoc(obj)
146 docstr = inspect.getdoc(obj)
147 encoding = get_encoding(obj)
147 encoding = get_encoding(obj)
148 return py3compat.cast_unicode(docstr, encoding=encoding)
148 return py3compat.cast_unicode(docstr, encoding=encoding)
149 except Exception:
149 except Exception:
150 # Harden against an inspect failure, which can occur with
150 # Harden against an inspect failure, which can occur with
151 # SWIG-wrapped extensions.
151 # SWIG-wrapped extensions.
152 raise
152 raise
153 return None
153 return None
154
154
155
155
156 def getsource(obj,is_binary=False):
156 def getsource(obj,is_binary=False):
157 """Wrapper around inspect.getsource.
157 """Wrapper around inspect.getsource.
158
158
159 This can be modified by other projects to provide customized source
159 This can be modified by other projects to provide customized source
160 extraction.
160 extraction.
161
161
162 Inputs:
162 Inputs:
163
163
164 - obj: an object whose source code we will attempt to extract.
164 - obj: an object whose source code we will attempt to extract.
165
165
166 Optional inputs:
166 Optional inputs:
167
167
168 - is_binary: whether the object is known to come from a binary source.
168 - is_binary: whether the object is known to come from a binary source.
169 This implementation will skip returning any output for binary objects, but
169 This implementation will skip returning any output for binary objects, but
170 custom extractors may know how to meaningfully process them."""
170 custom extractors may know how to meaningfully process them."""
171
171
172 if is_binary:
172 if is_binary:
173 return None
173 return None
174 else:
174 else:
175 # get source if obj was decorated with @decorator
175 # get source if obj was decorated with @decorator
176 if hasattr(obj,"__wrapped__"):
176 if hasattr(obj,"__wrapped__"):
177 obj = obj.__wrapped__
177 obj = obj.__wrapped__
178 try:
178 try:
179 src = inspect.getsource(obj)
179 src = inspect.getsource(obj)
180 except TypeError:
180 except TypeError:
181 if hasattr(obj,'__class__'):
181 if hasattr(obj,'__class__'):
182 src = inspect.getsource(obj.__class__)
182 src = inspect.getsource(obj.__class__)
183 encoding = get_encoding(obj)
183 encoding = get_encoding(obj)
184 return cast_unicode(src, encoding=encoding)
184 return cast_unicode(src, encoding=encoding)
185
185
186
186
187 def is_simple_callable(obj):
187 def is_simple_callable(obj):
188 """True if obj is a function ()"""
188 """True if obj is a function ()"""
189 return (inspect.isfunction(obj) or inspect.ismethod(obj) or \
189 return (inspect.isfunction(obj) or inspect.ismethod(obj) or \
190 isinstance(obj, _builtin_func_type) or isinstance(obj, _builtin_meth_type))
190 isinstance(obj, _builtin_func_type) or isinstance(obj, _builtin_meth_type))
191
191
192
192
193 def getargspec(obj):
193 def getargspec(obj):
194 """Wrapper around :func:`inspect.getfullargspec` on Python 3, and
194 """Wrapper around :func:`inspect.getfullargspec` on Python 3, and
195 :func:inspect.getargspec` on Python 2.
195 :func:inspect.getargspec` on Python 2.
196
196
197 In addition to functions and methods, this can also handle objects with a
197 In addition to functions and methods, this can also handle objects with a
198 ``__call__`` attribute.
198 ``__call__`` attribute.
199 """
199 """
200 if safe_hasattr(obj, '__call__') and not is_simple_callable(obj):
200 if safe_hasattr(obj, '__call__') and not is_simple_callable(obj):
201 obj = obj.__call__
201 obj = obj.__call__
202
202
203 return inspect.getfullargspec(obj) if PY3 else inspect.getargspec(obj)
203 return inspect.getfullargspec(obj) if PY3 else inspect.getargspec(obj)
204
204
205
205
206 def format_argspec(argspec):
206 def format_argspec(argspec):
207 """Format argspect, convenience wrapper around inspect's.
207 """Format argspect, convenience wrapper around inspect's.
208
208
209 This takes a dict instead of ordered arguments and calls
209 This takes a dict instead of ordered arguments and calls
210 inspect.format_argspec with the arguments in the necessary order.
210 inspect.format_argspec with the arguments in the necessary order.
211 """
211 """
212 return inspect.formatargspec(argspec['args'], argspec['varargs'],
212 return inspect.formatargspec(argspec['args'], argspec['varargs'],
213 argspec['varkw'], argspec['defaults'])
213 argspec['varkw'], argspec['defaults'])
214
214
215
215
216 def call_tip(oinfo, format_call=True):
216 def call_tip(oinfo, format_call=True):
217 """Extract call tip data from an oinfo dict.
217 """Extract call tip data from an oinfo dict.
218
218
219 Parameters
219 Parameters
220 ----------
220 ----------
221 oinfo : dict
221 oinfo : dict
222
222
223 format_call : bool, optional
223 format_call : bool, optional
224 If True, the call line is formatted and returned as a string. If not, a
224 If True, the call line is formatted and returned as a string. If not, a
225 tuple of (name, argspec) is returned.
225 tuple of (name, argspec) is returned.
226
226
227 Returns
227 Returns
228 -------
228 -------
229 call_info : None, str or (str, dict) tuple.
229 call_info : None, str or (str, dict) tuple.
230 When format_call is True, the whole call information is formattted as a
230 When format_call is True, the whole call information is formattted as a
231 single string. Otherwise, the object's name and its argspec dict are
231 single string. Otherwise, the object's name and its argspec dict are
232 returned. If no call information is available, None is returned.
232 returned. If no call information is available, None is returned.
233
233
234 docstring : str or None
234 docstring : str or None
235 The most relevant docstring for calling purposes is returned, if
235 The most relevant docstring for calling purposes is returned, if
236 available. The priority is: call docstring for callable instances, then
236 available. The priority is: call docstring for callable instances, then
237 constructor docstring for classes, then main object's docstring otherwise
237 constructor docstring for classes, then main object's docstring otherwise
238 (regular functions).
238 (regular functions).
239 """
239 """
240 # Get call definition
240 # Get call definition
241 argspec = oinfo.get('argspec')
241 argspec = oinfo.get('argspec')
242 if argspec is None:
242 if argspec is None:
243 call_line = None
243 call_line = None
244 else:
244 else:
245 # Callable objects will have 'self' as their first argument, prune
245 # Callable objects will have 'self' as their first argument, prune
246 # it out if it's there for clarity (since users do *not* pass an
246 # it out if it's there for clarity (since users do *not* pass an
247 # extra first argument explicitly).
247 # extra first argument explicitly).
248 try:
248 try:
249 has_self = argspec['args'][0] == 'self'
249 has_self = argspec['args'][0] == 'self'
250 except (KeyError, IndexError):
250 except (KeyError, IndexError):
251 pass
251 pass
252 else:
252 else:
253 if has_self:
253 if has_self:
254 argspec['args'] = argspec['args'][1:]
254 argspec['args'] = argspec['args'][1:]
255
255
256 call_line = oinfo['name']+format_argspec(argspec)
256 call_line = oinfo['name']+format_argspec(argspec)
257
257
258 # Now get docstring.
258 # Now get docstring.
259 # The priority is: call docstring, constructor docstring, main one.
259 # The priority is: call docstring, constructor docstring, main one.
260 doc = oinfo.get('call_docstring')
260 doc = oinfo.get('call_docstring')
261 if doc is None:
261 if doc is None:
262 doc = oinfo.get('init_docstring')
262 doc = oinfo.get('init_docstring')
263 if doc is None:
263 if doc is None:
264 doc = oinfo.get('docstring','')
264 doc = oinfo.get('docstring','')
265
265
266 return call_line, doc
266 return call_line, doc
267
267
268
268
269 def find_file(obj):
269 def find_file(obj):
270 """Find the absolute path to the file where an object was defined.
270 """Find the absolute path to the file where an object was defined.
271
271
272 This is essentially a robust wrapper around `inspect.getabsfile`.
272 This is essentially a robust wrapper around `inspect.getabsfile`.
273
273
274 Returns None if no file can be found.
274 Returns None if no file can be found.
275
275
276 Parameters
276 Parameters
277 ----------
277 ----------
278 obj : any Python object
278 obj : any Python object
279
279
280 Returns
280 Returns
281 -------
281 -------
282 fname : str
282 fname : str
283 The absolute path to the file where the object was defined.
283 The absolute path to the file where the object was defined.
284 """
284 """
285 # get source if obj was decorated with @decorator
285 # get source if obj was decorated with @decorator
286 if safe_hasattr(obj, '__wrapped__'):
286 if safe_hasattr(obj, '__wrapped__'):
287 obj = obj.__wrapped__
287 obj = obj.__wrapped__
288
288
289 fname = None
289 fname = None
290 try:
290 try:
291 fname = inspect.getabsfile(obj)
291 fname = inspect.getabsfile(obj)
292 except TypeError:
292 except TypeError:
293 # For an instance, the file that matters is where its class was
293 # For an instance, the file that matters is where its class was
294 # declared.
294 # declared.
295 if hasattr(obj, '__class__'):
295 if hasattr(obj, '__class__'):
296 try:
296 try:
297 fname = inspect.getabsfile(obj.__class__)
297 fname = inspect.getabsfile(obj.__class__)
298 except TypeError:
298 except TypeError:
299 # Can happen for builtins
299 # Can happen for builtins
300 pass
300 pass
301 except:
301 except:
302 pass
302 pass
303 return cast_unicode(fname)
303 return cast_unicode(fname)
304
304
305
305
306 def find_source_lines(obj):
306 def find_source_lines(obj):
307 """Find the line number in a file where an object was defined.
307 """Find the line number in a file where an object was defined.
308
308
309 This is essentially a robust wrapper around `inspect.getsourcelines`.
309 This is essentially a robust wrapper around `inspect.getsourcelines`.
310
310
311 Returns None if no file can be found.
311 Returns None if no file can be found.
312
312
313 Parameters
313 Parameters
314 ----------
314 ----------
315 obj : any Python object
315 obj : any Python object
316
316
317 Returns
317 Returns
318 -------
318 -------
319 lineno : int
319 lineno : int
320 The line number where the object definition starts.
320 The line number where the object definition starts.
321 """
321 """
322 # get source if obj was decorated with @decorator
322 # get source if obj was decorated with @decorator
323 if safe_hasattr(obj, '__wrapped__'):
323 if safe_hasattr(obj, '__wrapped__'):
324 obj = obj.__wrapped__
324 obj = obj.__wrapped__
325
325
326 try:
326 try:
327 try:
327 try:
328 lineno = inspect.getsourcelines(obj)[1]
328 lineno = inspect.getsourcelines(obj)[1]
329 except TypeError:
329 except TypeError:
330 # For instances, try the class object like getsource() does
330 # For instances, try the class object like getsource() does
331 if hasattr(obj, '__class__'):
331 if hasattr(obj, '__class__'):
332 lineno = inspect.getsourcelines(obj.__class__)[1]
332 lineno = inspect.getsourcelines(obj.__class__)[1]
333 else:
333 else:
334 lineno = None
334 lineno = None
335 except:
335 except:
336 return None
336 return None
337
337
338 return lineno
338 return lineno
339
339
340
340
341 class Inspector:
341 class Inspector:
342 def __init__(self, color_table=InspectColors,
342 def __init__(self, color_table=InspectColors,
343 code_color_table=PyColorize.ANSICodeColors,
343 code_color_table=PyColorize.ANSICodeColors,
344 scheme='NoColor',
344 scheme='NoColor',
345 str_detail_level=0):
345 str_detail_level=0):
346 self.color_table = color_table
346 self.color_table = color_table
347 self.parser = PyColorize.Parser(code_color_table,out='str')
347 self.parser = PyColorize.Parser(code_color_table,out='str')
348 self.format = self.parser.format
348 self.format = self.parser.format
349 self.str_detail_level = str_detail_level
349 self.str_detail_level = str_detail_level
350 self.set_active_scheme(scheme)
350 self.set_active_scheme(scheme)
351
351
352 def _getdef(self,obj,oname=''):
352 def _getdef(self,obj,oname=''):
353 """Return the call signature for any callable object.
353 """Return the call signature for any callable object.
354
354
355 If any exception is generated, None is returned instead and the
355 If any exception is generated, None is returned instead and the
356 exception is suppressed."""
356 exception is suppressed."""
357 try:
357 try:
358 hdef = oname + inspect.formatargspec(*getargspec(obj))
358 hdef = oname + inspect.formatargspec(*getargspec(obj))
359 return cast_unicode(hdef)
359 return cast_unicode(hdef)
360 except:
360 except:
361 return None
361 return None
362
362
363 def __head(self,h):
363 def __head(self,h):
364 """Return a header string with proper colors."""
364 """Return a header string with proper colors."""
365 return '%s%s%s' % (self.color_table.active_colors.header,h,
365 return '%s%s%s' % (self.color_table.active_colors.header,h,
366 self.color_table.active_colors.normal)
366 self.color_table.active_colors.normal)
367
367
368 def set_active_scheme(self, scheme):
368 def set_active_scheme(self, scheme):
369 self.color_table.set_active_scheme(scheme)
369 self.color_table.set_active_scheme(scheme)
370 self.parser.color_table.set_active_scheme(scheme)
370 self.parser.color_table.set_active_scheme(scheme)
371
371
372 def noinfo(self, msg, oname):
372 def noinfo(self, msg, oname):
373 """Generic message when no information is found."""
373 """Generic message when no information is found."""
374 print('No %s found' % msg, end=' ')
374 print('No %s found' % msg, end=' ')
375 if oname:
375 if oname:
376 print('for %s' % oname)
376 print('for %s' % oname)
377 else:
377 else:
378 print()
378 print()
379
379
380 def pdef(self, obj, oname=''):
380 def pdef(self, obj, oname=''):
381 """Print the call signature for any callable object.
381 """Print the call signature for any callable object.
382
382
383 If the object is a class, print the constructor information."""
383 If the object is a class, print the constructor information."""
384
384
385 if not callable(obj):
385 if not callable(obj):
386 print('Object is not callable.')
386 print('Object is not callable.')
387 return
387 return
388
388
389 header = ''
389 header = ''
390
390
391 if inspect.isclass(obj):
391 if inspect.isclass(obj):
392 header = self.__head('Class constructor information:\n')
392 header = self.__head('Class constructor information:\n')
393 obj = obj.__init__
393 obj = obj.__init__
394 elif (not py3compat.PY3) and type(obj) is types.InstanceType:
394 elif (not py3compat.PY3) and type(obj) is types.InstanceType:
395 obj = obj.__call__
395 obj = obj.__call__
396
396
397 output = self._getdef(obj,oname)
397 output = self._getdef(obj,oname)
398 if output is None:
398 if output is None:
399 self.noinfo('definition header',oname)
399 self.noinfo('definition header',oname)
400 else:
400 else:
401 print(header,self.format(output), end=' ', file=io.stdout)
401 print(header,self.format(output), end=' ', file=io.stdout)
402
402
403 # In Python 3, all classes are new-style, so they all have __init__.
403 # In Python 3, all classes are new-style, so they all have __init__.
404 @skip_doctest_py3
404 @skip_doctest_py3
405 def pdoc(self,obj,oname='',formatter = None):
405 def pdoc(self,obj,oname='',formatter = None):
406 """Print the docstring for any object.
406 """Print the docstring for any object.
407
407
408 Optional:
408 Optional:
409 -formatter: a function to run the docstring through for specially
409 -formatter: a function to run the docstring through for specially
410 formatted docstrings.
410 formatted docstrings.
411
411
412 Examples
412 Examples
413 --------
413 --------
414
414
415 In [1]: class NoInit:
415 In [1]: class NoInit:
416 ...: pass
416 ...: pass
417
417
418 In [2]: class NoDoc:
418 In [2]: class NoDoc:
419 ...: def __init__(self):
419 ...: def __init__(self):
420 ...: pass
420 ...: pass
421
421
422 In [3]: %pdoc NoDoc
422 In [3]: %pdoc NoDoc
423 No documentation found for NoDoc
423 No documentation found for NoDoc
424
424
425 In [4]: %pdoc NoInit
425 In [4]: %pdoc NoInit
426 No documentation found for NoInit
426 No documentation found for NoInit
427
427
428 In [5]: obj = NoInit()
428 In [5]: obj = NoInit()
429
429
430 In [6]: %pdoc obj
430 In [6]: %pdoc obj
431 No documentation found for obj
431 No documentation found for obj
432
432
433 In [5]: obj2 = NoDoc()
433 In [5]: obj2 = NoDoc()
434
434
435 In [6]: %pdoc obj2
435 In [6]: %pdoc obj2
436 No documentation found for obj2
436 No documentation found for obj2
437 """
437 """
438
438
439 head = self.__head # For convenience
439 head = self.__head # For convenience
440 lines = []
440 lines = []
441 ds = getdoc(obj)
441 ds = getdoc(obj)
442 if formatter:
442 if formatter:
443 ds = formatter(ds)
443 ds = formatter(ds)
444 if ds:
444 if ds:
445 lines.append(head("Class Docstring:"))
445 lines.append(head("Class Docstring:"))
446 lines.append(indent(ds))
446 lines.append(indent(ds))
447 if inspect.isclass(obj) and hasattr(obj, '__init__'):
447 if inspect.isclass(obj) and hasattr(obj, '__init__'):
448 init_ds = getdoc(obj.__init__)
448 init_ds = getdoc(obj.__init__)
449 if init_ds is not None:
449 if init_ds is not None:
450 lines.append(head("Constructor Docstring:"))
450 lines.append(head("Init Docstring:"))
451 lines.append(indent(init_ds))
451 lines.append(indent(init_ds))
452 elif hasattr(obj,'__call__'):
452 elif hasattr(obj,'__call__'):
453 call_ds = getdoc(obj.__call__)
453 call_ds = getdoc(obj.__call__)
454 if call_ds:
454 if call_ds:
455 lines.append(head("Calling Docstring:"))
455 lines.append(head("Call Docstring:"))
456 lines.append(indent(call_ds))
456 lines.append(indent(call_ds))
457
457
458 if not lines:
458 if not lines:
459 self.noinfo('documentation',oname)
459 self.noinfo('documentation',oname)
460 else:
460 else:
461 page.page('\n'.join(lines))
461 page.page('\n'.join(lines))
462
462
463 def psource(self,obj,oname=''):
463 def psource(self,obj,oname=''):
464 """Print the source code for an object."""
464 """Print the source code for an object."""
465
465
466 # Flush the source cache because inspect can return out-of-date source
466 # Flush the source cache because inspect can return out-of-date source
467 linecache.checkcache()
467 linecache.checkcache()
468 try:
468 try:
469 src = getsource(obj)
469 src = getsource(obj)
470 except:
470 except:
471 self.noinfo('source',oname)
471 self.noinfo('source',oname)
472 else:
472 else:
473 page.page(self.format(src))
473 page.page(self.format(src))
474
474
475 def pfile(self, obj, oname=''):
475 def pfile(self, obj, oname=''):
476 """Show the whole file where an object was defined."""
476 """Show the whole file where an object was defined."""
477
477
478 lineno = find_source_lines(obj)
478 lineno = find_source_lines(obj)
479 if lineno is None:
479 if lineno is None:
480 self.noinfo('file', oname)
480 self.noinfo('file', oname)
481 return
481 return
482
482
483 ofile = find_file(obj)
483 ofile = find_file(obj)
484 # run contents of file through pager starting at line where the object
484 # run contents of file through pager starting at line where the object
485 # is defined, as long as the file isn't binary and is actually on the
485 # is defined, as long as the file isn't binary and is actually on the
486 # filesystem.
486 # filesystem.
487 if ofile.endswith(('.so', '.dll', '.pyd')):
487 if ofile.endswith(('.so', '.dll', '.pyd')):
488 print('File %r is binary, not printing.' % ofile)
488 print('File %r is binary, not printing.' % ofile)
489 elif not os.path.isfile(ofile):
489 elif not os.path.isfile(ofile):
490 print('File %r does not exist, not printing.' % ofile)
490 print('File %r does not exist, not printing.' % ofile)
491 else:
491 else:
492 # Print only text files, not extension binaries. Note that
492 # Print only text files, not extension binaries. Note that
493 # getsourcelines returns lineno with 1-offset and page() uses
493 # getsourcelines returns lineno with 1-offset and page() uses
494 # 0-offset, so we must adjust.
494 # 0-offset, so we must adjust.
495 page.page(self.format(openpy.read_py_file(ofile, skip_encoding_cookie=False)), lineno - 1)
495 page.page(self.format(openpy.read_py_file(ofile, skip_encoding_cookie=False)), lineno - 1)
496
496
497 def _format_fields(self, fields, title_width=12):
497 def _format_fields(self, fields, title_width=0):
498 """Formats a list of fields for display.
498 """Formats a list of fields for display.
499
499
500 Parameters
500 Parameters
501 ----------
501 ----------
502 fields : list
502 fields : list
503 A list of 2-tuples: (field_title, field_content)
503 A list of 2-tuples: (field_title, field_content)
504 title_width : int
504 title_width : int
505 How many characters to pad titles to. Default 12.
505 How many characters to pad titles to. Default to longest title.
506 """
506 """
507 out = []
507 out = []
508 header = self.__head
508 header = self.__head
509 if title_width == 0:
510 for title, _ in fields:
511 title_width = max(len(title) + 2, title_width)
509 for title, content in fields:
512 for title, content in fields:
510 if len(content.splitlines()) > 1:
513 if len(content.splitlines()) > 1:
511 title = header(title + ":") + "\n"
514 title = header(title + ":") + "\n"
512 else:
515 else:
513 title = header((title+":").ljust(title_width))
516 title = header((title+":").ljust(title_width))
514 out.append(cast_unicode(title) + cast_unicode(content))
517 out.append(cast_unicode(title) + cast_unicode(content))
515 return "\n".join(out)
518 return "\n".join(out)
516
519
517 # The fields to be displayed by pinfo: (fancy_name, key_in_info_dict)
520 # The fields to be displayed by pinfo: (fancy_name, key_in_info_dict)
518 pinfo_fields1 = [("Type", "type_name"),
521 pinfo_fields1 = [("Type", "type_name"),
519 ]
522 ]
520
523
521 pinfo_fields2 = [("String Form", "string_form"),
524 pinfo_fields2 = [("String Form", "string_form"),
522 ]
525 ]
523
526
524 pinfo_fields3 = [("Length", "length"),
527 pinfo_fields3 = [("Length", "length"),
525 ("File", "file"),
528 ("File", "file"),
526 ("Definition", "definition"),
529 ("Definition", "definition"),
527 ]
530 ]
528
531
529 pinfo_fields_obj = [("Class Docstring", "class_docstring"),
532 pinfo_fields_obj = [("Class Docstring", "class_docstring"),
530 ("Constructor Docstring","init_docstring"),
533 ("Init Docstring", "init_docstring"),
531 ("Call def", "call_def"),
534 ("Call def", "call_def"),
532 ("Call docstring", "call_docstring")]
535 ("Call docstring", "call_docstring")]
533
536
534 def pinfo(self,obj,oname='',formatter=None,info=None,detail_level=0):
537 def pinfo(self,obj,oname='',formatter=None,info=None,detail_level=0):
535 """Show detailed information about an object.
538 """Show detailed information about an object.
536
539
537 Optional arguments:
540 Optional arguments:
538
541
539 - oname: name of the variable pointing to the object.
542 - oname: name of the variable pointing to the object.
540
543
541 - formatter: special formatter for docstrings (see pdoc)
544 - formatter: special formatter for docstrings (see pdoc)
542
545
543 - info: a structure with some information fields which may have been
546 - info: a structure with some information fields which may have been
544 precomputed already.
547 precomputed already.
545
548
546 - detail_level: if set to 1, more information is given.
549 - detail_level: if set to 1, more information is given.
547 """
550 """
548 info = self.info(obj, oname=oname, formatter=formatter,
551 info = self.info(obj, oname=oname, formatter=formatter,
549 info=info, detail_level=detail_level)
552 info=info, detail_level=detail_level)
550 displayfields = []
553 displayfields = []
551 def add_fields(fields):
554 def add_fields(fields):
552 for title, key in fields:
555 for title, key in fields:
553 field = info[key]
556 field = info[key]
554 if field is not None:
557 if field is not None:
555 displayfields.append((title, field.rstrip()))
558 displayfields.append((title, field.rstrip()))
556
559
557 add_fields(self.pinfo_fields1)
560 add_fields(self.pinfo_fields1)
558
561
559 # Base class for old-style instances
562 # Base class for old-style instances
560 if (not py3compat.PY3) and isinstance(obj, types.InstanceType) and info['base_class']:
563 if (not py3compat.PY3) and isinstance(obj, types.InstanceType) and info['base_class']:
561 displayfields.append(("Base Class", info['base_class'].rstrip()))
564 displayfields.append(("Base Class", info['base_class'].rstrip()))
562
565
563 add_fields(self.pinfo_fields2)
566 add_fields(self.pinfo_fields2)
564
567
565 # Namespace
568 # Namespace
566 if info['namespace'] != 'Interactive':
569 if info['namespace'] != 'Interactive':
567 displayfields.append(("Namespace", info['namespace'].rstrip()))
570 displayfields.append(("Namespace", info['namespace'].rstrip()))
568
571
569 add_fields(self.pinfo_fields3)
572 add_fields(self.pinfo_fields3)
573 if info['isclass'] and info['init_definition']:
574 displayfields.append(("Init Definition",
575 info['init_definition'].rstrip()))
570
576
571 # Source or docstring, depending on detail level and whether
577 # Source or docstring, depending on detail level and whether
572 # source found.
578 # source found.
573 if detail_level > 0 and info['source'] is not None:
579 if detail_level > 0 and info['source'] is not None:
574 displayfields.append(("Source",
580 displayfields.append(("Source",
575 self.format(cast_unicode(info['source']))))
581 self.format(cast_unicode(info['source']))))
576 elif info['docstring'] is not None:
582 elif info['docstring'] is not None:
577 displayfields.append(("Docstring", info["docstring"]))
583 displayfields.append(("Docstring", info["docstring"]))
578
584
579 # Constructor info for classes
585 # Constructor info for classes
580 if info['isclass']:
586 if info['isclass']:
581 if info['init_definition'] or info['init_docstring']:
582 displayfields.append(("Constructor information", ""))
583 if info['init_definition'] is not None:
584 displayfields.append((" Definition",
585 info['init_definition'].rstrip()))
586 if info['init_docstring'] is not None:
587 if info['init_docstring'] is not None:
587 displayfields.append((" Docstring",
588 displayfields.append(("Init Docstring",
588 indent(info['init_docstring'])))
589 info['init_docstring']))
589
590
590 # Info for objects:
591 # Info for objects:
591 else:
592 else:
592 add_fields(self.pinfo_fields_obj)
593 add_fields(self.pinfo_fields_obj)
593
594
594 # Finally send to printer/pager:
595 # Finally send to printer/pager:
595 if displayfields:
596 if displayfields:
596 page.page(self._format_fields(displayfields))
597 page.page(self._format_fields(displayfields))
597
598
598 def info(self, obj, oname='', formatter=None, info=None, detail_level=0):
599 def info(self, obj, oname='', formatter=None, info=None, detail_level=0):
599 """Compute a dict with detailed information about an object.
600 """Compute a dict with detailed information about an object.
600
601
601 Optional arguments:
602 Optional arguments:
602
603
603 - oname: name of the variable pointing to the object.
604 - oname: name of the variable pointing to the object.
604
605
605 - formatter: special formatter for docstrings (see pdoc)
606 - formatter: special formatter for docstrings (see pdoc)
606
607
607 - info: a structure with some information fields which may have been
608 - info: a structure with some information fields which may have been
608 precomputed already.
609 precomputed already.
609
610
610 - detail_level: if set to 1, more information is given.
611 - detail_level: if set to 1, more information is given.
611 """
612 """
612
613
613 obj_type = type(obj)
614 obj_type = type(obj)
614
615
615 if info is None:
616 if info is None:
616 ismagic = 0
617 ismagic = 0
617 isalias = 0
618 isalias = 0
618 ospace = ''
619 ospace = ''
619 else:
620 else:
620 ismagic = info.ismagic
621 ismagic = info.ismagic
621 isalias = info.isalias
622 isalias = info.isalias
622 ospace = info.namespace
623 ospace = info.namespace
623
624
624 # Get docstring, special-casing aliases:
625 # Get docstring, special-casing aliases:
625 if isalias:
626 if isalias:
626 if not callable(obj):
627 if not callable(obj):
627 try:
628 try:
628 ds = "Alias to the system command:\n %s" % obj[1]
629 ds = "Alias to the system command:\n %s" % obj[1]
629 except:
630 except:
630 ds = "Alias: " + str(obj)
631 ds = "Alias: " + str(obj)
631 else:
632 else:
632 ds = "Alias to " + str(obj)
633 ds = "Alias to " + str(obj)
633 if obj.__doc__:
634 if obj.__doc__:
634 ds += "\nDocstring:\n" + obj.__doc__
635 ds += "\nDocstring:\n" + obj.__doc__
635 else:
636 else:
636 ds = getdoc(obj)
637 ds = getdoc(obj)
637 if ds is None:
638 if ds is None:
638 ds = '<no docstring>'
639 ds = '<no docstring>'
639 if formatter is not None:
640 if formatter is not None:
640 ds = formatter(ds)
641 ds = formatter(ds)
641
642
642 # store output in a dict, we initialize it here and fill it as we go
643 # store output in a dict, we initialize it here and fill it as we go
643 out = dict(name=oname, found=True, isalias=isalias, ismagic=ismagic)
644 out = dict(name=oname, found=True, isalias=isalias, ismagic=ismagic)
644
645
645 string_max = 200 # max size of strings to show (snipped if longer)
646 string_max = 200 # max size of strings to show (snipped if longer)
646 shalf = int((string_max -5)/2)
647 shalf = int((string_max -5)/2)
647
648
648 if ismagic:
649 if ismagic:
649 obj_type_name = 'Magic function'
650 obj_type_name = 'Magic function'
650 elif isalias:
651 elif isalias:
651 obj_type_name = 'System alias'
652 obj_type_name = 'System alias'
652 else:
653 else:
653 obj_type_name = obj_type.__name__
654 obj_type_name = obj_type.__name__
654 out['type_name'] = obj_type_name
655 out['type_name'] = obj_type_name
655
656
656 try:
657 try:
657 bclass = obj.__class__
658 bclass = obj.__class__
658 out['base_class'] = str(bclass)
659 out['base_class'] = str(bclass)
659 except: pass
660 except: pass
660
661
661 # String form, but snip if too long in ? form (full in ??)
662 # String form, but snip if too long in ? form (full in ??)
662 if detail_level >= self.str_detail_level:
663 if detail_level >= self.str_detail_level:
663 try:
664 try:
664 ostr = str(obj)
665 ostr = str(obj)
665 str_head = 'string_form'
666 str_head = 'string_form'
666 if not detail_level and len(ostr)>string_max:
667 if not detail_level and len(ostr)>string_max:
667 ostr = ostr[:shalf] + ' <...> ' + ostr[-shalf:]
668 ostr = ostr[:shalf] + ' <...> ' + ostr[-shalf:]
668 ostr = ("\n" + " " * len(str_head.expandtabs())).\
669 ostr = ("\n" + " " * len(str_head.expandtabs())).\
669 join(q.strip() for q in ostr.split("\n"))
670 join(q.strip() for q in ostr.split("\n"))
670 out[str_head] = ostr
671 out[str_head] = ostr
671 except:
672 except:
672 pass
673 pass
673
674
674 if ospace:
675 if ospace:
675 out['namespace'] = ospace
676 out['namespace'] = ospace
676
677
677 # Length (for strings and lists)
678 # Length (for strings and lists)
678 try:
679 try:
679 out['length'] = str(len(obj))
680 out['length'] = str(len(obj))
680 except: pass
681 except: pass
681
682
682 # Filename where object was defined
683 # Filename where object was defined
683 binary_file = False
684 binary_file = False
684 fname = find_file(obj)
685 fname = find_file(obj)
685 if fname is None:
686 if fname is None:
686 # if anything goes wrong, we don't want to show source, so it's as
687 # if anything goes wrong, we don't want to show source, so it's as
687 # if the file was binary
688 # if the file was binary
688 binary_file = True
689 binary_file = True
689 else:
690 else:
690 if fname.endswith(('.so', '.dll', '.pyd')):
691 if fname.endswith(('.so', '.dll', '.pyd')):
691 binary_file = True
692 binary_file = True
692 elif fname.endswith('<string>'):
693 elif fname.endswith('<string>'):
693 fname = 'Dynamically generated function. No source code available.'
694 fname = 'Dynamically generated function. No source code available.'
694 out['file'] = fname
695 out['file'] = fname
695
696
696 # reconstruct the function definition and print it:
697 defln = self._getdef(obj, oname)
698 if defln:
699 out['definition'] = self.format(defln)
700
701 # Docstrings only in detail 0 mode, since source contains them (we
697 # Docstrings only in detail 0 mode, since source contains them (we
702 # avoid repetitions). If source fails, we add them back, see below.
698 # avoid repetitions). If source fails, we add them back, see below.
703 if ds and detail_level == 0:
699 if ds and detail_level == 0:
704 out['docstring'] = ds
700 out['docstring'] = ds
705
701
706 # Original source code for any callable
702 # Original source code for any callable
707 if detail_level:
703 if detail_level:
708 # Flush the source cache because inspect can return out-of-date
704 # Flush the source cache because inspect can return out-of-date
709 # source
705 # source
710 linecache.checkcache()
706 linecache.checkcache()
711 source = None
707 source = None
712 try:
708 try:
713 try:
709 try:
714 source = getsource(obj, binary_file)
710 source = getsource(obj, binary_file)
715 except TypeError:
711 except TypeError:
716 if hasattr(obj, '__class__'):
712 if hasattr(obj, '__class__'):
717 source = getsource(obj.__class__, binary_file)
713 source = getsource(obj.__class__, binary_file)
718 if source is not None:
714 if source is not None:
719 out['source'] = source.rstrip()
715 out['source'] = source.rstrip()
720 except Exception:
716 except Exception:
721 pass
717 pass
722
718
723 if ds and source is None:
719 if ds and source is None:
724 out['docstring'] = ds
720 out['docstring'] = ds
725
721
726
722
727 # Constructor docstring for classes
723 # Constructor docstring for classes
728 if inspect.isclass(obj):
724 if inspect.isclass(obj):
729 out['isclass'] = True
725 out['isclass'] = True
730 # reconstruct the function definition and print it:
726 # reconstruct the function definition and print it:
731 try:
727 try:
732 obj_init = obj.__init__
728 obj_init = obj.__init__
733 except AttributeError:
729 except AttributeError:
734 init_def = init_ds = None
730 init_def = init_ds = None
735 else:
731 else:
736 init_def = self._getdef(obj_init,oname)
732 init_def = self._getdef(obj_init,oname)
737 init_ds = getdoc(obj_init)
733 init_ds = getdoc(obj_init)
738 # Skip Python's auto-generated docstrings
734 # Skip Python's auto-generated docstrings
739 if init_ds == _object_init_docstring:
735 if init_ds == _object_init_docstring:
740 init_ds = None
736 init_ds = None
741
737
742 if init_def or init_ds:
738 if init_def or init_ds:
743 if init_def:
739 if init_def:
744 out['init_definition'] = self.format(init_def)
740 out['init_definition'] = self.format(init_def)
745 if init_ds:
741 if init_ds:
746 out['init_docstring'] = init_ds
742 out['init_docstring'] = init_ds
747
743
748 # and class docstring for instances:
744 # and class docstring for instances:
749 else:
745 else:
746 # reconstruct the function definition and print it:
747 defln = self._getdef(obj, oname)
748 if defln:
749 out['definition'] = self.format(defln)
750
750 # First, check whether the instance docstring is identical to the
751 # First, check whether the instance docstring is identical to the
751 # class one, and print it separately if they don't coincide. In
752 # class one, and print it separately if they don't coincide. In
752 # most cases they will, but it's nice to print all the info for
753 # most cases they will, but it's nice to print all the info for
753 # objects which use instance-customized docstrings.
754 # objects which use instance-customized docstrings.
754 if ds:
755 if ds:
755 try:
756 try:
756 cls = getattr(obj,'__class__')
757 cls = getattr(obj,'__class__')
757 except:
758 except:
758 class_ds = None
759 class_ds = None
759 else:
760 else:
760 class_ds = getdoc(cls)
761 class_ds = getdoc(cls)
761 # Skip Python's auto-generated docstrings
762 # Skip Python's auto-generated docstrings
762 if class_ds in _builtin_type_docstrings:
763 if class_ds in _builtin_type_docstrings:
763 class_ds = None
764 class_ds = None
764 if class_ds and ds != class_ds:
765 if class_ds and ds != class_ds:
765 out['class_docstring'] = class_ds
766 out['class_docstring'] = class_ds
766
767
767 # Next, try to show constructor docstrings
768 # Next, try to show constructor docstrings
768 try:
769 try:
769 init_ds = getdoc(obj.__init__)
770 init_ds = getdoc(obj.__init__)
770 # Skip Python's auto-generated docstrings
771 # Skip Python's auto-generated docstrings
771 if init_ds == _object_init_docstring:
772 if init_ds == _object_init_docstring:
772 init_ds = None
773 init_ds = None
773 except AttributeError:
774 except AttributeError:
774 init_ds = None
775 init_ds = None
775 if init_ds:
776 if init_ds:
776 out['init_docstring'] = init_ds
777 out['init_docstring'] = init_ds
777
778
778 # Call form docstring for callable instances
779 # Call form docstring for callable instances
779 if safe_hasattr(obj, '__call__') and not is_simple_callable(obj):
780 if safe_hasattr(obj, '__call__') and not is_simple_callable(obj):
780 call_def = self._getdef(obj.__call__, oname)
781 call_def = self._getdef(obj.__call__, oname)
781 if call_def is not None:
782 if call_def:
782 out['call_def'] = self.format(call_def)
783 call_def = self.format(call_def)
784 # it may never be the case that call def and definition differ,
785 # but don't include the same signature twice
786 if call_def != out.get('definition'):
787 out['call_def'] = call_def
783 call_ds = getdoc(obj.__call__)
788 call_ds = getdoc(obj.__call__)
784 # Skip Python's auto-generated docstrings
789 # Skip Python's auto-generated docstrings
785 if call_ds == _func_call_docstring:
790 if call_ds == _func_call_docstring:
786 call_ds = None
791 call_ds = None
787 if call_ds:
792 if call_ds:
788 out['call_docstring'] = call_ds
793 out['call_docstring'] = call_ds
789
794
790 # Compute the object's argspec as a callable. The key is to decide
795 # Compute the object's argspec as a callable. The key is to decide
791 # whether to pull it from the object itself, from its __init__ or
796 # whether to pull it from the object itself, from its __init__ or
792 # from its __call__ method.
797 # from its __call__ method.
793
798
794 if inspect.isclass(obj):
799 if inspect.isclass(obj):
795 # Old-style classes need not have an __init__
800 # Old-style classes need not have an __init__
796 callable_obj = getattr(obj, "__init__", None)
801 callable_obj = getattr(obj, "__init__", None)
797 elif callable(obj):
802 elif callable(obj):
798 callable_obj = obj
803 callable_obj = obj
799 else:
804 else:
800 callable_obj = None
805 callable_obj = None
801
806
802 if callable_obj:
807 if callable_obj:
803 try:
808 try:
804 argspec = getargspec(callable_obj)
809 argspec = getargspec(callable_obj)
805 except (TypeError, AttributeError):
810 except (TypeError, AttributeError):
806 # For extensions/builtins we can't retrieve the argspec
811 # For extensions/builtins we can't retrieve the argspec
807 pass
812 pass
808 else:
813 else:
809 # named tuples' _asdict() method returns an OrderedDict, but we
814 # named tuples' _asdict() method returns an OrderedDict, but we
810 # we want a normal
815 # we want a normal
811 out['argspec'] = argspec_dict = dict(argspec._asdict())
816 out['argspec'] = argspec_dict = dict(argspec._asdict())
812 # We called this varkw before argspec became a named tuple.
817 # We called this varkw before argspec became a named tuple.
813 # With getfullargspec it's also called varkw.
818 # With getfullargspec it's also called varkw.
814 if 'varkw' not in argspec_dict:
819 if 'varkw' not in argspec_dict:
815 argspec_dict['varkw'] = argspec_dict.pop('keywords')
820 argspec_dict['varkw'] = argspec_dict.pop('keywords')
816
821
817 return object_info(**out)
822 return object_info(**out)
818
823
819
824
820 def psearch(self,pattern,ns_table,ns_search=[],
825 def psearch(self,pattern,ns_table,ns_search=[],
821 ignore_case=False,show_all=False):
826 ignore_case=False,show_all=False):
822 """Search namespaces with wildcards for objects.
827 """Search namespaces with wildcards for objects.
823
828
824 Arguments:
829 Arguments:
825
830
826 - pattern: string containing shell-like wildcards to use in namespace
831 - pattern: string containing shell-like wildcards to use in namespace
827 searches and optionally a type specification to narrow the search to
832 searches and optionally a type specification to narrow the search to
828 objects of that type.
833 objects of that type.
829
834
830 - ns_table: dict of name->namespaces for search.
835 - ns_table: dict of name->namespaces for search.
831
836
832 Optional arguments:
837 Optional arguments:
833
838
834 - ns_search: list of namespace names to include in search.
839 - ns_search: list of namespace names to include in search.
835
840
836 - ignore_case(False): make the search case-insensitive.
841 - ignore_case(False): make the search case-insensitive.
837
842
838 - show_all(False): show all names, including those starting with
843 - show_all(False): show all names, including those starting with
839 underscores.
844 underscores.
840 """
845 """
841 #print 'ps pattern:<%r>' % pattern # dbg
846 #print 'ps pattern:<%r>' % pattern # dbg
842
847
843 # defaults
848 # defaults
844 type_pattern = 'all'
849 type_pattern = 'all'
845 filter = ''
850 filter = ''
846
851
847 cmds = pattern.split()
852 cmds = pattern.split()
848 len_cmds = len(cmds)
853 len_cmds = len(cmds)
849 if len_cmds == 1:
854 if len_cmds == 1:
850 # Only filter pattern given
855 # Only filter pattern given
851 filter = cmds[0]
856 filter = cmds[0]
852 elif len_cmds == 2:
857 elif len_cmds == 2:
853 # Both filter and type specified
858 # Both filter and type specified
854 filter,type_pattern = cmds
859 filter,type_pattern = cmds
855 else:
860 else:
856 raise ValueError('invalid argument string for psearch: <%s>' %
861 raise ValueError('invalid argument string for psearch: <%s>' %
857 pattern)
862 pattern)
858
863
859 # filter search namespaces
864 # filter search namespaces
860 for name in ns_search:
865 for name in ns_search:
861 if name not in ns_table:
866 if name not in ns_table:
862 raise ValueError('invalid namespace <%s>. Valid names: %s' %
867 raise ValueError('invalid namespace <%s>. Valid names: %s' %
863 (name,ns_table.keys()))
868 (name,ns_table.keys()))
864
869
865 #print 'type_pattern:',type_pattern # dbg
870 #print 'type_pattern:',type_pattern # dbg
866 search_result, namespaces_seen = set(), set()
871 search_result, namespaces_seen = set(), set()
867 for ns_name in ns_search:
872 for ns_name in ns_search:
868 ns = ns_table[ns_name]
873 ns = ns_table[ns_name]
869 # Normally, locals and globals are the same, so we just check one.
874 # Normally, locals and globals are the same, so we just check one.
870 if id(ns) in namespaces_seen:
875 if id(ns) in namespaces_seen:
871 continue
876 continue
872 namespaces_seen.add(id(ns))
877 namespaces_seen.add(id(ns))
873 tmp_res = list_namespace(ns, type_pattern, filter,
878 tmp_res = list_namespace(ns, type_pattern, filter,
874 ignore_case=ignore_case, show_all=show_all)
879 ignore_case=ignore_case, show_all=show_all)
875 search_result.update(tmp_res)
880 search_result.update(tmp_res)
876
881
877 page.page('\n'.join(sorted(search_result)))
882 page.page('\n'.join(sorted(search_result)))
@@ -1,157 +1,157 b''
1 """Tests for debugging machinery.
1 """Tests for debugging machinery.
2 """
2 """
3 from __future__ import print_function
3 from __future__ import print_function
4 #-----------------------------------------------------------------------------
4 #-----------------------------------------------------------------------------
5 # Copyright (c) 2012, The IPython Development Team.
5 # Copyright (c) 2012, The IPython Development Team.
6 #
6 #
7 # Distributed under the terms of the Modified BSD License.
7 # Distributed under the terms of the Modified BSD License.
8 #
8 #
9 # The full license is in the file COPYING.txt, distributed with this software.
9 # The full license is in the file COPYING.txt, distributed with this software.
10 #-----------------------------------------------------------------------------
10 #-----------------------------------------------------------------------------
11
11
12 #-----------------------------------------------------------------------------
12 #-----------------------------------------------------------------------------
13 # Imports
13 # Imports
14 #-----------------------------------------------------------------------------
14 #-----------------------------------------------------------------------------
15
15
16 import sys
16 import sys
17
17
18 # third-party
18 # third-party
19 import nose.tools as nt
19 import nose.tools as nt
20
20
21 # Our own
21 # Our own
22 from IPython.core import debugger
22 from IPython.core import debugger
23
23
24 #-----------------------------------------------------------------------------
24 #-----------------------------------------------------------------------------
25 # Helper classes, from CPython's Pdb test suite
25 # Helper classes, from CPython's Pdb test suite
26 #-----------------------------------------------------------------------------
26 #-----------------------------------------------------------------------------
27
27
28 class _FakeInput(object):
28 class _FakeInput(object):
29 """
29 """
30 A fake input stream for pdb's interactive debugger. Whenever a
30 A fake input stream for pdb's interactive debugger. Whenever a
31 line is read, print it (to simulate the user typing it), and then
31 line is read, print it (to simulate the user typing it), and then
32 return it. The set of lines to return is specified in the
32 return it. The set of lines to return is specified in the
33 constructor; they should not have trailing newlines.
33 constructor; they should not have trailing newlines.
34 """
34 """
35 def __init__(self, lines):
35 def __init__(self, lines):
36 self.lines = iter(lines)
36 self.lines = iter(lines)
37
37
38 def readline(self):
38 def readline(self):
39 line = next(self.lines)
39 line = next(self.lines)
40 print(line)
40 print(line)
41 return line+'\n'
41 return line+'\n'
42
42
43 class PdbTestInput(object):
43 class PdbTestInput(object):
44 """Context manager that makes testing Pdb in doctests easier."""
44 """Context manager that makes testing Pdb in doctests easier."""
45
45
46 def __init__(self, input):
46 def __init__(self, input):
47 self.input = input
47 self.input = input
48
48
49 def __enter__(self):
49 def __enter__(self):
50 self.real_stdin = sys.stdin
50 self.real_stdin = sys.stdin
51 sys.stdin = _FakeInput(self.input)
51 sys.stdin = _FakeInput(self.input)
52
52
53 def __exit__(self, *exc):
53 def __exit__(self, *exc):
54 sys.stdin = self.real_stdin
54 sys.stdin = self.real_stdin
55
55
56 #-----------------------------------------------------------------------------
56 #-----------------------------------------------------------------------------
57 # Tests
57 # Tests
58 #-----------------------------------------------------------------------------
58 #-----------------------------------------------------------------------------
59
59
60 def test_longer_repr():
60 def test_longer_repr():
61 try:
61 try:
62 from reprlib import repr as trepr # Py 3
62 from reprlib import repr as trepr # Py 3
63 except ImportError:
63 except ImportError:
64 from repr import repr as trepr # Py 2
64 from repr import repr as trepr # Py 2
65
65
66 a = '1234567890'* 7
66 a = '1234567890'* 7
67 ar = "'1234567890123456789012345678901234567890123456789012345678901234567890'"
67 ar = "'1234567890123456789012345678901234567890123456789012345678901234567890'"
68 a_trunc = "'123456789012...8901234567890'"
68 a_trunc = "'123456789012...8901234567890'"
69 nt.assert_equal(trepr(a), a_trunc)
69 nt.assert_equal(trepr(a), a_trunc)
70 # The creation of our tracer modifies the repr module's repr function
70 # The creation of our tracer modifies the repr module's repr function
71 # in-place, since that global is used directly by the stdlib's pdb module.
71 # in-place, since that global is used directly by the stdlib's pdb module.
72 t = debugger.Tracer()
72 t = debugger.Tracer()
73 nt.assert_equal(trepr(a), ar)
73 nt.assert_equal(trepr(a), ar)
74
74
75 def test_ipdb_magics():
75 def test_ipdb_magics():
76 '''Test calling some IPython magics from ipdb.
76 '''Test calling some IPython magics from ipdb.
77
77
78 First, set up some test functions and classes which we can inspect.
78 First, set up some test functions and classes which we can inspect.
79
79
80 >>> class ExampleClass(object):
80 >>> class ExampleClass(object):
81 ... """Docstring for ExampleClass."""
81 ... """Docstring for ExampleClass."""
82 ... def __init__(self):
82 ... def __init__(self):
83 ... """Docstring for ExampleClass.__init__"""
83 ... """Docstring for ExampleClass.__init__"""
84 ... pass
84 ... pass
85 ... def __str__(self):
85 ... def __str__(self):
86 ... return "ExampleClass()"
86 ... return "ExampleClass()"
87
87
88 >>> def example_function(x, y, z="hello"):
88 >>> def example_function(x, y, z="hello"):
89 ... """Docstring for example_function."""
89 ... """Docstring for example_function."""
90 ... pass
90 ... pass
91
91
92 >>> old_trace = sys.gettrace()
92 >>> old_trace = sys.gettrace()
93
93
94 Create a function which triggers ipdb.
94 Create a function which triggers ipdb.
95
95
96 >>> def trigger_ipdb():
96 >>> def trigger_ipdb():
97 ... a = ExampleClass()
97 ... a = ExampleClass()
98 ... debugger.Pdb().set_trace()
98 ... debugger.Pdb().set_trace()
99
99
100 >>> with PdbTestInput([
100 >>> with PdbTestInput([
101 ... 'pdef example_function',
101 ... 'pdef example_function',
102 ... 'pdoc ExampleClass',
102 ... 'pdoc ExampleClass',
103 ... 'pinfo a',
103 ... 'pinfo a',
104 ... 'continue',
104 ... 'continue',
105 ... ]):
105 ... ]):
106 ... trigger_ipdb()
106 ... trigger_ipdb()
107 --Return--
107 --Return--
108 None
108 None
109 > <doctest ...>(3)trigger_ipdb()
109 > <doctest ...>(3)trigger_ipdb()
110 1 def trigger_ipdb():
110 1 def trigger_ipdb():
111 2 a = ExampleClass()
111 2 a = ExampleClass()
112 ----> 3 debugger.Pdb().set_trace()
112 ----> 3 debugger.Pdb().set_trace()
113 <BLANKLINE>
113 <BLANKLINE>
114 ipdb> pdef example_function
114 ipdb> pdef example_function
115 example_function(x, y, z='hello')
115 example_function(x, y, z='hello')
116 ipdb> pdoc ExampleClass
116 ipdb> pdoc ExampleClass
117 Class Docstring:
117 Class Docstring:
118 Docstring for ExampleClass.
118 Docstring for ExampleClass.
119 Constructor Docstring:
119 Init Docstring:
120 Docstring for ExampleClass.__init__
120 Docstring for ExampleClass.__init__
121 ipdb> pinfo a
121 ipdb> pinfo a
122 Type: ExampleClass
122 Type: ExampleClass
123 String Form:ExampleClass()
123 String Form: ExampleClass()
124 Namespace: Local...
124 Namespace: Local...
125 Docstring: Docstring for ExampleClass.
125 Docstring: Docstring for ExampleClass.
126 Constructor Docstring:Docstring for ExampleClass.__init__
126 Init Docstring: Docstring for ExampleClass.__init__
127 ipdb> continue
127 ipdb> continue
128
128
129 Restore previous trace function, e.g. for coverage.py
129 Restore previous trace function, e.g. for coverage.py
130
130
131 >>> sys.settrace(old_trace)
131 >>> sys.settrace(old_trace)
132 '''
132 '''
133
133
134 def test_ipdb_magics2():
134 def test_ipdb_magics2():
135 '''Test ipdb with a very short function.
135 '''Test ipdb with a very short function.
136
136
137 >>> old_trace = sys.gettrace()
137 >>> old_trace = sys.gettrace()
138
138
139 >>> def bar():
139 >>> def bar():
140 ... pass
140 ... pass
141
141
142 Run ipdb.
142 Run ipdb.
143
143
144 >>> with PdbTestInput([
144 >>> with PdbTestInput([
145 ... 'continue',
145 ... 'continue',
146 ... ]):
146 ... ]):
147 ... debugger.Pdb().runcall(bar)
147 ... debugger.Pdb().runcall(bar)
148 > <doctest ...>(2)bar()
148 > <doctest ...>(2)bar()
149 1 def bar():
149 1 def bar():
150 ----> 2 pass
150 ----> 2 pass
151 <BLANKLINE>
151 <BLANKLINE>
152 ipdb> continue
152 ipdb> continue
153
153
154 Restore previous trace function, e.g. for coverage.py
154 Restore previous trace function, e.g. for coverage.py
155
155
156 >>> sys.settrace(old_trace)
156 >>> sys.settrace(old_trace)
157 '''
157 '''
@@ -1,325 +1,325 b''
1 """Tests for the object inspection functionality.
1 """Tests for the object inspection functionality.
2 """
2 """
3 #-----------------------------------------------------------------------------
3 #-----------------------------------------------------------------------------
4 # Copyright (C) 2010-2011 The IPython Development Team.
4 # Copyright (C) 2010-2011 The IPython Development Team.
5 #
5 #
6 # Distributed under the terms of the BSD License.
6 # Distributed under the terms of the BSD License.
7 #
7 #
8 # The full license is in the file COPYING.txt, distributed with this software.
8 # The full license is in the file COPYING.txt, distributed with this software.
9 #-----------------------------------------------------------------------------
9 #-----------------------------------------------------------------------------
10
10
11 #-----------------------------------------------------------------------------
11 #-----------------------------------------------------------------------------
12 # Imports
12 # Imports
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14 from __future__ import print_function
14 from __future__ import print_function
15
15
16 # Stdlib imports
16 # Stdlib imports
17 import os
17 import os
18 import re
18 import re
19
19
20 # Third-party imports
20 # Third-party imports
21 import nose.tools as nt
21 import nose.tools as nt
22
22
23 # Our own imports
23 # Our own imports
24 from .. import oinspect
24 from .. import oinspect
25 from IPython.core.magic import (Magics, magics_class, line_magic,
25 from IPython.core.magic import (Magics, magics_class, line_magic,
26 cell_magic, line_cell_magic,
26 cell_magic, line_cell_magic,
27 register_line_magic, register_cell_magic,
27 register_line_magic, register_cell_magic,
28 register_line_cell_magic)
28 register_line_cell_magic)
29 from IPython.external.decorator import decorator
29 from IPython.external.decorator import decorator
30 from IPython.testing.decorators import skipif
30 from IPython.testing.decorators import skipif
31 from IPython.utils import py3compat
31 from IPython.utils import py3compat
32
32
33
33
34 #-----------------------------------------------------------------------------
34 #-----------------------------------------------------------------------------
35 # Globals and constants
35 # Globals and constants
36 #-----------------------------------------------------------------------------
36 #-----------------------------------------------------------------------------
37
37
38 inspector = oinspect.Inspector()
38 inspector = oinspect.Inspector()
39 ip = get_ipython()
39 ip = get_ipython()
40
40
41 #-----------------------------------------------------------------------------
41 #-----------------------------------------------------------------------------
42 # Local utilities
42 # Local utilities
43 #-----------------------------------------------------------------------------
43 #-----------------------------------------------------------------------------
44
44
45 # WARNING: since this test checks the line number where a function is
45 # WARNING: since this test checks the line number where a function is
46 # defined, if any code is inserted above, the following line will need to be
46 # defined, if any code is inserted above, the following line will need to be
47 # updated. Do NOT insert any whitespace between the next line and the function
47 # updated. Do NOT insert any whitespace between the next line and the function
48 # definition below.
48 # definition below.
49 THIS_LINE_NUMBER = 49 # Put here the actual number of this line
49 THIS_LINE_NUMBER = 49 # Put here the actual number of this line
50 def test_find_source_lines():
50 def test_find_source_lines():
51 nt.assert_equal(oinspect.find_source_lines(test_find_source_lines),
51 nt.assert_equal(oinspect.find_source_lines(test_find_source_lines),
52 THIS_LINE_NUMBER+1)
52 THIS_LINE_NUMBER+1)
53
53
54
54
55 # A couple of utilities to ensure these tests work the same from a source or a
55 # A couple of utilities to ensure these tests work the same from a source or a
56 # binary install
56 # binary install
57 def pyfile(fname):
57 def pyfile(fname):
58 return os.path.normcase(re.sub('.py[co]$', '.py', fname))
58 return os.path.normcase(re.sub('.py[co]$', '.py', fname))
59
59
60
60
61 def match_pyfiles(f1, f2):
61 def match_pyfiles(f1, f2):
62 nt.assert_equal(pyfile(f1), pyfile(f2))
62 nt.assert_equal(pyfile(f1), pyfile(f2))
63
63
64
64
65 def test_find_file():
65 def test_find_file():
66 match_pyfiles(oinspect.find_file(test_find_file), os.path.abspath(__file__))
66 match_pyfiles(oinspect.find_file(test_find_file), os.path.abspath(__file__))
67
67
68
68
69 def test_find_file_decorated1():
69 def test_find_file_decorated1():
70
70
71 @decorator
71 @decorator
72 def noop1(f):
72 def noop1(f):
73 def wrapper():
73 def wrapper():
74 return f(*a, **kw)
74 return f(*a, **kw)
75 return wrapper
75 return wrapper
76
76
77 @noop1
77 @noop1
78 def f(x):
78 def f(x):
79 "My docstring"
79 "My docstring"
80
80
81 match_pyfiles(oinspect.find_file(f), os.path.abspath(__file__))
81 match_pyfiles(oinspect.find_file(f), os.path.abspath(__file__))
82 nt.assert_equal(f.__doc__, "My docstring")
82 nt.assert_equal(f.__doc__, "My docstring")
83
83
84
84
85 def test_find_file_decorated2():
85 def test_find_file_decorated2():
86
86
87 @decorator
87 @decorator
88 def noop2(f, *a, **kw):
88 def noop2(f, *a, **kw):
89 return f(*a, **kw)
89 return f(*a, **kw)
90
90
91 @noop2
91 @noop2
92 def f(x):
92 def f(x):
93 "My docstring 2"
93 "My docstring 2"
94
94
95 match_pyfiles(oinspect.find_file(f), os.path.abspath(__file__))
95 match_pyfiles(oinspect.find_file(f), os.path.abspath(__file__))
96 nt.assert_equal(f.__doc__, "My docstring 2")
96 nt.assert_equal(f.__doc__, "My docstring 2")
97
97
98
98
99 def test_find_file_magic():
99 def test_find_file_magic():
100 run = ip.find_line_magic('run')
100 run = ip.find_line_magic('run')
101 nt.assert_not_equal(oinspect.find_file(run), None)
101 nt.assert_not_equal(oinspect.find_file(run), None)
102
102
103
103
104 # A few generic objects we can then inspect in the tests below
104 # A few generic objects we can then inspect in the tests below
105
105
106 class Call(object):
106 class Call(object):
107 """This is the class docstring."""
107 """This is the class docstring."""
108
108
109 def __init__(self, x, y=1):
109 def __init__(self, x, y=1):
110 """This is the constructor docstring."""
110 """This is the constructor docstring."""
111
111
112 def __call__(self, *a, **kw):
112 def __call__(self, *a, **kw):
113 """This is the call docstring."""
113 """This is the call docstring."""
114
114
115 def method(self, x, z=2):
115 def method(self, x, z=2):
116 """Some method's docstring"""
116 """Some method's docstring"""
117
117
118 class SimpleClass(object):
118 class SimpleClass(object):
119 def method(self, x, z=2):
119 def method(self, x, z=2):
120 """Some method's docstring"""
120 """Some method's docstring"""
121
121
122
122
123 class OldStyle:
123 class OldStyle:
124 """An old-style class for testing."""
124 """An old-style class for testing."""
125 pass
125 pass
126
126
127
127
128 def f(x, y=2, *a, **kw):
128 def f(x, y=2, *a, **kw):
129 """A simple function."""
129 """A simple function."""
130
130
131
131
132 def g(y, z=3, *a, **kw):
132 def g(y, z=3, *a, **kw):
133 pass # no docstring
133 pass # no docstring
134
134
135
135
136 @register_line_magic
136 @register_line_magic
137 def lmagic(line):
137 def lmagic(line):
138 "A line magic"
138 "A line magic"
139
139
140
140
141 @register_cell_magic
141 @register_cell_magic
142 def cmagic(line, cell):
142 def cmagic(line, cell):
143 "A cell magic"
143 "A cell magic"
144
144
145
145
146 @register_line_cell_magic
146 @register_line_cell_magic
147 def lcmagic(line, cell=None):
147 def lcmagic(line, cell=None):
148 "A line/cell magic"
148 "A line/cell magic"
149
149
150
150
151 @magics_class
151 @magics_class
152 class SimpleMagics(Magics):
152 class SimpleMagics(Magics):
153 @line_magic
153 @line_magic
154 def Clmagic(self, cline):
154 def Clmagic(self, cline):
155 "A class-based line magic"
155 "A class-based line magic"
156
156
157 @cell_magic
157 @cell_magic
158 def Ccmagic(self, cline, ccell):
158 def Ccmagic(self, cline, ccell):
159 "A class-based cell magic"
159 "A class-based cell magic"
160
160
161 @line_cell_magic
161 @line_cell_magic
162 def Clcmagic(self, cline, ccell=None):
162 def Clcmagic(self, cline, ccell=None):
163 "A class-based line/cell magic"
163 "A class-based line/cell magic"
164
164
165
165
166 class Awkward(object):
166 class Awkward(object):
167 def __getattr__(self, name):
167 def __getattr__(self, name):
168 raise Exception(name)
168 raise Exception(name)
169
169
170
170
171 def check_calltip(obj, name, call, docstring):
171 def check_calltip(obj, name, call, docstring):
172 """Generic check pattern all calltip tests will use"""
172 """Generic check pattern all calltip tests will use"""
173 info = inspector.info(obj, name)
173 info = inspector.info(obj, name)
174 call_line, ds = oinspect.call_tip(info)
174 call_line, ds = oinspect.call_tip(info)
175 nt.assert_equal(call_line, call)
175 nt.assert_equal(call_line, call)
176 nt.assert_equal(ds, docstring)
176 nt.assert_equal(ds, docstring)
177
177
178 #-----------------------------------------------------------------------------
178 #-----------------------------------------------------------------------------
179 # Tests
179 # Tests
180 #-----------------------------------------------------------------------------
180 #-----------------------------------------------------------------------------
181
181
182 def test_calltip_class():
182 def test_calltip_class():
183 check_calltip(Call, 'Call', 'Call(x, y=1)', Call.__init__.__doc__)
183 check_calltip(Call, 'Call', 'Call(x, y=1)', Call.__init__.__doc__)
184
184
185
185
186 def test_calltip_instance():
186 def test_calltip_instance():
187 c = Call(1)
187 c = Call(1)
188 check_calltip(c, 'c', 'c(*a, **kw)', c.__call__.__doc__)
188 check_calltip(c, 'c', 'c(*a, **kw)', c.__call__.__doc__)
189
189
190
190
191 def test_calltip_method():
191 def test_calltip_method():
192 c = Call(1)
192 c = Call(1)
193 check_calltip(c.method, 'c.method', 'c.method(x, z=2)', c.method.__doc__)
193 check_calltip(c.method, 'c.method', 'c.method(x, z=2)', c.method.__doc__)
194
194
195
195
196 def test_calltip_function():
196 def test_calltip_function():
197 check_calltip(f, 'f', 'f(x, y=2, *a, **kw)', f.__doc__)
197 check_calltip(f, 'f', 'f(x, y=2, *a, **kw)', f.__doc__)
198
198
199
199
200 def test_calltip_function2():
200 def test_calltip_function2():
201 check_calltip(g, 'g', 'g(y, z=3, *a, **kw)', '<no docstring>')
201 check_calltip(g, 'g', 'g(y, z=3, *a, **kw)', '<no docstring>')
202
202
203
203
204 def test_calltip_builtin():
204 def test_calltip_builtin():
205 check_calltip(sum, 'sum', None, sum.__doc__)
205 check_calltip(sum, 'sum', None, sum.__doc__)
206
206
207
207
208 def test_calltip_line_magic():
208 def test_calltip_line_magic():
209 check_calltip(lmagic, 'lmagic', 'lmagic(line)', "A line magic")
209 check_calltip(lmagic, 'lmagic', 'lmagic(line)', "A line magic")
210
210
211
211
212 def test_calltip_cell_magic():
212 def test_calltip_cell_magic():
213 check_calltip(cmagic, 'cmagic', 'cmagic(line, cell)', "A cell magic")
213 check_calltip(cmagic, 'cmagic', 'cmagic(line, cell)', "A cell magic")
214
214
215
215
216 def test_calltip_line_cell_magic():
216 def test_calltip_line_cell_magic():
217 check_calltip(lcmagic, 'lcmagic', 'lcmagic(line, cell=None)',
217 check_calltip(lcmagic, 'lcmagic', 'lcmagic(line, cell=None)',
218 "A line/cell magic")
218 "A line/cell magic")
219
219
220
220
221 def test_class_magics():
221 def test_class_magics():
222 cm = SimpleMagics(ip)
222 cm = SimpleMagics(ip)
223 ip.register_magics(cm)
223 ip.register_magics(cm)
224 check_calltip(cm.Clmagic, 'Clmagic', 'Clmagic(cline)',
224 check_calltip(cm.Clmagic, 'Clmagic', 'Clmagic(cline)',
225 "A class-based line magic")
225 "A class-based line magic")
226 check_calltip(cm.Ccmagic, 'Ccmagic', 'Ccmagic(cline, ccell)',
226 check_calltip(cm.Ccmagic, 'Ccmagic', 'Ccmagic(cline, ccell)',
227 "A class-based cell magic")
227 "A class-based cell magic")
228 check_calltip(cm.Clcmagic, 'Clcmagic', 'Clcmagic(cline, ccell=None)',
228 check_calltip(cm.Clcmagic, 'Clcmagic', 'Clcmagic(cline, ccell=None)',
229 "A class-based line/cell magic")
229 "A class-based line/cell magic")
230
230
231
231
232 def test_info():
232 def test_info():
233 "Check that Inspector.info fills out various fields as expected."
233 "Check that Inspector.info fills out various fields as expected."
234 i = inspector.info(Call, oname='Call')
234 i = inspector.info(Call, oname='Call')
235 nt.assert_equal(i['type_name'], 'type')
235 nt.assert_equal(i['type_name'], 'type')
236 expted_class = str(type(type)) # <class 'type'> (Python 3) or <type 'type'>
236 expted_class = str(type(type)) # <class 'type'> (Python 3) or <type 'type'>
237 nt.assert_equal(i['base_class'], expted_class)
237 nt.assert_equal(i['base_class'], expted_class)
238 nt.assert_equal(i['string_form'], "<class 'IPython.core.tests.test_oinspect.Call'>")
238 nt.assert_equal(i['string_form'], "<class 'IPython.core.tests.test_oinspect.Call'>")
239 fname = __file__
239 fname = __file__
240 if fname.endswith(".pyc"):
240 if fname.endswith(".pyc"):
241 fname = fname[:-1]
241 fname = fname[:-1]
242 # case-insensitive comparison needed on some filesystems
242 # case-insensitive comparison needed on some filesystems
243 # e.g. Windows:
243 # e.g. Windows:
244 nt.assert_equal(i['file'].lower(), fname.lower())
244 nt.assert_equal(i['file'].lower(), fname.lower())
245 nt.assert_equal(i['definition'], 'Call(self, *a, **kw)\n')
245 nt.assert_equal(i['definition'], None)
246 nt.assert_equal(i['docstring'], Call.__doc__)
246 nt.assert_equal(i['docstring'], Call.__doc__)
247 nt.assert_equal(i['source'], None)
247 nt.assert_equal(i['source'], None)
248 nt.assert_true(i['isclass'])
248 nt.assert_true(i['isclass'])
249 nt.assert_equal(i['init_definition'], "Call(self, x, y=1)\n")
249 nt.assert_equal(i['init_definition'], "Call(self, x, y=1)\n")
250 nt.assert_equal(i['init_docstring'], Call.__init__.__doc__)
250 nt.assert_equal(i['init_docstring'], Call.__init__.__doc__)
251
251
252 i = inspector.info(Call, detail_level=1)
252 i = inspector.info(Call, detail_level=1)
253 nt.assert_not_equal(i['source'], None)
253 nt.assert_not_equal(i['source'], None)
254 nt.assert_equal(i['docstring'], None)
254 nt.assert_equal(i['docstring'], None)
255
255
256 c = Call(1)
256 c = Call(1)
257 c.__doc__ = "Modified instance docstring"
257 c.__doc__ = "Modified instance docstring"
258 i = inspector.info(c)
258 i = inspector.info(c)
259 nt.assert_equal(i['type_name'], 'Call')
259 nt.assert_equal(i['type_name'], 'Call')
260 nt.assert_equal(i['docstring'], "Modified instance docstring")
260 nt.assert_equal(i['docstring'], "Modified instance docstring")
261 nt.assert_equal(i['class_docstring'], Call.__doc__)
261 nt.assert_equal(i['class_docstring'], Call.__doc__)
262 nt.assert_equal(i['init_docstring'], Call.__init__.__doc__)
262 nt.assert_equal(i['init_docstring'], Call.__init__.__doc__)
263 nt.assert_equal(i['call_docstring'], c.__call__.__doc__)
263 nt.assert_equal(i['call_docstring'], Call.__call__.__doc__)
264
264
265 # Test old-style classes, which for example may not have an __init__ method.
265 # Test old-style classes, which for example may not have an __init__ method.
266 if not py3compat.PY3:
266 if not py3compat.PY3:
267 i = inspector.info(OldStyle)
267 i = inspector.info(OldStyle)
268 nt.assert_equal(i['type_name'], 'classobj')
268 nt.assert_equal(i['type_name'], 'classobj')
269
269
270 i = inspector.info(OldStyle())
270 i = inspector.info(OldStyle())
271 nt.assert_equal(i['type_name'], 'instance')
271 nt.assert_equal(i['type_name'], 'instance')
272 nt.assert_equal(i['docstring'], OldStyle.__doc__)
272 nt.assert_equal(i['docstring'], OldStyle.__doc__)
273
273
274 def test_info_awkward():
274 def test_info_awkward():
275 # Just test that this doesn't throw an error.
275 # Just test that this doesn't throw an error.
276 i = inspector.info(Awkward())
276 i = inspector.info(Awkward())
277
277
278 def test_calldef_none():
278 def test_calldef_none():
279 # We should ignore __call__ for all of these.
279 # We should ignore __call__ for all of these.
280 for obj in [f, SimpleClass().method, any, str.upper]:
280 for obj in [f, SimpleClass().method, any, str.upper]:
281 print(obj)
281 print(obj)
282 i = inspector.info(obj)
282 i = inspector.info(obj)
283 nt.assert_is(i['call_def'], None)
283 nt.assert_is(i['call_def'], None)
284
284
285 if py3compat.PY3:
285 if py3compat.PY3:
286 exec("def f_kwarg(pos, *, kwonly): pass")
286 exec("def f_kwarg(pos, *, kwonly): pass")
287
287
288 @skipif(not py3compat.PY3)
288 @skipif(not py3compat.PY3)
289 def test_definition_kwonlyargs():
289 def test_definition_kwonlyargs():
290 i = inspector.info(f_kwarg, oname='f_kwarg') # analysis:ignore
290 i = inspector.info(f_kwarg, oname='f_kwarg') # analysis:ignore
291 nt.assert_equal(i['definition'], "f_kwarg(pos, *, kwonly)\n")
291 nt.assert_equal(i['definition'], "f_kwarg(pos, *, kwonly)\n")
292
292
293 def test_getdoc():
293 def test_getdoc():
294 class A(object):
294 class A(object):
295 """standard docstring"""
295 """standard docstring"""
296 pass
296 pass
297
297
298 class B(object):
298 class B(object):
299 """standard docstring"""
299 """standard docstring"""
300 def getdoc(self):
300 def getdoc(self):
301 return "custom docstring"
301 return "custom docstring"
302
302
303 class C(object):
303 class C(object):
304 """standard docstring"""
304 """standard docstring"""
305 def getdoc(self):
305 def getdoc(self):
306 return None
306 return None
307
307
308 a = A()
308 a = A()
309 b = B()
309 b = B()
310 c = C()
310 c = C()
311
311
312 nt.assert_equal(oinspect.getdoc(a), "standard docstring")
312 nt.assert_equal(oinspect.getdoc(a), "standard docstring")
313 nt.assert_equal(oinspect.getdoc(b), "custom docstring")
313 nt.assert_equal(oinspect.getdoc(b), "custom docstring")
314 nt.assert_equal(oinspect.getdoc(c), "standard docstring")
314 nt.assert_equal(oinspect.getdoc(c), "standard docstring")
315
315
316 def test_pdef():
316 def test_pdef():
317 # See gh-1914
317 # See gh-1914
318 def foo(): pass
318 def foo(): pass
319 inspector.pdef(foo, 'foo')
319 inspector.pdef(foo, 'foo')
320
320
321 def test_pinfo_nonascii():
321 def test_pinfo_nonascii():
322 # See gh-1177
322 # See gh-1177
323 from . import nonascii2
323 from . import nonascii2
324 ip.user_ns['nonascii2'] = nonascii2
324 ip.user_ns['nonascii2'] = nonascii2
325 ip._inspect('pinfo', 'nonascii2', detail_level=1)
325 ip._inspect('pinfo', 'nonascii2', detail_level=1)
General Comments 0
You need to be logged in to leave comments. Login now