■
Loggerにつかえるアスペクト・メタクラス(?)を書いてみた。
(何度目だろう ... )
class HelloWorld: def sayHello(self): print "Hello, world" class HelloWorldAspect(Aspect): _target_class = HelloWorld def before_sayHello(self, *args, **keys): print "sayHello method was called" # HelloWorldAspectクラスを定義した辞典で # HelloWorldのsayHelloメソッドが変更されている。 world = HelloWorld() world.sayHello()
class HelloWorldAspect: __metaclass__ = AspectFor(HelloWorld)
と、メタクラスを返す関数を定義しようとも考えたけど、
メタクラスも継承出来るようなので、AspectClassを作り
Aspectに継承させて、Aspectを継承するクラスは、
_target_class でクラスを指定し、wrapperクラスを普通の
メソッドと同じように定義する事で、ターゲットに指定したクラスのメソッドを変更する様な振舞にした。メソッド名は、プレフィクス(after|before)_(元のメソッド名)とする。(自動判別)
再利用するメタクラスは以下の通り。
import re import inspect def makeAdvice(advice, func, old_method): def _func(self, *args, **keys): if advice == "before": func(self, *args, **keys) result = old_method(self, *args, **keys) if advice == "after": func(self) return result return _func class AspectClass(type): def __new__(self, classname, classbases, classdict): if classdict.has_key('_target_class'): target_class = classdict["_target_class"] for name in classdict: if inspect.isfunction(classdict[name]): func = classdict[name] matched = re.match("^(after|before)_(.+)$", name) if matched: advice, funcname = matched.groups() if hasattr(target_class, funcname): old_method = getattr(target_class, funcname) new_method = makeAdvice(advice, func, old_method) setattr(target_class, funcname, new_method) else: raise NotImplementedError return type.__new__(self, classname, classbases, classdict) class Aspect: __metaclass__ = AspectClass