Fun with parameter-collecting proxies

Further inspired by the Routes submapper idea (see DRY up your routes) here’s a generic proxy object that collects arguments repeated across method calls:

class Params(object):
    def __init__(self, obj, *args, **kwargs):
        self.__obj = obj
        self.__args = args
        self.__kwargs = kwargs

    def __getattr__(self, name):
        try:
            attr = getattr(self.__obj, name)
            if callable(attr):
                # Target attr is callable; return another that
                # will sneak in our remembered args
                def wrapped_method(*args, **kwargs):
                    return attr(*(self.__args + args),
                                **dict(self.__kwargs, **kwargs))
                return wrapped_method
            else:
                # Plain old attribute
                return attr
        except AttributeError:
            # self.foo(bar, *args, **kwargs)
            # -> scope(self, foo=bar, *args, **kwargs)
            def wrapped_scope(*args, **kwargs):
                return Params(self, *args[1:],
                              **dict({name: args[0]}, **kwargs))
            return wrapped_scope

    def __enter__(self):
        return self

    def __exit__(self, type, value, tb):
        pass

params = Params

You can use it submapper-style (with or without the ‘with‘ syntax), collecting arbitrary args and kwargs as follows:

with params(mapper, controller='entries') as entries:
    entries.connect(...)
    entries.connect(...)
    ...

Here controller='entries' gets included in each method call to the underlying mapper.

Equivalently, it supports a “fluent” or DSL-ish style where named parameters are transfomed into (chainable) methods:

m = params(mapper)
with m.controller('entries') as entries:
    entries.connect(...)
    entries.connect(...)
    ...

Of course the Routes API (in the dev version at least) already has submappers and param makes a poor substititute, but as tool for reducing duplication elsewhere it may yet prove useful.

Tags:

Leave a Reply