Show More
@@ -83,6 +83,7 b' Inheritance diagram:' | |||
|
83 | 83 | from __future__ import unicode_literals |
|
84 | 84 | from __future__ import print_function |
|
85 | 85 | |
|
86 | import dis | |
|
86 | 87 | import inspect |
|
87 | 88 | import keyword |
|
88 | 89 | import linecache |
@@ -222,21 +223,98 b' def findsource(object):' | |||
|
222 | 223 | raise IOError('could not find code object') |
|
223 | 224 | |
|
224 | 225 | |
|
226 | # This is a patched version of inspect.getargs that applies the (unmerged) | |
|
227 | # patch for http://bugs.python.org/file25269/issue_14611. This fixes | |
|
228 | # https://github.com/ipython/ipython/issues/8205 and | |
|
229 | # https://github.com/ipython/ipython/issues/8293 | |
|
230 | def getargs(co): | |
|
231 | """Get information about the arguments accepted by a code object. | |
|
232 | ||
|
233 | Three things are returned: (args, varargs, varkw), where 'args' is | |
|
234 | a list of argument names (possibly containing nested lists), and | |
|
235 | 'varargs' and 'varkw' are the names of the * and ** arguments or None.""" | |
|
236 | if not iscode(co): | |
|
237 | raise TypeError('{!r} is not a code object'.format(co)) | |
|
238 | ||
|
239 | nargs = co.co_argcount | |
|
240 | names = co.co_varnames | |
|
241 | args = list(names[:nargs]) | |
|
242 | step = 0 | |
|
243 | ||
|
244 | # The following acrobatics are for anonymous (tuple) arguments. | |
|
245 | for i in range(nargs): | |
|
246 | if args[i][:1] in ('', '.'): | |
|
247 | stack, remain, count = [], [], [] | |
|
248 | while step < len(co.co_code): | |
|
249 | op = ord(co.co_code[step]) | |
|
250 | step = step + 1 | |
|
251 | if op >= dis.HAVE_ARGUMENT: | |
|
252 | opname = dis.opname[op] | |
|
253 | value = ord(co.co_code[step]) + ord(co.co_code[step+1])*256 | |
|
254 | step = step + 2 | |
|
255 | if opname in ('UNPACK_TUPLE', 'UNPACK_SEQUENCE'): | |
|
256 | remain.append(value) | |
|
257 | count.append(value) | |
|
258 | elif opname in ('STORE_FAST', 'STORE_DEREF'): | |
|
259 | if op in dis.haslocal: | |
|
260 | stack.append(co.co_varnames[value]) | |
|
261 | elif op in dis.hasfree: | |
|
262 | stack.append((co.co_cellvars + co.co_freevars)[value]) | |
|
263 | # Special case for sublists of length 1: def foo((bar)) | |
|
264 | # doesn't generate the UNPACK_TUPLE bytecode, so if | |
|
265 | # `remain` is empty here, we have such a sublist. | |
|
266 | if not remain: | |
|
267 | stack[0] = [stack[0]] | |
|
268 | break | |
|
269 | else: | |
|
270 | remain[-1] = remain[-1] - 1 | |
|
271 | while remain[-1] == 0: | |
|
272 | remain.pop() | |
|
273 | size = count.pop() | |
|
274 | stack[-size:] = [stack[-size:]] | |
|
275 | if not remain: break | |
|
276 | remain[-1] = remain[-1] - 1 | |
|
277 | if not remain: break | |
|
278 | args[i] = stack[0] | |
|
279 | ||
|
280 | varargs = None | |
|
281 | if co.co_flags & inspect.CO_VARARGS: | |
|
282 | varargs = co.co_varnames[nargs] | |
|
283 | nargs = nargs + 1 | |
|
284 | varkw = None | |
|
285 | if co.co_flags & inspect.CO_VARKEYWORDS: | |
|
286 | varkw = co.co_varnames[nargs] | |
|
287 | return inspect.Arguments(args, varargs, varkw) | |
|
288 | ||
|
289 | ||
|
225 | 290 | # Monkeypatch inspect to apply our bugfix. |
|
226 | 291 | def with_patch_inspect(f): |
|
227 | 292 | """decorator for monkeypatching inspect.findsource""" |
|
228 | 293 | |
|
229 | 294 | def wrapped(*args, **kwargs): |
|
230 | 295 | save_findsource = inspect.findsource |
|
296 | save_getargs = inspect.getargs | |
|
231 | 297 | inspect.findsource = findsource |
|
298 | inspect.getargs = getargs | |
|
232 | 299 | try: |
|
233 | 300 | return f(*args, **kwargs) |
|
234 | 301 | finally: |
|
235 | 302 | inspect.findsource = save_findsource |
|
303 | inspect.getargs = save_getargs | |
|
236 | 304 | |
|
237 | 305 | return wrapped |
|
238 | 306 | |
|
239 | 307 | |
|
308 | if py3compat.PY3: | |
|
309 | fixed_getargvalues = inspect.getargvalues | |
|
310 | else: | |
|
311 | # Fixes for https://github.com/ipython/ipython/issues/8293 | |
|
312 | # and https://github.com/ipython/ipython/issues/8205. | |
|
313 | # The relevant bug is caused by failure to correctly handle anonymous tuple | |
|
314 | # unpacking, which only exists in Python 2. | |
|
315 | fixed_getargvalues = with_patch_inspect(inspect.getargvalues) | |
|
316 | ||
|
317 | ||
|
240 | 318 | def fix_frame_records_filenames(records): |
|
241 | 319 | """Try to fix the filenames in each record from inspect.getinnerframes(). |
|
242 | 320 | |
@@ -744,7 +822,7 b' class VerboseTB(TBTools):' | |||
|
744 | 822 | |
|
745 | 823 | file = py3compat.cast_unicode(file, util_path.fs_encoding) |
|
746 | 824 | link = tpl_link % file |
|
747 |
args, varargs, varkw, locals = |
|
|
825 | args, varargs, varkw, locals = fixed_getargvalues(frame) | |
|
748 | 826 | |
|
749 | 827 | if func == '?': |
|
750 | 828 | call = '' |
General Comments 0
You need to be logged in to leave comments.
Login now