AugBar
AugBar

Reputation: 467

Calling decorated external functions

I am looking for a way for a script to execute some functions for which I don't know the names and defined on another module (supposedly provided by another user), but decorated with ones that I define.

For example, the external script would be:

    from MyScript import preprocess, process, postprocess 

    @preprocess(foo, bar)
    def external_provider_random_name():
        return "foo"

    @process(foobar)
    def external_provider_random():
        return "bar"

    @postprocess(foo, bar)
    def external_provider():
        return "foobar"

I would in turn import this in my application and execute the functions ( I don't know their name), with the ability to use what the decorated function returns.

The reason I thought of decorators is become flask seems to expose the similar behavior: the user can define new route by decorating a function with [email protected](my/route). This function is then executed when a http call is performed on the route, and the application can use whatever the function returns (a json) to return it to the user.

However it seems that behavior doesn't fit with the actual definition of decorators, and I can't see how I can achieve such. Am I missing something here or is there a solution using only decorators ?

Upvotes: 2

Views: 1240

Answers (2)

Jared Goguen
Jared Goguen

Reputation: 9008

It seems like you are want to create some sort of function registry. Here's a simple example implementation that uses a dictionary to keep track of the registered functions.

class Tracker(dict):
    def register(self, identifier):
        def wrapper(function):
            self[identifier] = function
            return function
        return wrapper


tracker = Tracker()

@tracker.register('A')
def function_A():
    print('Blah')

tracker['A']() # Blah

If you want to register an already defined function, you can use:

tracker.register('A')(function_A)

Upvotes: 2

Robᵩ
Robᵩ

Reputation: 168766

You just need to squirrel away a copy of the passed-in function from inside your wrapper. You could store the function references in a global name, in a list, a dict or any other way you choose.

Here is an example of MyScript.py that stores its function references in a dict:

funcs = { }

def preprocess(*args):
    def wrapper(fn):
        funcs['preprocess'] = fn
        return fn
    return wrapper

def process(*args):
    def wrapper(fn):
        funcs['process'] = fn
        return fn
    return wrapper

def postprocess(*args):
    def wrapper(fn):
        funcs['process'] = fn
        return fn
    return wrapper

After all of the initialization, you can invoke the functions thusly:

MyScript.funcs['preprocess']()

Upvotes: 2

Related Questions