Here is some proof of concept code I wrote that demonstrates how Dectate might work if we use a more functional way to define directives, instead of using the action subclasses we do now. The idea is to make the signature of the directive be the correct signature right away if we generated code or alternatively used a library like wrapt
.
class App(object):
registered = []
@classmethod
def commit(cls):
for perform, config, obj in cls.registered:
kw = {}
for key, value in config.items():
for name, factory in config.items():
c = getattr(cls, name, None)
if c is None:
c = factory()
setattr(cls, name, c)
kw[name] = c
perform(obj, **kw)
def action(config):
def get_directive(func):
def wrapper(cls, *args, **kw):
info = func(cls, *args, **kw)
def register(obj):
cls.registered.append(
(info.perform, get_directive.config, obj))
return obj
return register
return classmethod(wrapper)
get_directive.config = config
return get_directive
class Info(object):
def __init__(self, perform):
self.perform = perform
class MyApp(App):
@action(config={'r': dict})
def mydecorator(cls, message):
def perform(obj, r):
r[message] = obj
return Info(perform)
@MyApp.mydecorator('foo')
def myfunction():
return "the function"
MyApp.commit()
assert MyApp.r == {'foo': myfunction}