summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Lib/dis.py9
-rw-r--r--Lib/test/test_dis.py24
-rw-r--r--Misc/NEWS2
3 files changed, 35 insertions, 0 deletions
diff --git a/Lib/dis.py b/Lib/dis.py
index 3a706be3c8..0794b7f743 100644
--- a/Lib/dis.py
+++ b/Lib/dis.py
@@ -16,6 +16,8 @@ del _opcodes_all
_have_code = (types.MethodType, types.FunctionType, types.CodeType,
classmethod, staticmethod, type)
+FORMAT_VALUE = opmap['FORMAT_VALUE']
+
def _try_compile(source, name):
"""Attempts to compile the given source, first as an expression and
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
elif op in hasfree:
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,
arg, argval, argrepr,
offset, starts_line, is_jump_target)
diff --git a/Lib/test/test_dis.py b/Lib/test/test_dis.py
index f3193368e9..b9b5ac2667 100644
--- a/Lib/test/test_dis.py
+++ b/Lib/test/test_dis.py
@@ -301,6 +301,27 @@ dis_traceback = """\
TRACEBACK_CODE.co_firstlineno + 4,
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):
yield x
@@ -404,6 +425,9 @@ class DisTests(unittest.TestCase):
gen_disas = self.get_disassembly(_g(1)) # Disassemble generator itself
self.assertEqual(gen_disas, gen_func_disas)
+ def test_disassemble_fstring(self):
+ self.do_disassembly_test(_fstring, dis_fstring)
+
def test_dis_none(self):
try:
del sys.last_traceback
diff --git a/Misc/NEWS b/Misc/NEWS
index 237bf6fd01..f433959a93 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -62,6 +62,8 @@ Core and Builtins
Library
-------
+- Issue #28317: The disassembler now decodes FORMAT_VALUE argument.
+
- 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
conforming to the specification.