Doge log

Abby CTO 雑賀 力王のオフィシャルサイトです

AOP weave

benjyoni weaving no code sample ga kaiteattayo!

ASPNより抜粋

aspect.py
import sys, types

class LoggerAspect(object):

    def __init__(self, method):
        self.method = method

    def before(self):
        print 'entering', self.method

    def after(self, retval, exc):
        print 'retval', retval
        print 'leaving', self.method

def weave_method(method, advice_class, *advice_args, **advice_kwargs):
    advice = advice_class(method, *advice_args, **advice_kwargs)
    advice_before = advice.before
    advice_after = advice.after

    def invoke_advice(*args, **kwargs):
        advice_before()
        try:
            retval = method(*args, **kwargs)
        except Exception, e:
            advice_after(None, e)
            raise
        else:
            advice_after(retval, None)
            return retval

    try:
        class_ = method.im_class
    except:
        method.func_globals[method.func_name] = invoke_advice
    else:
        setattr(class_, method.__name__, invoke_advice)
    return invoke_advice


def weave():
    frame = sys._getframe(1)
    for k,v in frame.f_locals.items():
        if not k.startswith('__'):
            if not isinstance(v, types.FunctionType) and not isinstance(v, types.ModuleType):
                _class_weave(v)

def _class_weave(clazz):
    for key, value in clazz.__dict__.items():
        if not key.startswith('__') and isinstance(value, types.FunctionType):
            #logging example
            weave_method(getattr(clazz, key), LoggerAspect)

暗黒魔術じゃないとは思うけどframeを使います。
今回は無条件でloggingをメソッドに織り込む。

test.py
import aspect

class Test(object):
    
    def test(self, str):
        return str

aspect.weave()

普通にライブラリみたいなものを書く。
んで織り込む。

sample.py
import test

t = test.Test()
t.test("test")

とまあこんな感じ。
まずは手動織り込み。明示的に織り込む。
織り込む対象はいくらでもフィルタを書いてカスタマイズできる。
例えば正規表現とかsetting.pyに書いて織り込むとか。
自動で織り込むには結構制限がかかりそうなのでコンテナ管理とかそーいうのにしないといかんかな。
(指定されたモジュールをimportするとかね。)
うくく。