-
-
Save thatbirdguythatuknownot/524234dbe8415f1873da57713fa0869c to your computer and use it in GitHub Desktop.
Inner decorator
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import types | |
import opcode | |
MAKE_FUNCTION = opcode.opmap['MAKE_FUNCTION'] | |
del opcode | |
def decorate_inner(decorator, name): | |
def actual_decorator(outer_fn): | |
# Try and find the decorator function in co_consts, | |
# perform EAFP | |
co_consts = outer_fn.__code__.co_consts | |
try: | |
index = co_consts.index(decorator) | |
except ValueError: | |
index = len(co_consts) | |
outer_fn.__code__ = outer_fn.__code__.replace( | |
co_consts=co_consts + (decorator,) | |
) | |
# Try and find the name in co_consts, | |
# perform EAFP | |
try: | |
index2 = co_consts.index( | |
f"{outer_fn.__code__.co_name}.<locals>.{name}" | |
) | |
except ValueError: | |
raise RuntimeError(f"couldn't find name {name}") from None | |
if index2 > 127: | |
raise IndexError(f"name index in co_consts is > 127") | |
co_code = outer_fn.__code__.co_code | |
character = chr(index2) | |
base = co_code.find(f'd{character}'.encode()) | |
while co_code[base+2] is not MAKE_FUNCTION: | |
base = co_code.find(f'd{character}'.encode(), base+2) | |
outer_fn.__code__ = outer_fn.__code__.replace( | |
co_code=(co_code[:base+4] | |
+ f'd{chr(index)}\x02\x00\x83\x01'.encode('l1') | |
+ co_code[base+4:]) | |
) | |
return outer_fn | |
return actual_decorator | |
def deco(fn): | |
def wrapper(*args, **kwargs): | |
print("Calling", fn.__name__) | |
ret = fn() | |
print("Called", fn.__name__) | |
return ret | |
return wrapper | |
@decorate_inner(deco, "g") | |
def f(): | |
def g(): | |
return 42 | |
return g | |
g = f() | |
print(g()) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment