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