Why are these decorators called from outermost to innermost, not the other way round?

StackOverflow https://stackoverflow.com/questions/22309087

  •  12-06-2023
  •  | 
  •  

Вопрос

I have the following method inside a tornado.websocket.WebSocketHandler subclass:

@authenticate_user_async
@gen.coroutine
def on_message(self, data):
    """
    Callback when new message received via the socket.
    """
    # do stuff...

The @authenticate_user_async decorator is below:

def authenticate_user_async(f):
    """
    Authentication decorator based on http://tornadogists.org/5251927/

    Authenticates the user's credentials and sets self.current_user if valid
    """
    @functools.wraps(f)
    @gen.coroutine
    def wrapper(self, *args, **kwargs):
        # do stuff...

        f(self, *args, **kwargs)

    return wrapper

I thought that the innermost decorator was called first, so would have expected to need them to be given:

@gen.coroutine
@authenticate_user_async
def on_message(self, data):
   ...

but only the first version works and the one above is never called if the yield keyword is inside the on_message() method.

Why is it necessary to use the first version and not the second?

Это было полезно?

Решение

(I think I gave you this bug in my answer to your previous question, sorry.)

The line in authenticate_user_async where it calls f needs to be changed. Change this:

f(self, *args, **kwargs)

To this:

yield f(self, *args, **kwargs)

Now swap the order of decoration for on_message:

@authenticate_user_async
@gen.coroutine
def on_message(self, data):

In authenticate_user_async, "f" is your on_message. These two fixes ensure that "f" is a coroutine and that it gets run to completion.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top