Last active
September 16, 2019 22:46
-
-
Save me2beats/6ade679d95a23f4c4c0cb83a5d065b68 to your computer and use it in GitHub Desktop.
Deco
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
from inspect import currentframe, getouterframes | |
class CalledFromHereBhv: | |
def __init__(self): | |
curframe = currentframe() | |
self.called_from_module_fn,\ | |
self.called_from_start_line =\ | |
self._get_module_and_start_line(curframe) | |
def _get_module_and_start_line(self, curframe): | |
module, start_line = None, None | |
calframe = getouterframes(curframe, 2) | |
for frame_info in calframe: | |
context = frame_info.code_context | |
for i in context: | |
if 'with Deco' in i: | |
module, start_line = frame_info[1:3] | |
return (module, start_line) |
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
from sys import modules as sys_modules | |
import inspect | |
from os import path | |
from called_from_here_bhv import CalledFromHereBhv | |
from SkipWith import SkipWith | |
from dict_utils import get_by_val_attr | |
class Deco(CalledFromHereBhv, SkipWith): | |
def __init__(self, decorator_name): | |
super().__init__() | |
self.decorator_name = decorator_name | |
module_fn = self.called_from_module_fn | |
module = get_by_val_attr(sys_modules, '__file__', module_fn) | |
start_line = self.called_from_start_line | |
src_lines = self.get_codeblock_source(module_fn, start_line) | |
new_foo_lines = self.make_decorated_foo(src_lines) | |
new_foo_str = '\n'.join(new_foo_lines) | |
module_globals = module.__dict__ | |
exec (new_foo_str, module_globals) | |
def get_codeblock_source(self,module_fn, start_line): | |
l = [] | |
first_line_spaces = 0 | |
with open(module_fn) as src: | |
for i, line in enumerate(src): | |
if i<start_line-1: continue | |
l.append(line) | |
if i==start_line-1: | |
first_line_spaces = self.count_first_spaces(line) | |
elif i > start_line-1: | |
if self.count_first_spaces(line)<=first_line_spaces: | |
break | |
l = [self.undent(line, first_line_spaces) for (line) in l] | |
return l | |
def count_first_spaces(self, s): | |
return len(s) - len(s.lstrip(' ')) | |
def undent(self, s, min_): | |
return s[min_:] | |
def make_decorated_foo(self, src_lines): | |
foo_lines = self.replace_head(src_lines) | |
decorated_foo_lines = self.decorate(foo_lines, self.decorator_name) | |
self.add_call(decorated_foo_lines) | |
return decorated_foo_lines | |
def replace_head(self, src_lines): | |
src_lines[0] = 'def my_temp_foo():' | |
return src_lines | |
def decorate(self, src_lines, decorator_name): | |
src_lines.insert(0, '@'+decorator_name) | |
return src_lines | |
def add_call(self, src_lines): | |
src_lines.append('my_temp_foo()') | |
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
def get_by_val_attr(dct, attr_name, attr_val, ret = 'v'): | |
for k, v in dct.items(): | |
try: | |
if getattr(v,attr_name) != attr_val: continue | |
if ret == 'v': | |
return v | |
elif ret == 'k': | |
return k | |
elif ret == 'kv': | |
return (k, v) | |
except: pass |
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 test | |
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
from sys import settrace, _getframe | |
class SkipWithExc(Exception): | |
pass | |
class SkipWith: | |
def __enter__(self): | |
settrace(lambda *args, **keys: None) | |
frame = _getframe(1) | |
frame.f_trace = self.trace | |
def trace(self, frame, event, arg): | |
raise SkipWithExc() | |
def __exit__(self, type, value, traceback): | |
if type is None: | |
return # No exception | |
if issubclass(type, SkipWithExc): | |
return True # Suppress special SkipWithBlock exception |
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
from Deco import * | |
def decorated(foo): | |
def inner_decorator(): | |
foo() | |
foo() | |
return inner_decorator | |
def decorated1(foo): | |
def inner_decorator(): | |
print('ok') | |
return inner_decorator | |
h = 'hewwo' | |
w = 'worwd' | |
with Deco('decorated'): | |
print(h, w) | |
if True: | |
with Deco('decorated1'): | |
print(h) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment