Skip to content

Commit

Permalink
Merge pull request #157 from 2elli/python-3.13
Browse files Browse the repository at this point in the history
Python 3.10-3.13 line number and opcode argrepr fixes
  • Loading branch information
rocky authored Dec 15, 2024
2 parents 7f9e8d5 + 6044598 commit 0af394a
Show file tree
Hide file tree
Showing 8 changed files with 58 additions and 200 deletions.
28 changes: 2 additions & 26 deletions xdis/codetype/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@
from xdis.codetype.code38 import Code38
from xdis.codetype.code310 import Code310
from xdis.codetype.code311 import Code311, Code311FieldNames
from xdis.codetype.code312 import Code312
from xdis.version_info import PYTHON_VERSION_TRIPLE


Expand Down Expand Up @@ -101,7 +100,7 @@ def codeType2Portable(code, version_tuple=PYTHON_VERSION_TRIPLE):
co_firstlineno=code.co_firstlineno,
co_linetable=line_table,
)
elif version_tuple[:2] == (3,11):
elif version_tuple[:2] >= (3,11):
return Code311(
co_argcount=code.co_argcount,
co_posonlyargcount=code.co_posonlyargcount,
Expand All @@ -122,27 +121,6 @@ def codeType2Portable(code, version_tuple=PYTHON_VERSION_TRIPLE):
co_linetable=line_table,
co_exceptiontable=code.co_exceptiontable,
)
elif version_tuple[:2] >= (3,12):
return Code312(
co_argcount=code.co_argcount,
co_posonlyargcount=code.co_posonlyargcount,
co_kwonlyargcount=code.co_kwonlyargcount,
co_nlocals=code.co_nlocals,
co_stacksize=code.co_stacksize,
co_flags=code.co_flags,
co_consts=code.co_consts,
co_code=code.co_code,
co_names=code.co_names,
co_varnames=code.co_varnames,
co_freevars=code.co_freevars,
co_cellvars=code.co_cellvars,
co_filename=code.co_filename,
co_name=code.co_name,
co_qualname=code.co_qualname,
co_firstlineno=code.co_firstlineno,
co_linetable=line_table,
co_exceptiontable=code.co_exceptiontable,
)
elif version_tuple > (2, 0):
# 2.0 .. 2.7
return Code2(
Expand Down Expand Up @@ -209,11 +187,9 @@ def portableCodeType(version_tuple=PYTHON_VERSION_TRIPLE):
elif version_tuple[:2] == (3, 10):
# 3.10
return Code310
elif version_tuple[:2] == (3,11):
elif version_tuple[:2] >= (3,11):
# 3.11 ...
return Code311
elif version_tuple[:2] >= (3,12):
return Code312
elif version_tuple > (2, 0):
# 2.0 .. 2.7
return Code2
Expand Down
50 changes: 18 additions & 32 deletions xdis/codetype/code310.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
import types
from copy import deepcopy

import struct

from xdis.codetype.code38 import Code38
from xdis.cross_types import UnicodeForPython3
from xdis.version_info import PYTHON_VERSION_TRIPLE, version_tuple_to_str
Expand Down Expand Up @@ -160,41 +162,25 @@ def co_lines(self):
equal to the size of the bytecode. line will
either be a positive integer, or None
Parsing implementation adapted from: https://github.com/python/cpython/blob/3.10/Objects/lnotab_notes.txt
"""
line_number = self.co_firstlineno
start_offset = 0
byte_increments = [c for c in tuple(self.co_linetable[0::2])]
line_deltas = [c for c in tuple(self.co_linetable[1::2])]

if len(byte_increments) == 0:
yield start_offset, len(self.co_code), line_number
return

byte_incr = byte_increments[0]
line_delta = line_deltas[0]
assert line_delta != -128, "the first line delta can't logically be -128"
assert isinstance(line_delta, int)
if line_delta > 127:
line_delta = 256 - line_delta
else:
line_number += line_delta

for byte_incr, line_delta in zip(byte_increments[1:], line_deltas[1:]):
line = self.co_firstlineno
end_offset = 0
# co_linetable is pairs of (offset_delta: unsigned byte, line_delta: signed byte)
for offset_delta, line_delta in struct.iter_unpack('=Bb', self.co_linetable):
assert isinstance(line_delta, int)
assert isinstance(byte_incr, int)
end_offset = start_offset + byte_incr
if line_delta > 127:
line_delta = 256 - line_delta

if line_delta == -128:
line_delta = 0
yield start_offset, end_offset, line_number
line_number += line_delta
assert isinstance(offset_delta, int)
if line_delta == 0: # No change to line number, just accumulate changes to end
end_offset += offset_delta
continue
start_offset = end_offset

end_offset = len(self.co_code)
yield start_offset, end_offset, line_number
return
end_offset = start_offset + offset_delta
if line_delta == -128: # No valid line number -- skip entry
continue
line += line_delta
if end_offset == start_offset: # Empty range, omit.
continue
yield start_offset, end_offset, line

def encode_lineno_tab(self):
"""
Expand Down
61 changes: 31 additions & 30 deletions xdis/codetype/code311.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,37 @@
from xdis.version_info import PYTHON_VERSION_TRIPLE, version_tuple_to_str


# Note: order is the positional order given in the Python docs for
# 3.11 types.Codetype.
# "posonlyargcount" is not used, but it is in other Python versions, so it
# has to be included since this structure is used as the Union type
# for all code types.
Code311FieldNames = """
co_argcount
co_posonlyargcount
co_kwonlyargcount
co_nlocals
co_stacksize
co_flags
co_consts
co_code
co_names
co_varnames
co_freevars
co_cellvars
co_filename
co_name
co_qualname
co_firstlineno
co_linetable
co_exceptiontable
"""

Code311FieldTypes = deepcopy(Code310FieldTypes)
Code311FieldTypes.update({"co_qualname": str, "co_exceptiontable": bytes})


##### Parse location table #####
def parse_location_entries(location_bytes, first_line):
"""
Parses the locations table described in: https://github.com/python/cpython/blob/3.11/Objects/locations.md
Expand Down Expand Up @@ -131,36 +162,6 @@ def decode_signed_varint(s):
return entries


# Note: order is the positional order given in the Python docs for
# 3.11 types.Codetype.
# "posonlyargcount" is not used, but it is in other Python versions, so it
# has to be included since this structure is used as the Union type
# for all code types.
Code311FieldNames = """
co_argcount
co_posonlyargcount
co_kwonlyargcount
co_nlocals
co_stacksize
co_flags
co_consts
co_code
co_names
co_varnames
co_freevars
co_cellvars
co_filename
co_name
co_qualname
co_firstlineno
co_linetable
co_exceptiontable
"""

Code311FieldTypes = deepcopy(Code310FieldTypes)
Code311FieldTypes.update({"co_qualname": str, "co_exceptiontable": bytes})


##### NEW "OPAQUE" LINE TABLE PARSING #####
# See: https://github.com/python/cpython/blob/aaed91cabcedc16c089c4b1c9abb1114659a83d3/Objects/codeobject.c#L1245C1-L1245C17
PY_CODE_LOCATION_INFO_SHORT0 = 0
Expand Down
97 changes: 0 additions & 97 deletions xdis/codetype/code312.py

This file was deleted.

7 changes: 1 addition & 6 deletions xdis/opcodes/opcode_310.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,15 +49,10 @@
def_op(loc, "RERAISE", 119, 3, 0)
def_op(loc, "GEN_START", 129, 1, 0)
def_op(loc, "MATCH_CLASS", 152, 2, 1)
# fmt: on


# fmt: on
opcode_arg_fmt = opcode_arg_fmt310 = opcode_arg_fmt39.copy()
opcode_extended_fmt = opcode_extended_fmt310 = opcode_extended_fmt39.copy()

# fmt: on

opcode_arg_fmt = opcode_arg_fmt10 = opcode_arg_fmt39.copy()

update_pj3(globals(), loc)
finalize_opcodes(loc)
4 changes: 0 additions & 4 deletions xdis/opcodes/opcode_311.py
Original file line number Diff line number Diff line change
Expand Up @@ -297,10 +297,6 @@ def format_BINARY_OP(arg) -> str:
del opcode_extended_fmt311["INPLACE_TRUE_DIVIDE"]
del opcode_extended_fmt311["INPLACE_XOR"]

opcode_extended_fmt = opcode_extended_fmt311

opcode_arg_fmt = opcode_arg_fmt11 = opcode_arg_fmt310.copy()

from xdis.opcodes.opcode_310 import findlinestarts

update_pj3(globals(), loc)
Expand Down
7 changes: 4 additions & 3 deletions xdis/opcodes/opcode_312.py
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,10 @@ def format_CALL_INTRINSIC_1(arg) -> str:
def format_CALL_INTRINSIC_2(arg) -> str:
return _intrinsic_2_descs[arg]


opcode_extended_fmt = opcode_extended_fmt312 = opcode_extended_fmt311.copy()
opcode_arg_fmt = opcode_arg_fmt12 = opcode_arg_fmt311.copy()

### update arg formatting
opcode_arg_fmt312 = {
**opcode_arg_fmt311,
Expand All @@ -185,9 +189,6 @@ def format_CALL_INTRINSIC_2(arg) -> str:
"CALL_INTRINSIC_2": format_CALL_INTRINSIC_2,
},
}
opcode_extended_fmt = opcode_extended_fmt312 = opcode_extended_fmt311.copy()

opcode_arg_fmt = opcode_arg_fmt12 = opcode_arg_fmt311.copy()

from xdis.opcodes.opcode_311 import findlinestarts

Expand Down
4 changes: 2 additions & 2 deletions xdis/opcodes/opcode_313.py
Original file line number Diff line number Diff line change
Expand Up @@ -450,8 +450,8 @@
opcode_extended_fmt = opcode_312.opcode_extended_fmt312.copy()
for fmt_table in (opcode_arg_fmt, opcode_extended_fmt):
fmt_table.pop("MAKE_FUNCTION") # MAKE_FUNCTION formatting not in 3.13
opcode_arg_fmt13 = opcode_arg_fmt
opcode_extended_fmt13 = opcode_extended_fmt
opcode_arg_fmt313 = opcode_arg_fmt
opcode_extended_fmt313 = opcode_extended_fmt


# update any calls to findlinestarts to include the version tuple
Expand Down

0 comments on commit 0af394a

Please sign in to comment.