flask-classy icon indicating copy to clipboard operation
flask-classy copied to clipboard

Decorators that accepts kwargs from URL test

Open shuhaowu opened this issue 11 years ago • 3 comments

Test will fail with saying multiple id keyword. In reality, kwargs will have id and the actually id is passed with self, an instance of DecoratedView

Test case for #35

shuhaowu avatar Jun 17 '13 00:06 shuhaowu

Hi @shuhaowu I'm sorry it's taken me so long to get to this.

Can you give me some more background on this issue or what decorators you've come across in the wild that cause this same problem?

apiguy avatar Nov 12 '13 03:11 apiguy

Hi @apiguy

When combining flask-classy with http://pythonhosted.org/Flask-OAuth/ (and flask-oauthlib) we experience the same issue.

class LoginView(FlaskView):
    route_base = '/'

    @oauth.authorized_handler
    @route('/oauth2callback')
    def oauth2callback(self, data):
        access_token = data['access_token']
        # snipped
        return redirect('/')

data and self are switched around.

This is because inside the decorator data is passed in as the first argument.

    def authorized_handler(self, f):
        """Injects additional authorization functionality into the function.
        The function will be passed the response object as first argument
        if the request was allowed, or `None` if access was denied.  When the
        authorized handler is called, the temporary issued tokens are already
        destroyed.
        """
        @wraps(f)
        def decorated(*args, **kwargs):
            if 'oauth_verifier' in request.args:
                data = self.handle_oauth1_response()
            elif 'code' in request.args:
                data = self.handle_oauth2_response()
            else:
                data = self.handle_unknown_response()
            self.free_request_token()
            return f(*((data,) + args), **kwargs)
        return decorated

Not sure how you would go about addressing this.

johnjiang avatar Dec 31 '13 07:12 johnjiang

Actually, to fix it I just had to do this:


class LoginView(FlaskView):
    route_base = '/'

    @route('/oauth2callback')
    def oauth2callback(self):
        @oauth.authorized_handler
        def save_access_token(data):
            access_token = data['access_token']
            # snipp
        save_access_token()
        return redirect('/')

which seems to work. Looks a bit dirty though.

johnjiang avatar Dec 31 '13 07:12 johnjiang