Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Merge remote-tracking branch 'upstream/master' into super_call
  • Loading branch information
vladima committed Mar 20, 2021
commit b8ab90fba0ee5d03811ace041343ec297d4692d2
25 changes: 25 additions & 0 deletions Lib/test/test_dis.py
Original file line number Diff line number Diff line change
Expand Up @@ -809,6 +809,31 @@ def f(self): return super().x
0: __class__"""
self.assertEqual(dedent(dis.code_info(g["C"].f)), expected_dis_info)

def test_super_attr_load_self_cell(self):
src = """
class C:
def f(self):
lambda: self
return super().x
"""
expected = """\
4 0 LOAD_CLOSURE 0 (self)
2 BUILD_TUPLE 1
4 LOAD_CONST 1 (<code object <lambda> at 0x..., file "<string>", line 4>)
6 LOAD_CONST 2 ('C.f.<locals>.<lambda>')
8 MAKE_FUNCTION 8 (closure)
10 POP_TOP

5 12 LOAD_GLOBAL 0 (super)
14 LOAD_DEREF 1 (__class__)
16 LOAD_DEREF 0 (self)
18 LOAD_ATTR_SUPER 3 ((1, True))
20 RETURN_VALUE
"""
g = {}
exec(dedent(src), g)
self.do_disassembly_test(g["C"].f, expected)

def test_super_attr_store(self):
src = """
class C:
Expand Down
6 changes: 3 additions & 3 deletions Lib/test/test_gdb.py
Original file line number Diff line number Diff line change
Expand Up @@ -928,12 +928,12 @@ def test_wrapper_call(self):
cmd = textwrap.dedent('''
class MyList(list):
def __init__(self):
super().__init__() # wrapper_call()
super().__init__() # wrapperdescr_call()

id("first break point")
l = MyList()
''')
cmds_after_breakpoint = ['break wrapper_call', 'continue']
cmds_after_breakpoint = ['break wrapperdescr_call', 'continue']
if CET_PROTECTION:
# bpo-32962: same case as in get_stack_trace():
# we need an additional 'next' command in order to read
Expand All @@ -945,7 +945,7 @@ def __init__(self):
gdb_output = self.get_stack_trace(cmd,
cmds_after_breakpoint=cmds_after_breakpoint)
self.assertRegex(gdb_output,
r"<method-wrapper u?'__init__' of MyList object at ")
r"methoddescr-wrapper '__init__'>, args=\(<MyList at ")


class PyPrintTests(DebuggerTests):
Expand Down
4 changes: 2 additions & 2 deletions Python/compile.c
Original file line number Diff line number Diff line change
Expand Up @@ -4148,13 +4148,13 @@ is_super_call(struct compiler *c, expr_ty e)
return 0;
}
// try to find "super" symbol being defined in file
int scope = PyST_GetScope(c->u->u_ste, super_name);
int scope = _PyST_GetScope(c->u->u_ste, super_name);
// any scoping besides GLOBAL_IMPLICIT is not accepted
if (scope != GLOBAL_IMPLICIT) {
return -1;
}
// ensure it is not defined in top level scope
scope = PyST_GetScope(c->c_st->st_top, super_name);
scope = _PyST_GetScope(c->c_st->st_top, super_name);
if (scope != 0 && scope != GLOBAL_IMPLICIT) {
return -1;
}
Expand Down
34 changes: 31 additions & 3 deletions Tools/gdb/libpython.py
Original file line number Diff line number Diff line change
Expand Up @@ -358,7 +358,6 @@ def subclass_from_type(cls, t):
# Handle any kind of error e.g. NULL ptrs by simply using the base
# class
return cls

#print('tp_flags = 0x%08x' % tp_flags)
#print('tp_name = %r' % tp_name)

Expand All @@ -370,6 +369,7 @@ def subclass_from_type(cls, t):
'frozenset' : PySetObjectPtr,
'builtin_function_or_method' : PyCFunctionObjectPtr,
'method-wrapper': wrapperobject,
'wrapper_descriptor': wrapperdescrobject,
}
if tp_name in name_map:
return name_map[tp_name]
Expand Down Expand Up @@ -1401,6 +1401,24 @@ def write_repr(self, out, visited):
proxy = self.proxyval(visited)
out.write(proxy)

class wrapperdescrobject(PyObjectPtr):
_typename = 'wrapperdescrobject'

def safe_name(self):
try:
name = self.field('d_base')['name'].string()
return repr(name)
except (NullPyObjectPtr, RuntimeError, UnicodeDecodeError):
return '<unknown name>'

def proxyval(self, visited):
name = self.safe_name()
return ("<methoddescr-wrapper %s>"
% (name,))

def write_repr(self, out, visited):
proxy = self.proxyval(visited)
out.write(proxy)

def int_from_int(gdbval):
return int(gdbval)
Expand Down Expand Up @@ -1439,7 +1457,7 @@ def pretty_printer_lookup(gdbval):

type = type.target().unqualified()
t = str(type)
if t in ("PyObject", "PyFrameObject", "PyUnicodeObject", "wrapperobject"):
if t in ("PyObject", "PyFrameObject", "PyUnicodeObject", "wrapperobject", "PyWrapperDescrObject"):
return PyObjectPtrPrinter(gdbval)

"""
Expand Down Expand Up @@ -1573,7 +1591,6 @@ def is_other_python_frame(self):
caller = frame.name()
if not caller:
return False

if (caller.startswith('cfunction_vectorcall_') or
caller == 'cfunction_call'):
arg_name = 'func'
Expand Down Expand Up @@ -1603,6 +1620,17 @@ def is_other_python_frame(self):
except RuntimeError:
return '<wrapper_call invocation (unable to read %s)>' % arg_name

if caller == 'wrapperdescr_call':
arg_name = 'descr'
try:
func = frame.read_var(arg_name)
return str(func)
except ValueError:
return ('<wrapperdescr_call invocation (unable to read %s: '
'missing debuginfos?)>' % arg_name)
except RuntimeError:
return '<wrapperdescr_call invocation (unable to read %s)>' % arg_name

# This frame isn't worth reporting:
return False

Expand Down
You are viewing a condensed version of this merge commit. You can view the full changes here.