Commit 8bb090b0 authored by Stefan Behnel's avatar Stefan Behnel

make libcython.py Py2/3 compatible to allows its immediate usage from both...

make libcython.py Py2/3 compatible to allows its immediate usage from both versions (and clean it up a little)
parent f4a2df85
......@@ -2,7 +2,7 @@
GDB extension that adds Cython support.
"""
from __future__ import with_statement
from __future__ import print_function
import sys
import textwrap
......@@ -54,6 +54,7 @@ PythonObject = 'PythonObject'
_data_types = dict(CObject=CObject, PythonObject=PythonObject)
_filesystemencoding = sys.getfilesystemencoding() or 'UTF-8'
# decorators
def dont_suppress_errors(function):
......@@ -68,6 +69,7 @@ def dont_suppress_errors(function):
return wrapper
def default_selected_gdb_frame(err=True):
def decorator(function):
@functools.wraps(function)
......@@ -84,6 +86,7 @@ def default_selected_gdb_frame(err=True):
return wrapper
return decorator
def require_cython_frame(function):
@functools.wraps(function)
@require_running_program
......@@ -95,6 +98,7 @@ def require_cython_frame(function):
return function(self, *args, **kwargs)
return wrapper
def dispatch_on_frame(c_command, python_command=None):
def decorator(function):
@functools.wraps(function)
......@@ -115,6 +119,7 @@ def dispatch_on_frame(c_command, python_command=None):
return wrapper
return decorator
def require_running_program(function):
@functools.wraps(function)
def wrapper(*args, **kwargs):
......@@ -152,6 +157,7 @@ class CythonModule(object):
self.lineno_c2cy = {}
self.functions = {}
class CythonVariable(object):
def __init__(self, name, cname, qualified_name, type, lineno):
......@@ -161,6 +167,7 @@ class CythonVariable(object):
self.type = type
self.lineno = int(lineno)
class CythonFunction(CythonVariable):
def __init__(self,
module,
......@@ -297,7 +304,7 @@ class CythonBase(object):
try:
source_desc, lineno = self.get_source_desc(frame)
except NoFunctionNameInFrameError:
print '#%-2d Unknown Frame (compile with -g)' % index
print('#%-2d Unknown Frame (compile with -g)' % index)
return
if not is_c and self.is_python_function(frame):
......@@ -381,10 +388,9 @@ class CythonBase(object):
typename = '(%s) ' % (value.type,)
if max_name_length is None:
print '%s%s = %s%s' % (prefix, name, typename, value)
print('%s%s = %s%s' % (prefix, name, typename, value))
else:
print '%s%-*s = %s%s' % (prefix, max_name_length, name, typename,
value)
print('%s%-*s = %s%s' % (prefix, max_name_length, name, typename, value))
def is_initialized(self, cython_func, local_name):
cyvar = cython_func.locals[local_name]
......@@ -473,6 +479,7 @@ class CyGDBError(gdb.GdbError):
args = args or (self.msg,)
super(CyGDBError, self).__init__(*args)
class NoCythonFunctionInFrameError(CyGDBError):
"""
raised when the user requests the current cython function, which is
......@@ -480,6 +487,7 @@ class NoCythonFunctionInFrameError(CyGDBError):
"""
msg = "Current function is a function cygdb doesn't know about"
class NoFunctionNameInFrameError(NoCythonFunctionInFrameError):
"""
raised when the name of the C function could not be determined
......@@ -509,21 +517,25 @@ class CythonParameter(gdb.Parameter):
__nonzero__ = __bool__ # Python 2
class CompleteUnqualifiedFunctionNames(CythonParameter):
"""
Have 'cy break' complete unqualified function or method names.
"""
class ColorizeSourceCode(CythonParameter):
"""
Tell cygdb whether to colorize source code.
"""
class TerminalBackground(CythonParameter):
"""
Tell cygdb about the user's terminal background (light or dark).
"""
class CythonParameters(object):
"""
Simple container class that might get more functionality in the distant
......@@ -636,7 +648,7 @@ class CyCy(CythonCommand):
cy_eval = CyEval('cy_eval'),
)
for command_name, command in commands.iteritems():
for command_name, command in commands.items():
command.cy = self
setattr(self, command_name, command)
......@@ -672,9 +684,8 @@ class CyImport(CythonCommand):
for arg in string_to_argv(args):
try:
f = open(arg)
except OSError, e:
raise gdb.GdbError('Unable to open file %r: %s' %
(args, e.args[1]))
except OSError as e:
raise gdb.GdbError('Unable to open file %r: %s' % (args, e.args[1]))
t = etree.parse(f)
......@@ -782,9 +793,9 @@ class CyBreak(CythonCommand):
if len(funcs) > 1:
# multiple functions, let the user pick one
print 'There are multiple such functions:'
print('There are multiple such functions:')
for idx, func in enumerate(funcs):
print '%3d) %s' % (idx, func.qualified_name)
print('%3d) %s' % (idx, func.qualified_name))
while True:
try:
......@@ -804,7 +815,7 @@ class CyBreak(CythonCommand):
break_funcs = [funcs[int(result)]]
break
else:
print 'Not understood...'
print('Not understood...')
else:
break_funcs = [funcs[0]]
......@@ -977,7 +988,7 @@ class CyUp(CythonCommand):
gdb.execute(self._command, to_string=True)
while not self.is_relevant_function(gdb.selected_frame()):
gdb.execute(self._command, to_string=True)
except RuntimeError, e:
except RuntimeError as e:
raise gdb.GdbError(*e.args)
frame = gdb.selected_frame()
......@@ -1020,7 +1031,7 @@ class CySelect(CythonCommand):
try:
gdb.execute('select %d' % (stackdepth - stackno - 1,))
except RuntimeError, e:
except RuntimeError as e:
raise gdb.GdbError(*e.args)
......@@ -1070,7 +1081,7 @@ class CyList(CythonCommand):
sd, lineno = self.get_source_desc()
source = sd.get_source(lineno - 5, lineno + 5, mark_line=lineno,
lex_entire=True)
print source
print(source)
class CyPrint(CythonCommand):
......@@ -1104,7 +1115,8 @@ class CyPrint(CythonCommand):
return []
sortkey = lambda (name, value): name.lower()
sortkey = lambda item: item[0].lower()
class CyLocals(CythonCommand):
"""
......@@ -1157,13 +1169,13 @@ class CyGlobals(CyLocals):
max_name_length = max(max_globals_len, max_globals_dict_len)
seen = set()
print 'Python globals:'
print('Python globals:')
for k, v in sorted(global_python_dict.iteritems(), key=sortkey):
v = v.get_truncated_repr(libpython.MAX_OUTPUT_LEN)
seen.add(k)
print ' %-*s = %s' % (max_name_length, k, v)
print(' %-*s = %s' % (max_name_length, k, v))
print 'C globals:'
print('C globals:')
for name, cyvar in sorted(module_globals.iteritems(), key=sortkey):
if name not in seen:
try:
......@@ -1176,7 +1188,6 @@ class CyGlobals(CyLocals):
max_name_length, ' ')
class EvaluateOrExecuteCodeMixin(object):
"""
Evaluate or execute Python code in a Cython or Python frame. The 'evalcode'
......@@ -1228,7 +1239,6 @@ class EvaluateOrExecuteCodeMixin(object):
raise gdb.GdbError("There is no Cython or Python frame on the stack.")
def _evalcode_cython(self, executor, code, input_type):
with libpython.FetchAndRestoreError():
# get the dict of Cython globals and construct a dict in the
......@@ -1384,6 +1394,7 @@ cython_info = CythonInfo()
cy = CyCy.register()
cython_info.cy = cy
def register_defines():
libpython.source_gdb_script(textwrap.dedent("""\
define cy step
......
......@@ -45,8 +45,6 @@ the type names are known to the debugger
The module also extends gdb with some python-specific commands.
'''
from __future__ import with_statement
import os
import re
import sys
......@@ -60,6 +58,11 @@ import itertools
import gdb
try:
xrange
except NameError:
xrange = range
if sys.version_info[0] < 3:
# I think this is the only way to fix this bug :'(
# http://sourceware.org/bugzilla/show_bug.cgi?id=12285
......@@ -75,18 +78,18 @@ _type_void_ptr = gdb.lookup_type('void').pointer() # void*
SIZEOF_VOID_P = _type_void_ptr.sizeof
Py_TPFLAGS_HEAPTYPE = (1L << 9)
Py_TPFLAGS_HEAPTYPE = (1 << 9)
Py_TPFLAGS_INT_SUBCLASS = (1L << 23)
Py_TPFLAGS_LONG_SUBCLASS = (1L << 24)
Py_TPFLAGS_LIST_SUBCLASS = (1L << 25)
Py_TPFLAGS_TUPLE_SUBCLASS = (1L << 26)
Py_TPFLAGS_STRING_SUBCLASS = (1L << 27)
Py_TPFLAGS_BYTES_SUBCLASS = (1L << 27)
Py_TPFLAGS_UNICODE_SUBCLASS = (1L << 28)
Py_TPFLAGS_DICT_SUBCLASS = (1L << 29)
Py_TPFLAGS_BASE_EXC_SUBCLASS = (1L << 30)
Py_TPFLAGS_TYPE_SUBCLASS = (1L << 31)
Py_TPFLAGS_INT_SUBCLASS = (1 << 23)
Py_TPFLAGS_LONG_SUBCLASS = (1 << 24)
Py_TPFLAGS_LIST_SUBCLASS = (1 << 25)
Py_TPFLAGS_TUPLE_SUBCLASS = (1 << 26)
Py_TPFLAGS_STRING_SUBCLASS = (1 << 27)
Py_TPFLAGS_BYTES_SUBCLASS = (1 << 27)
Py_TPFLAGS_UNICODE_SUBCLASS = (1 << 28)
Py_TPFLAGS_DICT_SUBCLASS = (1 << 29)
Py_TPFLAGS_BASE_EXC_SUBCLASS = (1 << 30)
Py_TPFLAGS_TYPE_SUBCLASS = (1 << 31)
MAX_OUTPUT_LEN = 1024
......@@ -94,6 +97,7 @@ hexdigits = "0123456789abcdef"
ENCODING = locale.getpreferredencoding()
class NullPyObjectPtr(RuntimeError):
pass
......@@ -110,16 +114,18 @@ def safe_range(val):
# threshold in case the data was corrupted
return xrange(safety_limit(val))
def write_unicode(file, text):
# Write a byte or unicode string to file. Unicode strings are encoded to
# ENCODING encoding with 'backslashreplace' error handler to avoid
# UnicodeEncodeError.
if isinstance(text, unicode):
if not isinstance(text, str):
text = text.encode(ENCODING, 'backslashreplace')
file.write(text)
def os_fsencode(filename):
if not isinstance(filename, unicode):
if isinstance(filename, str): # only encode in Py2
return filename
encoding = sys.getfilesystemencoding()
if encoding == 'mbcs':
......@@ -135,9 +141,11 @@ def os_fsencode(filename):
encoded.append(byte)
return ''.join(encoded)
class StringTruncated(RuntimeError):
pass
class TruncatedStringIO(object):
'''Similar to cStringIO, but can truncate the output by raising a
StringTruncated exception'''
......@@ -161,6 +169,7 @@ class TruncatedStringIO(object):
# pretty printer lookup
all_pretty_typenames = set()
class PrettyPrinterTrackerMeta(type):
def __init__(self, name, bases, dict):
......@@ -406,7 +415,7 @@ class PyObjectPtr(object):
p = PyObjectPtr(gdbval)
cls = cls.subclass_from_type(p.type())
return cls(gdbval, cast_to=cls.get_gdb_type())
except RuntimeError, exc:
except RuntimeError as exc:
# Handle any kind of error e.g. NULL ptrs by simply using the base
# class
pass
......@@ -423,6 +432,7 @@ class PyObjectPtr(object):
class PyVarObjectPtr(PyObjectPtr):
_typename = 'PyVarObject'
class ProxyAlreadyVisited(object):
'''
Placeholder proxy to use when protecting against infinite recursion due to
......@@ -467,13 +477,14 @@ class InstanceProxy(object):
def __repr__(self):
if isinstance(self.attrdict, dict):
kwargs = ', '.join(["%s=%r" % (arg, val)
for arg, val in self.attrdict.iteritems()])
return '<%s(%s) at remote 0x%x>' % (self.cl_name,
kwargs, self.address)
kwargs = ', '.join("%s=%r" % (arg, val)
for arg, val in self.attrdict.iteritems())
return '<%s(%s) at remote 0x%x>' % (
self.cl_name, kwargs, self.address)
else:
return '<%s at remote 0x%x>' % (self.cl_name,
self.address)
return '<%s at remote 0x%x>' % (
self.cl_name, self.address)
def _PyObject_VAR_SIZE(typeobj, nitems):
return ( ( typeobj.field('tp_basicsize') +
......@@ -482,6 +493,7 @@ def _PyObject_VAR_SIZE(typeobj, nitems):
) & ~(SIZEOF_VOID_P - 1)
).cast(gdb.lookup_type('size_t'))
class PyTypeObjectPtr(PyObjectPtr):
_typename = 'PyTypeObject'
......@@ -549,12 +561,12 @@ class PyTypeObjectPtr(PyObjectPtr):
except RuntimeError:
tp_name = 'unknown'
out.write('<type %s at remote 0x%x>' % (tp_name,
self.as_address()))
out.write('<type %s at remote 0x%x>' % (tp_name, self.as_address()))
# pyop_attrdict = self.get_attr_dict()
# _write_instance_repr(out, visited,
# self.safe_tp_name(), pyop_attrdict, self.as_address())
class ProxyException(Exception):
def __init__(self, tp_name, args):
self.tp_name = tp_name
......@@ -563,6 +575,7 @@ class ProxyException(Exception):
def __repr__(self):
return '%s%r' % (self.tp_name, self.args)
class PyBaseExceptionObjectPtr(PyObjectPtr):
"""
Class wrapping a gdb.Value that's a PyBaseExceptionObject* i.e. an exception
......@@ -605,17 +618,17 @@ class BuiltInFunctionProxy(object):
def __repr__(self):
return "<built-in function %s>" % self.ml_name
class BuiltInMethodProxy(object):
def __init__(self, ml_name, pyop_m_self):
self.ml_name = ml_name
self.pyop_m_self = pyop_m_self
def __repr__(self):
return ('<built-in method %s of %s object at remote 0x%x>'
% (self.ml_name,
self.pyop_m_self.safe_tp_name(),
return '<built-in method %s of %s object at remote 0x%x>' % (
self.ml_name, self.pyop_m_self.safe_tp_name(),
self.pyop_m_self.as_address())
)
class PyCFunctionObjectPtr(PyObjectPtr):
"""
......@@ -714,6 +727,7 @@ class PyDictObjectPtr(PyObjectPtr):
pyop_value.write_repr(out, visited)
out.write('}')
class PyInstanceObjectPtr(PyObjectPtr):
_typename = 'PyInstanceObject'
......@@ -752,6 +766,7 @@ class PyInstanceObjectPtr(PyObjectPtr):
_write_instance_repr(out, visited,
cl_name, pyop_in_dict, self.as_address())
class PyIntObjectPtr(PyObjectPtr):
_typename = 'PyIntObject'
......@@ -759,6 +774,7 @@ class PyIntObjectPtr(PyObjectPtr):
result = int_from_int(self.field('ob_ival'))
return result
class PyListObjectPtr(PyObjectPtr):
_typename = 'PyListObject'
......@@ -792,6 +808,7 @@ class PyListObjectPtr(PyObjectPtr):
element.write_repr(out, visited)
out.write(']')
class PyLongObjectPtr(PyObjectPtr):
_typename = 'PyLongObject'
......@@ -815,16 +832,16 @@ class PyLongObjectPtr(PyObjectPtr):
'''
ob_size = long(self.field('ob_size'))
if ob_size == 0:
return 0L
return long(0)
ob_digit = self.field('ob_digit')
if gdb.lookup_type('digit').sizeof == 2:
SHIFT = 15L
SHIFT = 15
else:
SHIFT = 30L
SHIFT = 30
digits = [long(ob_digit[i]) * 2**(SHIFT*i)
digits = [ob_digit[i] * (1 << (SHIFT*i))
for i in safe_range(abs(ob_size))]
result = sum(digits)
if ob_size < 0:
......@@ -989,6 +1006,7 @@ class PyFrameObjectPtr(PyObjectPtr):
out.write(')')
class PySetObjectPtr(PyObjectPtr):
_typename = 'PySetObject'
......@@ -1099,12 +1117,14 @@ class PyBytesObjectPtr(PyObjectPtr):
out.write(byte)
out.write(quote)
class PyStringObjectPtr(PyBytesObjectPtr):
_typename = 'PyStringObject'
def write_repr(self, out, visited):
return super(PyStringObjectPtr, self).write_repr(out, visited, py3=False)
class PyTupleObjectPtr(PyObjectPtr):
_typename = 'PyTupleObject'
......@@ -1149,8 +1169,12 @@ def _unichr_is_printable(char):
import unicodedata
return unicodedata.category(char) not in ("C", "Z")
if sys.maxunicode >= 0x10000:
try:
_unichr = unichr
except NameError:
_unichr = chr
else:
# Needed for proper surrogate support if sizeof(Py_UNICODE) is 2 in gdb
def _unichr(x):
......@@ -1161,6 +1185,7 @@ else:
ch2 = 0xDC00 | (x & 0x3FF)
return unichr(ch1) + unichr(ch2)
class PyUnicodeObjectPtr(PyObjectPtr):
_typename = 'PyUnicodeObject'
......@@ -1333,6 +1358,7 @@ class PyUnicodeObjectPtr(PyObjectPtr):
# Be compatible with that.
return unicode(self).encode('UTF-8')
def int_from_int(gdbval):
return int(str(gdbval))
......@@ -1363,6 +1389,7 @@ class PyObjectPtrPrinter:
proxyval = pyop.proxyval(set())
return stringify(proxyval)
def pretty_printer_lookup(gdbval):
type = gdbval.type.unqualified()
if type.code == gdb.TYPE_CODE_PTR:
......@@ -1389,19 +1416,22 @@ that this python file is installed to the same path as the library (or its
/usr/lib/libpython2.6.so.1.0-gdb.py
/usr/lib/debug/usr/lib/libpython2.6.so.1.0.debug-gdb.py
"""
def register (obj):
if obj == None:
def register(obj):
if obj is None:
obj = gdb
# Wire up the pretty-printer
obj.pretty_printers.append(pretty_printer_lookup)
register (gdb.current_objfile ())
register(gdb.current_objfile())
# Unfortunately, the exact API exposed by the gdb module varies somewhat
# from build to build
# See http://bugs.python.org/issue8279?#msg102276
class Frame(object):
'''
Wrapper for gdb.Frame, adding various methods
......@@ -1529,6 +1559,7 @@ class Frame(object):
else:
sys.stdout.write('#%i\n' % self.get_index())
class PyList(gdb.Command):
'''List the current Python source code, if any
......@@ -1547,7 +1578,6 @@ class PyList(gdb.Command):
gdb.COMMAND_FILES,
gdb.COMPLETE_NONE)
def invoke(self, args, from_tty):
import re
......@@ -1565,12 +1595,12 @@ class PyList(gdb.Command):
frame = Frame.get_selected_python_frame()
if not frame:
print 'Unable to locate python frame'
print('Unable to locate python frame')
return
pyop = frame.get_pyop()
if not pyop:
print 'Unable to read information on python frame'
print('Unable to read information on python frame')
return
filename = pyop.filename()
......@@ -1595,10 +1625,10 @@ class PyList(gdb.Command):
linestr = '>' + linestr
sys.stdout.write('%4s %s' % (linestr, line))
# ...and register the command:
PyList()
def move_in_stack(move_up):
'''Move up or down the stack (for the py-up/py-down command)'''
frame = Frame.get_selected_python_frame()
......@@ -1620,9 +1650,10 @@ def move_in_stack(move_up):
frame = iter_frame
if move_up:
print 'Unable to find an older python frame'
print('Unable to find an older python frame')
else:
print 'Unable to find a newer python frame'
print('Unable to find a newer python frame')
class PyUp(gdb.Command):
'Select and print the python stack frame that called this one (if any)'
......@@ -1632,10 +1663,10 @@ class PyUp(gdb.Command):
gdb.COMMAND_STACK,
gdb.COMPLETE_NONE)
def invoke(self, args, from_tty):
move_in_stack(move_up=True)
class PyDown(gdb.Command):
'Select and print the python stack frame called by this one (if any)'
def __init__(self):
......@@ -1644,15 +1675,16 @@ class PyDown(gdb.Command):
gdb.COMMAND_STACK,
gdb.COMPLETE_NONE)
def invoke(self, args, from_tty):
move_in_stack(move_up=False)
# Not all builds of gdb have gdb.Frame.select
if hasattr(gdb.Frame, 'select'):
PyUp()
PyDown()
class PyBacktrace(gdb.Command):
'Display the current python frame and all the frames within its call stack (if any)'
def __init__(self):
......@@ -1671,6 +1703,7 @@ class PyBacktrace(gdb.Command):
PyBacktrace()
class PyPrint(gdb.Command):
'Look up the given python variable name, and print it'
def __init__(self):
......@@ -1679,32 +1712,30 @@ class PyPrint(gdb.Command):
gdb.COMMAND_DATA,
gdb.COMPLETE_NONE)
def invoke(self, args, from_tty):
name = str(args)
frame = Frame.get_selected_python_frame()
if not frame:
print 'Unable to locate python frame'
print('Unable to locate python frame')
return
pyop_frame = frame.get_pyop()
if not pyop_frame:
print 'Unable to read information on python frame'
print('Unable to read information on python frame')
return
pyop_var, scope = pyop_frame.get_var_by_name(name)
if pyop_var:
print ('%s %r = %s'
% (scope,
name,
pyop_var.get_truncated_repr(MAX_OUTPUT_LEN)))
print('%s %r = %s' % (
scope, name, pyop_var.get_truncated_repr(MAX_OUTPUT_LEN)))
else:
print '%r not found' % name
print('%r not found' % name)
PyPrint()
class PyLocals(gdb.Command):
'Look up the given python variable name, and print it'
......@@ -1713,24 +1744,24 @@ class PyLocals(gdb.Command):
frame = Frame.get_selected_python_frame()
if not frame:
print 'Unable to locate python frame'
print('Unable to locate python frame')
return
pyop_frame = frame.get_pyop()
if not pyop_frame:
print 'Unable to read information on python frame'
print('Unable to read information on python frame')
return
namespace = self.get_namespace(pyop_frame)
namespace = [(name.proxyval(set()), val) for name, val in namespace]
if namespace:
name, val = max(namespace, key=lambda (name, val): len(name))
name, val = max(namespace, key=lambda item: len(item[0]))
max_name_length = len(name)
for name, pyop_value in namespace:
value = pyop_value.get_truncated_repr(MAX_OUTPUT_LEN)
print ('%-*s = %s' % (max_name_length, name, value))
print('%-*s = %s' % (max_name_length, name, value))
def get_namespace(self, pyop_frame):
return pyop_frame.iter_locals()
......@@ -1880,6 +1911,7 @@ def get_selected_inferior():
if thread == selected_thread:
return inferior
def source_gdb_script(script_contents, to_string=False):
"""
Source a gdb script with script_contents passed as a string. This is useful
......@@ -1894,6 +1926,7 @@ def source_gdb_script(script_contents, to_string=False):
gdb.execute("source %s" % filename, to_string=to_string)
os.remove(filename)
def register_defines():
source_gdb_script(textwrap.dedent("""\
define py-step
......@@ -1923,6 +1956,7 @@ def stackdepth(frame):
return depth
class ExecutionControlCommandBase(gdb.Command):
"""
Superclass for language specific execution control. Language specific
......@@ -1983,7 +2017,6 @@ class ExecutionControlCommandBase(gdb.Command):
return (filter_output(output_on_halt),
finish_output + filter_output(output_always))
def stopped(self):
return get_selected_inferior().pid == 0
......@@ -1996,22 +2029,22 @@ class ExecutionControlCommandBase(gdb.Command):
output_on_halt, output_always = self.filter_output(result)
if self.stopped():
print output_always
print output_on_halt
print(output_always)
print(output_on_halt)
else:
frame = gdb.selected_frame()
source_line = self.lang_info.get_source_line(frame)
if self.lang_info.is_relevant_function(frame):
raised_exception = self.lang_info.exc_info(frame)
if raised_exception:
print raised_exception
print(raised_exception)
if source_line:
if output_always.rstrip():
print output_always.rstrip()
print source_line
print(output_always.rstrip())
print(source_line)
else:
print result
print(result)
def _finish(self):
"""
......@@ -2181,6 +2214,7 @@ class LanguageInfo(object):
"""
return ()
class PythonInfo(LanguageInfo):
def pyframe(self, frame):
......@@ -2203,7 +2237,7 @@ class PythonInfo(LanguageInfo):
pyframe = self.pyframe(frame)
return '%4d %s' % (pyframe.current_line_num(),
pyframe.current_line().rstrip())
except IOError, e:
except IOError:
return None
def exc_info(self, frame):
......@@ -2216,7 +2250,7 @@ class PythonInfo(LanguageInfo):
if inf_type:
return 'An exception was raised: %s' % (inf_value,)
except (ValueError, RuntimeError), e:
except (ValueError, RuntimeError):
# Could not read the variable tstate or it's memory, it's ok
pass
......@@ -2249,21 +2283,25 @@ class PyStep(ExecutionControlCommandBase, PythonStepperMixin):
def invoke(self, args, from_tty):
self.python_step(stepinto=self.stepinto)
class PyNext(PyStep):
"Step-over Python code."
stepinto = False
class PyFinish(ExecutionControlCommandBase):
"Execute until function returns to a caller."
invoke = ExecutionControlCommandBase.finish
class PyRun(ExecutionControlCommandBase):
"Run the program."
invoke = ExecutionControlCommandBase.run
class PyCont(ExecutionControlCommandBase):
invoke = ExecutionControlCommandBase.cont
......@@ -2283,6 +2321,7 @@ def _pointervalue(gdbval):
# still convert the pointer to an int
return long(gdbval)
def pointervalue(gdbval):
pointer = _pointervalue(gdbval)
try:
......@@ -2296,6 +2335,7 @@ def pointervalue(gdbval):
return pointer
def get_inferior_unicode_postfix():
try:
gdb.parse_and_eval('PyUnicode_FromEncodedObject')
......@@ -2309,6 +2349,7 @@ def get_inferior_unicode_postfix():
else:
return ''
class PythonCodeExecutor(object):
Py_single_input = 256
......@@ -2408,6 +2449,7 @@ class PythonCodeExecutor(object):
return pyobject_return_value
class FetchAndRestoreError(PythonCodeExecutor):
"""
Context manager that fetches the error indicator in the inferior and
......@@ -2478,7 +2520,7 @@ class FixGdbCommand(gdb.Command):
self.fix_gdb()
try:
gdb.execute('%s %s' % (self.actual_command, args))
except RuntimeError, e:
except RuntimeError as e:
raise gdb.GdbError(str(e))
self.fix_gdb()
......@@ -2497,6 +2539,7 @@ def _evalcode_python(executor, code, input_type):
return executor.evalcode(code, input_type, global_dict, local_dict)
class PyExec(gdb.Command):
def readcode(self, expr):
......@@ -2520,8 +2563,7 @@ class PyExec(gdb.Command):
def invoke(self, expr, from_tty):
expr, input_type = self.readcode(expr)
executor = PythonCodeExecutor()
executor.xdecref(_evalcode_python(executor, input_type, global_dict,
local_dict))
executor.xdecref(_evalcode_python(executor, input_type, global_dict, local_dict))
gdb.execute('set breakpoint pending on')
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment