MatthieuDartiailh / bytecode

Python module to modify bytecode
https://bytecode.readthedocs.io/
MIT License
302 stars 38 forks source link

cannot directly set argnames when creating a new code object from an existed one #31

Closed thautwarm closed 6 years ago

thautwarm commented 6 years ago

Hi, community! This is such an awesome project that enable people to try something amazing in python, it does help me.

Currently, the following problem just troubled me:

def f(x):
    y = 1
    print(y)

codeobj: types.CodeType = f.__code__
print(codeobj.co_varnames)       # (x, y) 
bc = Bytecode.from_code(codeobj)
bc.to_code() == codeobj  # -> True
new_bc = Bytecode([each for each in bc])
new_code_obj = new_bc.to_code()
new_code_obj == codeobj # False
new_code_obj.co_varnames # (y, )

I cannot correctly set the arguments now if I do not add new_bc.argnames = bc.argnames, for the Bytecode constructor doesn't have any other argument except an instructions. I wonder if I can rewrite the bytecode of a function and immediately create a new one with a constructor like:

new_bc = Bytecode([each for each in bc], metadata_from=bc)

The new argument metadata_from could make the new code object consistent with the older one

new_code_object.argcount == code_object.argcount,  # True
new_code_object.kwonlyargcount  == code_object.kwonlyargcount, # True
...
MatthieuDartiailh commented 6 years ago

I am not sure I understand your use case. Why do you need to create a second Bytecode object ? Can't you just modify the one you get after disassembling ? Before adding any new capabilities, I just prefer to be sure I understand your use case.

thautwarm commented 6 years ago

@MatthieuDartiailh Sorry, I've never thought about mutating the bytecode object directly! You've just reminded me and it works perfectly now! Thank you!

thautwarm commented 6 years ago

What I want to do is just replacing some instructions of a function's code object.

MatthieuDartiailh commented 6 years ago

Happy we could figure this out.