Closed
Description
Bug report
# minimal reproducible example
import types
members = [ # 16 members
"co_argcount", "co_posonlyargcount", "co_kwonlyargcount",
"co_nlocals", "co_stacksize", "co_flags",
"co_code", "co_consts", "co_names",
"co_varnames", "co_filename", "co_name",
"co_firstlineno", "co_lnotab", "co_freevars",
"co_cellvars",
]
codeobj = (lambda x: x).__code__
newobj = types.CodeType(*(getattr(codeobj, member) for member in members))
# TypeError: code() argument 13 must be str, not int
I've already asked this on Python user discord server but couldn't get proper answer.
13th argument is codeobj.co_lnotab
but putting invalid input (None
, ""
or b""
) does not change the error message, TypeError: code() argument 13 must be str, not int
. So I'm guessing there's a mismatch on the order of parameters of types.CodeType
and code()
.
Context
I'm maintaining DSL, which can import Python and vice versa. I need to reconstruct lnotab
for correct line numbers for e.g. stacktrace.
I tried using types.CodeType.replace
but it does not support co_lnotab
.
Original code: https://github.com/armoha/eudplib/blob/master/eudplib/epscript/epsimp.py#L46-L92
def modifyCodeLineno(codeobj, codeMap):
co_lnotab = codeobj.co_lnotab
co_firstlineno = codeobj.co_firstlineno
# Reconstruct code data
new_lnotab = []
currentLine = co_firstlineno
currentMappedLine = codeMap(currentLine)
for i in range(0, len(co_lnotab), 2):
bytecodeLen, lineAdvance = co_lnotab[i : i + 2]
nextLine = currentLine + lineAdvance
nextMappedLine = codeMap(nextLine)
newLineAdvance = nextMappedLine - currentMappedLine
while newLineAdvance >= 0xFF:
new_lnotab.append(bytes([0, 0xFF]))
newLineAdvance -= 0xFF
new_lnotab.append(bytes([bytecodeLen, newLineAdvance]))
currentLine = nextLine
currentMappedLine = nextMappedLine
# For code objects
new_co_consts = []
for c in codeobj.co_consts:
if isinstance(c, types.CodeType):
c = modifyCodeLineno(c, codeMap)
new_co_consts.append(c)
codeobj = types.CodeType(
codeobj.co_argcount,
codeobj.co_posonlyargcount, # python 3.8 support (See PEP 570)
codeobj.co_kwonlyargcount,
codeobj.co_nlocals,
codeobj.co_stacksize,
codeobj.co_flags,
codeobj.co_code,
tuple(new_co_consts),
codeobj.co_names,
codeobj.co_varnames,
codeobj.co_filename,
codeobj.co_name,
codeMap(co_firstlineno), # codeobj.co_firstlineno,
b"".join(new_lnotab), # codeobj.co_lnotab,
codeobj.co_freevars,
codeobj.co_cellvars,
)
return codeobj
Your environment
- CPython versions tested on: Python 3.11.1 (works fine on Python 3.7~10)
- Operating system and architecture: Windows amd64