Skip to content

Commit 58f3d98

Browse files
bpo-46422: use dis.Positions in dis.Instruction (GH-30716)
Co-authored-by: Batuhan Taskaya <isidentical@gmail.com>
1 parent 0367a36 commit 58f3d98

4 files changed

Lines changed: 42 additions & 14 deletions

File tree

‎Doc/library/dis.rst‎

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,8 +316,30 @@ details of bytecode instructions as :class:`Instruction` instances:
316316

317317
``True`` if other code jumps to here, otherwise ``False``
318318

319+
320+
.. data:: positions
321+
322+
:class:`dis.Positions` object holding the
323+
start and end locations that are covered by this instruction.
324+
319325
.. versionadded:: 3.4
320326

327+
.. versionchanged:: 3.11
328+
329+
Field ``positions`` is added.
330+
331+
332+
.. class:: Positions
333+
334+
In case the information is not available, some fields might be `None`.
335+
336+
.. data:: lineno
337+
.. data:: end_lineno
338+
.. data:: col_offset
339+
.. data:: end_col_offset
340+
341+
.. versionadded:: 3.11
342+
321343

322344
The Python compiler currently generates the following bytecode instructions.
323345

‎Lib/dis.py‎

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -413,10 +413,7 @@ def _get_instructions_bytes(code, varname_from_oparg=None,
413413
is_jump_target = offset in labels
414414
argval = None
415415
argrepr = ''
416-
try:
417-
positions = next(co_positions)
418-
except StopIteration:
419-
positions = None
416+
positions = Positions(*next(co_positions, ()))
420417
if arg is not None:
421418
# Set argval to the dereferenced value of the argument when
422419
# available, and argrepr to the string representation of argval.

‎Lib/test/test_dis.py‎

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1313,32 +1313,40 @@ def test_co_positions(self):
13131313
]
13141314
self.assertEqual(positions, expected)
13151315

1316+
named_positions = [
1317+
(pos.lineno, pos.end_lineno, pos.col_offset, pos.end_col_offset)
1318+
for pos in positions
1319+
]
1320+
self.assertEqual(named_positions, expected)
1321+
13161322
@requires_debug_ranges()
13171323
def test_co_positions_missing_info(self):
13181324
code = compile('x, y, z', '<test>', 'exec')
13191325
code_without_column_table = code.replace(co_columntable=b'')
13201326
actual = dis.get_instructions(code_without_column_table)
13211327
for instruction in actual:
13221328
with self.subTest(instruction=instruction):
1323-
start_line, end_line, start_offset, end_offset = instruction.positions
1329+
positions = instruction.positions
1330+
self.assertEqual(len(positions), 4)
13241331
if instruction.opname == "RESUME":
13251332
continue
1326-
assert start_line == 1
1327-
assert end_line == 1
1328-
assert start_offset is None
1329-
assert end_offset is None
1333+
self.assertEqual(positions.lineno, 1)
1334+
self.assertEqual(positions.end_lineno, 1)
1335+
self.assertIsNone(positions.col_offset)
1336+
self.assertIsNone(positions.end_col_offset)
13301337

13311338
code_without_endline_table = code.replace(co_endlinetable=b'')
13321339
actual = dis.get_instructions(code_without_endline_table)
13331340
for instruction in actual:
13341341
with self.subTest(instruction=instruction):
1335-
start_line, end_line, start_offset, end_offset = instruction.positions
1342+
positions = instruction.positions
1343+
self.assertEqual(len(positions), 4)
13361344
if instruction.opname == "RESUME":
13371345
continue
1338-
assert start_line == 1
1339-
assert end_line is None
1340-
assert start_offset is not None
1341-
assert end_offset is not None
1346+
self.assertEqual(positions.lineno, 1)
1347+
self.assertIsNone(positions.end_lineno)
1348+
self.assertIsNotNone(positions.col_offset)
1349+
self.assertIsNotNone(positions.end_col_offset)
13421350

13431351
# get_instructions has its own tests above, so can rely on it to validate
13441352
# the object oriented API
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Use ``dis.Positions`` in ``dis.Instruction`` instead of a regular ``tuple``.

0 commit comments

Comments
 (0)