python-gdb.py supports method-wrapper
Issue #29367: python-gdb.py now supports also method-wrapper (wrapperobject) objects.
This commit is contained in:
parent
c9473b838a
commit
611083331d
|
@ -3,13 +3,14 @@
|
|||
# The code for testing gdb was adapted from similar work in Unladen Swallow's
|
||||
# Lib/test/test_jit_gdb.py
|
||||
|
||||
import locale
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
import sysconfig
|
||||
import textwrap
|
||||
import unittest
|
||||
import locale
|
||||
|
||||
# Is this Python configured to support threads?
|
||||
try:
|
||||
|
@ -847,6 +848,24 @@ id(42)
|
|||
)
|
||||
self.assertIn('#1 <built-in method gmtime', gdb_output)
|
||||
|
||||
@unittest.skipIf(python_is_optimized(),
|
||||
"Python was compiled with optimizations")
|
||||
def test_wrapper_call(self):
|
||||
cmd = textwrap.dedent('''
|
||||
class MyList(list):
|
||||
def __init__(self):
|
||||
super().__init__() # wrapper_call()
|
||||
|
||||
l = MyList()
|
||||
''')
|
||||
# Verify with "py-bt":
|
||||
gdb_output = self.get_stack_trace(cmd,
|
||||
breakpoint='wrapper_call',
|
||||
cmds_after_breakpoint=['py-bt'],
|
||||
)
|
||||
self.assertIn("<method-wrapper '__init__' of MyList object at ",
|
||||
gdb_output)
|
||||
|
||||
|
||||
class PyPrintTests(DebuggerTests):
|
||||
@unittest.skipIf(python_is_optimized(),
|
||||
|
|
|
@ -746,6 +746,9 @@ Build
|
|||
Tools/Demos
|
||||
-----------
|
||||
|
||||
- Issue #29367: python-gdb.py now supports also ``method-wrapper``
|
||||
(``wrapperobject``) objects.
|
||||
|
||||
- Issue #28023: Fix python-gdb.py didn't support new dict implementation.
|
||||
|
||||
- Issue #15369: The pybench and pystone microbenchmark have been removed from
|
||||
|
|
|
@ -362,6 +362,7 @@ class PyObjectPtr(object):
|
|||
'set' : PySetObjectPtr,
|
||||
'frozenset' : PySetObjectPtr,
|
||||
'builtin_function_or_method' : PyCFunctionObjectPtr,
|
||||
'method-wrapper': wrapperobject,
|
||||
}
|
||||
if tp_name in name_map:
|
||||
return name_map[tp_name]
|
||||
|
@ -1330,6 +1331,39 @@ class PyUnicodeObjectPtr(PyObjectPtr):
|
|||
out.write(quote)
|
||||
|
||||
|
||||
class wrapperobject(PyObjectPtr):
|
||||
_typename = 'wrapperobject'
|
||||
|
||||
def safe_name(self):
|
||||
try:
|
||||
name = self.field('descr')['d_base']['name'].string()
|
||||
return repr(name)
|
||||
except (NullPyObjectPtr, RuntimeError):
|
||||
return '<unknown name>'
|
||||
|
||||
def safe_tp_name(self):
|
||||
try:
|
||||
return self.field('self')['ob_type']['tp_name'].string()
|
||||
except (NullPyObjectPtr, RuntimeError):
|
||||
return '<unknown tp_name>'
|
||||
|
||||
def safe_self_addresss(self):
|
||||
try:
|
||||
address = long(self.field('self'))
|
||||
return '%#x' % address
|
||||
except (NullPyObjectPtr, RuntimeError):
|
||||
return '<failed to get self address>'
|
||||
|
||||
def proxyval(self, visited):
|
||||
name = self.safe_name()
|
||||
tp_name = self.safe_tp_name()
|
||||
self_address = self.safe_self_addresss()
|
||||
return ("<method-wrapper %s of %s object at %s>"
|
||||
% (name, tp_name, self_address))
|
||||
|
||||
def write_repr(self, out, visited):
|
||||
proxy = self.proxyval(visited)
|
||||
out.write(proxy)
|
||||
|
||||
|
||||
def int_from_int(gdbval):
|
||||
|
@ -1364,11 +1398,13 @@ class PyObjectPtrPrinter:
|
|||
|
||||
def pretty_printer_lookup(gdbval):
|
||||
type = gdbval.type.unqualified()
|
||||
if type.code == gdb.TYPE_CODE_PTR:
|
||||
type = type.target().unqualified()
|
||||
t = str(type)
|
||||
if t in ("PyObject", "PyFrameObject", "PyUnicodeObject"):
|
||||
return PyObjectPtrPrinter(gdbval)
|
||||
if type.code != gdb.TYPE_CODE_PTR:
|
||||
return None
|
||||
|
||||
type = type.target().unqualified()
|
||||
t = str(type)
|
||||
if t in ("PyObject", "PyFrameObject", "PyUnicodeObject", "wrapperobject"):
|
||||
return PyObjectPtrPrinter(gdbval)
|
||||
|
||||
"""
|
||||
During development, I've been manually invoking the code in this way:
|
||||
|
@ -1520,6 +1556,13 @@ class Frame(object):
|
|||
except RuntimeError:
|
||||
return 'PyCFunction invocation (unable to read %s)' % arg_name
|
||||
|
||||
if caller == 'wrapper_call':
|
||||
try:
|
||||
func = frame.read_var('wp')
|
||||
return str(func)
|
||||
except RuntimeError:
|
||||
return '<wrapper_call invocation>'
|
||||
|
||||
# This frame isn't worth reporting:
|
||||
return False
|
||||
|
||||
|
|
Loading…
Reference in New Issue