From 58f3d980989c7346ad792d464c1d749dcec6af63 Mon Sep 17 00:00:00 2001 From: Nikita Sobolev Date: Mon, 24 Jan 2022 14:09:20 +0300 Subject: [PATCH] bpo-46422: use `dis.Positions` in `dis.Instruction` (GH-30716) Co-authored-by: Batuhan Taskaya --- Doc/library/dis.rst | 22 +++++++++++++++ Lib/dis.py | 5 +--- Lib/test/test_dis.py | 28 ++++++++++++------- .../2022-01-20-10-35-50.bpo-46422.1UAEHL.rst | 1 + 4 files changed, 42 insertions(+), 14 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2022-01-20-10-35-50.bpo-46422.1UAEHL.rst diff --git a/Doc/library/dis.rst b/Doc/library/dis.rst index ddba668088e..793152d9d81 100644 --- a/Doc/library/dis.rst +++ b/Doc/library/dis.rst @@ -316,8 +316,30 @@ details of bytecode instructions as :class:`Instruction` instances: ``True`` if other code jumps to here, otherwise ``False`` + + .. data:: positions + + :class:`dis.Positions` object holding the + start and end locations that are covered by this instruction. + .. versionadded:: 3.4 + .. versionchanged:: 3.11 + + Field ``positions`` is added. + + +.. class:: Positions + + In case the information is not available, some fields might be `None`. + + .. data:: lineno + .. data:: end_lineno + .. data:: col_offset + .. data:: end_col_offset + + .. versionadded:: 3.11 + The Python compiler currently generates the following bytecode instructions. diff --git a/Lib/dis.py b/Lib/dis.py index ac0c6e7f04c..2462a8434e8 100644 --- a/Lib/dis.py +++ b/Lib/dis.py @@ -413,10 +413,7 @@ def _get_instructions_bytes(code, varname_from_oparg=None, is_jump_target = offset in labels argval = None argrepr = '' - try: - positions = next(co_positions) - except StopIteration: - positions = None + positions = Positions(*next(co_positions, ())) if arg is not None: # Set argval to the dereferenced value of the argument when # available, and argrepr to the string representation of argval. diff --git a/Lib/test/test_dis.py b/Lib/test/test_dis.py index 19a4be2c413..ee9729ebabf 100644 --- a/Lib/test/test_dis.py +++ b/Lib/test/test_dis.py @@ -1313,6 +1313,12 @@ def test_co_positions(self): ] self.assertEqual(positions, expected) + named_positions = [ + (pos.lineno, pos.end_lineno, pos.col_offset, pos.end_col_offset) + for pos in positions + ] + self.assertEqual(named_positions, expected) + @requires_debug_ranges() def test_co_positions_missing_info(self): code = compile('x, y, z', '', 'exec') @@ -1320,25 +1326,27 @@ def test_co_positions_missing_info(self): actual = dis.get_instructions(code_without_column_table) for instruction in actual: with self.subTest(instruction=instruction): - start_line, end_line, start_offset, end_offset = instruction.positions + positions = instruction.positions + self.assertEqual(len(positions), 4) if instruction.opname == "RESUME": continue - assert start_line == 1 - assert end_line == 1 - assert start_offset is None - assert end_offset is None + self.assertEqual(positions.lineno, 1) + self.assertEqual(positions.end_lineno, 1) + self.assertIsNone(positions.col_offset) + self.assertIsNone(positions.end_col_offset) code_without_endline_table = code.replace(co_endlinetable=b'') actual = dis.get_instructions(code_without_endline_table) for instruction in actual: with self.subTest(instruction=instruction): - start_line, end_line, start_offset, end_offset = instruction.positions + positions = instruction.positions + self.assertEqual(len(positions), 4) if instruction.opname == "RESUME": continue - assert start_line == 1 - assert end_line is None - assert start_offset is not None - assert end_offset is not None + self.assertEqual(positions.lineno, 1) + self.assertIsNone(positions.end_lineno) + self.assertIsNotNone(positions.col_offset) + self.assertIsNotNone(positions.end_col_offset) # get_instructions has its own tests above, so can rely on it to validate # the object oriented API diff --git a/Misc/NEWS.d/next/Library/2022-01-20-10-35-50.bpo-46422.1UAEHL.rst b/Misc/NEWS.d/next/Library/2022-01-20-10-35-50.bpo-46422.1UAEHL.rst new file mode 100644 index 00000000000..831f5263590 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2022-01-20-10-35-50.bpo-46422.1UAEHL.rst @@ -0,0 +1 @@ +Use ``dis.Positions`` in ``dis.Instruction`` instead of a regular ``tuple``.