Search code examples
pythondjango-channelsasgi

Unusual python function wrapper syntax


I'm going through django channels tutorial and I'm baffled by the async_to_sync syntax in the asgiref.sync module

Specifically

async_to_sync(self.channel_layer.group_add)(
    self.room_group_name,
    self.channel_name
)

It says async_to_sync is a wrapper, which seems to be an interchangeable term with decorator (please correct me if this is not the case) but I'm unable to find any documentation where decorators have the syntax of

func_one(func_two)(args)

What's the flow of this line? is func_one or func_two called first? And how are the return values passed around?


Solution

  • def wrapper(func):
        def inner(*args):
            return (output.uppercase() for outputs in func())
    
        return inner
    

    You can use the decorator wrapper in two ways:

    wrapper(function)("Hello", "World")
    

    Or, the more traditional way:

    @wrapper
    def function(*args):
        print(args)
    
    function("Hello", "World")
    

    Both outputs:

    ('HELLO', 'WORLD')
    

    The function wrapper returns the function inner(), which modifies the output of the function() call. Some pseudocode:

    wrapper(function)("Hello", "World")
        inner("Hello", "World")
            output = function("Hello", "World")
            output = output.modified # ("HELLO", "WORLD")
        return output # ("HELLO", "WORLD")