Skip to content

functional style decorators proof of concept #39

@faassen

Description

@faassen

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.

This does require us to give up on the current with statement as that allows you to define a subset of functions. This could be replaced by pointing people in the direction of functools.partial.

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}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions