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