##// END OF EJS Templates
Fixes in ?? introspection for new-style classes, as well as closing an old bug on traceback computations that appears occasionally
fperez -
Show More
@@ -6,7 +6,7 b' Uses syntax highlighting for presenting the various information elements.'
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 $Id: OInspect.py 2463 2007-06-27 22:51:16Z vivainio $
9 $Id: OInspect.py 2480 2007-07-06 19:33:43Z fperez $
10 """
10 """
11
11
12 #*****************************************************************************
12 #*****************************************************************************
@@ -150,7 +150,7 b' def getsource(obj,is_binary=False):'
150
150
151 - is_binary: whether the object is known to come from a binary source.
151 - is_binary: whether the object is known to come from a binary source.
152 This implementation will skip returning any output for binary objects, but
152 This implementation will skip returning any output for binary objects, but
153 custom extractors may know how to meaninfully process them."""
153 custom extractors may know how to meaningfully process them."""
154
154
155 if is_binary:
155 if is_binary:
156 return None
156 return None
@@ -234,10 +234,12 b' class Inspector:'
234 return
234 return
235
235
236 header = ''
236 header = ''
237 if type(obj) is types.ClassType:
237
238 if inspect.isclass(obj):
238 header = self.__head('Class constructor information:\n')
239 header = self.__head('Class constructor information:\n')
239 obj = obj.__init__
240 obj = obj.__init__
240 elif type(obj) is types.InstanceType:
241 elif type(obj) is types.InstanceType or \
242 isinstance(obj,object):
241 obj = obj.__call__
243 obj = obj.__call__
242
244
243 output = self.__getdef(obj,oname)
245 output = self.__getdef(obj,oname)
@@ -252,18 +254,19 b' class Inspector:'
252 Optional:
254 Optional:
253 -formatter: a function to run the docstring through for specially
255 -formatter: a function to run the docstring through for specially
254 formatted docstrings."""
256 formatted docstrings."""
255
257
256 head = self.__head # so that itpl can find it even if private
258 head = self.__head # so that itpl can find it even if private
257 ds = getdoc(obj)
259 ds = getdoc(obj)
258 if formatter:
260 if formatter:
259 ds = formatter(ds)
261 ds = formatter(ds)
260 if type(obj) is types.ClassType:
262 if inspect.isclass(obj):
261 init_ds = getdoc(obj.__init__)
263 init_ds = getdoc(obj.__init__)
262 output = itpl('$head("Class Docstring:")\n'
264 output = itpl('$head("Class Docstring:")\n'
263 '$indent(ds)\n'
265 '$indent(ds)\n'
264 '$head("Constructor Docstring"):\n'
266 '$head("Constructor Docstring"):\n'
265 '$indent(init_ds)')
267 '$indent(init_ds)')
266 elif type(obj) is types.InstanceType and hasattr(obj,'__call__'):
268 elif (type(obj) is types.InstanceType or isinstance(obj,object)) \
269 and hasattr(obj,'__call__'):
267 call_ds = getdoc(obj.__call__)
270 call_ds = getdoc(obj.__call__)
268 if call_ds:
271 if call_ds:
269 output = itpl('$head("Class Docstring:")\n$indent(ds)\n'
272 output = itpl('$head("Class Docstring:")\n$indent(ds)\n'
@@ -438,7 +441,7 b' class Inspector:'
438 + indent(ds))
441 + indent(ds))
439
442
440 # Constructor docstring for classes
443 # Constructor docstring for classes
441 if obj_type is types.ClassType:
444 if inspect.isclass(obj):
442 # reconstruct the function definition and print it:
445 # reconstruct the function definition and print it:
443 try:
446 try:
444 obj_init = obj.__init__
447 obj_init = obj.__init__
@@ -455,7 +458,8 b' class Inspector:'
455 if init_ds:
458 if init_ds:
456 out.writeln(header('Docstring:\n') + indent(init_ds))
459 out.writeln(header('Docstring:\n') + indent(init_ds))
457 # and class docstring for instances:
460 # and class docstring for instances:
458 elif obj_type is types.InstanceType:
461 elif obj_type is types.InstanceType or \
462 isinstance(obj,object):
459
463
460 # First, check whether the instance docstring is identical to the
464 # First, check whether the instance docstring is identical to the
461 # class one, and print it separately if they don't coincide. In
465 # class one, and print it separately if they don't coincide. In
@@ -60,7 +60,7 b' You can implement other color schemes easily, the syntax is fairly'
60 self-explanatory. Please send back new schemes you develop to the author for
60 self-explanatory. Please send back new schemes you develop to the author for
61 possible inclusion in future releases.
61 possible inclusion in future releases.
62
62
63 $Id: ultraTB.py 2419 2007-06-01 07:31:42Z fperez $"""
63 $Id: ultraTB.py 2480 2007-07-06 19:33:43Z fperez $"""
64
64
65 #*****************************************************************************
65 #*****************************************************************************
66 # Copyright (C) 2001 Nathaniel Gray <n8gray@caltech.edu>
66 # Copyright (C) 2001 Nathaniel Gray <n8gray@caltech.edu>
@@ -81,6 +81,7 b' import keyword'
81 import linecache
81 import linecache
82 import os
82 import os
83 import pydoc
83 import pydoc
84 import re
84 import string
85 import string
85 import sys
86 import sys
86 import time
87 import time
@@ -88,6 +89,11 b' import tokenize'
88 import traceback
89 import traceback
89 import types
90 import types
90
91
92 # For purposes of monkeypatching inspect to fix a bug in it.
93 from inspect import getsourcefile, getfile, getmodule,\
94 ismodule, isclass, ismethod, isfunction, istraceback, isframe, iscode
95
96
91 # IPython's own modules
97 # IPython's own modules
92 # Modified pdb which doesn't damage IPython's readline handling
98 # Modified pdb which doesn't damage IPython's readline handling
93 from IPython import Debugger, PyColorize
99 from IPython import Debugger, PyColorize
@@ -117,6 +123,79 b' def inspect_error():'
117 error('Internal Python error in the inspect module.\n'
123 error('Internal Python error in the inspect module.\n'
118 'Below is the traceback from this internal error.\n')
124 'Below is the traceback from this internal error.\n')
119
125
126
127 def findsource(object):
128 """Return the entire source file and starting line number for an object.
129
130 The argument may be a module, class, method, function, traceback, frame,
131 or code object. The source code is returned as a list of all the lines
132 in the file and the line number indexes a line in that list. An IOError
133 is raised if the source code cannot be retrieved.
134
135 FIXED version with which we monkeypatch the stdlib to work around a bug."""
136
137 file = getsourcefile(object) or getfile(object)
138 module = getmodule(object, file)
139 if module:
140 lines = linecache.getlines(file, module.__dict__)
141 else:
142 lines = linecache.getlines(file)
143 if not lines:
144 raise IOError('could not get source code')
145
146 if ismodule(object):
147 return lines, 0
148
149 if isclass(object):
150 name = object.__name__
151 pat = re.compile(r'^(\s*)class\s*' + name + r'\b')
152 # make some effort to find the best matching class definition:
153 # use the one with the least indentation, which is the one
154 # that's most probably not inside a function definition.
155 candidates = []
156 for i in range(len(lines)):
157 match = pat.match(lines[i])
158 if match:
159 # if it's at toplevel, it's already the best one
160 if lines[i][0] == 'c':
161 return lines, i
162 # else add whitespace to candidate list
163 candidates.append((match.group(1), i))
164 if candidates:
165 # this will sort by whitespace, and by line number,
166 # less whitespace first
167 candidates.sort()
168 return lines, candidates[0][1]
169 else:
170 raise IOError('could not find class definition')
171
172 if ismethod(object):
173 object = object.im_func
174 if isfunction(object):
175 object = object.func_code
176 if istraceback(object):
177 object = object.tb_frame
178 if isframe(object):
179 object = object.f_code
180 if iscode(object):
181 if not hasattr(object, 'co_firstlineno'):
182 raise IOError('could not find function definition')
183 pat = re.compile(r'^(\s*def\s)|(.*(?<!\w)lambda(:|\s))|^(\s*@)')
184 pmatch = pat.match
185 # fperez - fix: sometimes, co_firstlineno can give a number larger than
186 # the length of lines, which causes an error. Safeguard against that.
187 lnum = min(object.co_firstlineno,len(lines))-1
188 while lnum > 0:
189 if pmatch(lines[lnum]): break
190 lnum -= 1
191
192 return lines, lnum
193 raise IOError('could not find code object')
194
195 # Monkeypatch inspect to apply our bugfix. This code only works with py25
196 if sys.version_info[:2] >= (2,5):
197 inspect.findsource = findsource
198
120 def _fixed_getinnerframes(etb, context=1,tb_offset=0):
199 def _fixed_getinnerframes(etb, context=1,tb_offset=0):
121 import linecache
200 import linecache
122 LNUM_POS, LINES_POS, INDEX_POS = 2, 4, 5
201 LNUM_POS, LINES_POS, INDEX_POS = 2, 4, 5
@@ -1,3 +1,8 b''
1 2007-07-06 Fernando Perez <Fernando.Perez@colorado.edu>
2
3 * IPython/OInspect.py (Inspector.pinfo): Add support for new-style
4 classes in various inspector functions.
5
1 2007-06-28 Ville Vainio <vivainio@gmail.com>
6 2007-06-28 Ville Vainio <vivainio@gmail.com>
2
7
3 * shadowns.py, iplib.py, ipapi.py, OInspect.py:
8 * shadowns.py, iplib.py, ipapi.py, OInspect.py:
@@ -14,6 +19,11 b''
14
19
15 * New generic inspect_object, called on obj? and obj??
20 * New generic inspect_object, called on obj? and obj??
16
21
22 2007-06-15 Fernando Perez <Fernando.Perez@colorado.edu>
23
24 * IPython/ultraTB.py (findsource): fix a problem with
25 inspect.getfile that can cause crashes during traceback construction.
26
17 2007-06-14 Ville Vainio <vivainio@gmail.com>
27 2007-06-14 Ville Vainio <vivainio@gmail.com>
18
28
19 * iplib.py (handle_auto): Try to use ascii for printing "--->"
29 * iplib.py (handle_auto): Try to use ascii for printing "--->"
General Comments 0
You need to be logged in to leave comments. Login now