Search code examples
pythondecorator

How to strip decorators from a function in Python


Let's say I have the following:

def with_connection(f):
    def decorated(*args, **kwargs):
        f(get_connection(...), *args, **kwargs)
    return decorated

@with_connection
def spam(connection):
    # Do something

I want to test the spam function without going through the hassle of setting up a connection (or whatever the decorator is doing).

Given spam, how do I strip the decorator from it and get the underlying "undecorated" function?


Solution

  • In the general case, you can't, because

    @with_connection
    def spam(connection):
        # Do something
    

    is equivalent to

    def spam(connection):
        # Do something
    
    spam = with_connection(spam)
    

    which means that the "original" spam might not even exist anymore. A (not too pretty) hack would be this:

    def with_connection(f):
        def decorated(*args, **kwargs):
            f(get_connection(...), *args, **kwargs)
        decorated._original = f
        return decorated
    
    @with_connection
    def spam(connection):
        # Do something
    
    spam._original(testcon) # calls the undecorated function