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