mirror of
https://github.com/python/cpython.git
synced 2025-09-26 10:19:53 +00:00
Issue #28317: The disassembler now decodes FORMAT_VALUE argument.
This commit is contained in:
parent
56588b7055
commit
dd102f7af8
3 changed files with 35 additions and 0 deletions
|
@ -16,6 +16,8 @@ del _opcodes_all
|
||||||
_have_code = (types.MethodType, types.FunctionType, types.CodeType,
|
_have_code = (types.MethodType, types.FunctionType, types.CodeType,
|
||||||
classmethod, staticmethod, type)
|
classmethod, staticmethod, type)
|
||||||
|
|
||||||
|
FORMAT_VALUE = opmap['FORMAT_VALUE']
|
||||||
|
|
||||||
def _try_compile(source, name):
|
def _try_compile(source, name):
|
||||||
"""Attempts to compile the given source, first as an expression and
|
"""Attempts to compile the given source, first as an expression and
|
||||||
then as a statement if the first approach fails.
|
then as a statement if the first approach fails.
|
||||||
|
@ -314,6 +316,13 @@ def _get_instructions_bytes(code, varnames=None, names=None, constants=None,
|
||||||
argrepr = argval
|
argrepr = argval
|
||||||
elif op in hasfree:
|
elif op in hasfree:
|
||||||
argval, argrepr = _get_name_info(arg, cells)
|
argval, argrepr = _get_name_info(arg, cells)
|
||||||
|
elif op == FORMAT_VALUE:
|
||||||
|
argval = ((None, str, repr, ascii)[arg & 0x3], bool(arg & 0x4))
|
||||||
|
argrepr = ('', 'str', 'repr', 'ascii')[arg & 0x3]
|
||||||
|
if argval[1]:
|
||||||
|
if argrepr:
|
||||||
|
argrepr += ', '
|
||||||
|
argrepr += 'with format'
|
||||||
yield Instruction(opname[op], op,
|
yield Instruction(opname[op], op,
|
||||||
arg, argval, argrepr,
|
arg, argval, argrepr,
|
||||||
offset, starts_line, is_jump_target)
|
offset, starts_line, is_jump_target)
|
||||||
|
|
|
@ -301,6 +301,27 @@ dis_traceback = """\
|
||||||
TRACEBACK_CODE.co_firstlineno + 4,
|
TRACEBACK_CODE.co_firstlineno + 4,
|
||||||
TRACEBACK_CODE.co_firstlineno + 5)
|
TRACEBACK_CODE.co_firstlineno + 5)
|
||||||
|
|
||||||
|
def _fstring(a, b, c, d):
|
||||||
|
return f'{a} {b:4} {c!r} {d!r:4}'
|
||||||
|
|
||||||
|
dis_fstring = """\
|
||||||
|
%3d 0 LOAD_FAST 0 (a)
|
||||||
|
2 FORMAT_VALUE 0
|
||||||
|
4 LOAD_CONST 1 (' ')
|
||||||
|
6 LOAD_FAST 1 (b)
|
||||||
|
8 LOAD_CONST 2 ('4')
|
||||||
|
10 FORMAT_VALUE 4 (with format)
|
||||||
|
12 LOAD_CONST 1 (' ')
|
||||||
|
14 LOAD_FAST 2 (c)
|
||||||
|
16 FORMAT_VALUE 2 (repr)
|
||||||
|
18 LOAD_CONST 1 (' ')
|
||||||
|
20 LOAD_FAST 3 (d)
|
||||||
|
22 LOAD_CONST 2 ('4')
|
||||||
|
24 FORMAT_VALUE 6 (repr, with format)
|
||||||
|
26 BUILD_STRING 7
|
||||||
|
28 RETURN_VALUE
|
||||||
|
""" % (_fstring.__code__.co_firstlineno + 1,)
|
||||||
|
|
||||||
def _g(x):
|
def _g(x):
|
||||||
yield x
|
yield x
|
||||||
|
|
||||||
|
@ -404,6 +425,9 @@ class DisTests(unittest.TestCase):
|
||||||
gen_disas = self.get_disassembly(_g(1)) # Disassemble generator itself
|
gen_disas = self.get_disassembly(_g(1)) # Disassemble generator itself
|
||||||
self.assertEqual(gen_disas, gen_func_disas)
|
self.assertEqual(gen_disas, gen_func_disas)
|
||||||
|
|
||||||
|
def test_disassemble_fstring(self):
|
||||||
|
self.do_disassembly_test(_fstring, dis_fstring)
|
||||||
|
|
||||||
def test_dis_none(self):
|
def test_dis_none(self):
|
||||||
try:
|
try:
|
||||||
del sys.last_traceback
|
del sys.last_traceback
|
||||||
|
|
|
@ -62,6 +62,8 @@ Core and Builtins
|
||||||
Library
|
Library
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
- Issue #28317: The disassembler now decodes FORMAT_VALUE argument.
|
||||||
|
|
||||||
- Issue #26293: Fixed writing ZIP files that starts not from the start of the
|
- Issue #26293: Fixed writing ZIP files that starts not from the start of the
|
||||||
file. Offsets in ZIP file now are relative to the start of the archive in
|
file. Offsets in ZIP file now are relative to the start of the archive in
|
||||||
conforming to the specification.
|
conforming to the specification.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue