0

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?

  • `async_to_sync(self.channel_layer.group_add)` returns a function which takes two params, `self.room_group_name` and `self.channel_name`. – felipe Feb 07 '20 at 23:43
  • @Felipe OK, excellent, thanks. Does this syntax have a special name? Is there any documentation that I could read on it? I always thought of functions working from right to left so this is a jarring discovery for me! – Bleep_Bloop Feb 07 '20 at 23:47
  • The function `async_to_sync` would indeed be a [`decorator`](https://wiki.python.org/moin/PythonDecorators#What_is_a_Decorator), but it's being called directly with the function as opposed to being used with the `@async_to_sync` syntax. – felipe Feb 07 '20 at 23:48

1 Answers1

2
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")
felipe
  • 7,324
  • 2
  • 28
  • 37