Пользовательский колб декоратор вызывает UnboundLocalError - PullRequest
0 голосов
/ 27 апреля 2018

Я макетирую сервис для среды разработки и написал собственный декоратор для проверки токена авторизации. При написании пользовательского декоратора я следовал документации Flasks для аналогичного декоратора здесь . У меня проблема в том, что теперь я получаю UnboundLocalError.

Traceback (most recent call last):
  File "/Users/jgoodell/virtualenvs/mock-zoom-api/lib/python2.7/site-packages/flask/app.py", line 1997, in __call__
    return self.wsgi_app(environ, start_response)
  File "/Users/jgoodell/virtualenvs/mock-zoom-api/lib/python2.7/site-packages/flask/app.py", line 1985, in wsgi_app
    response = self.handle_exception(e)
  File "/Users/jgoodell/virtualenvs/mock-zoom-api/lib/python2.7/site-packages/flask/app.py", line 1540, in handle_exception
    reraise(exc_type, exc_value, tb)
  File "/Users/jgoodell/virtualenvs/mock-zoom-api/lib/python2.7/site-packages/flask/app.py", line 1982, in wsgi_app
    response = self.full_dispatch_request()
  File "/Users/jgoodell/virtualenvs/mock-zoom-api/lib/python2.7/site-packages/flask/app.py", line 1614, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "/Users/jgoodell/virtualenvs/mock-zoom-api/lib/python2.7/site-packages/flask/app.py", line 1517, in handle_user_exception
    reraise(exc_type, exc_value, tb)
  File "/Users/jgoodell/virtualenvs/mock-zoom-api/lib/python2.7/site-packages/flask/app.py", line 1612, in full_dispatch_request
    rv = self.dispatch_request()
  File "/Users/jgoodell/virtualenvs/mock-zoom-api/lib/python2.7/site-packages/flask/app.py", line 1598, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "/Users/jgoodell/code/python/mock-zoom-api/app.py", line 28, in decorated_function
    return f(*args, **kwargs)
  File "/Users/jgoodell/code/python/mock-zoom-api/app.py", line 35, in users
    if request.method == 'GET':
UnboundLocalError: local variable 'request' referenced before assignment

Вот исходный код, из которого возникает ошибка.

from functools import wraps
import logging
import json

from flask import Flask
from flask import request
from flask import make_response

from mock_zoom_api.auth import check_token
from mock_zoom_api.auth import InvalidTokenError


app = Flask(__name__)

logging.basicConfig()
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)


def require_token(f):
    @wraps(f)
    def decorated_function(*args, **kwargs):
        logger.debug('%s', request.headers)
        try:
            token = request.headers['Authorization']
        except KeyError, InvalidTokenError:
            return make_response('Unauthorized', 401)
        return f(*args, **kwargs)
    return decorated_function


@app.route('/v2/users', methods=['GET', 'POST'])
@require_token
def users():
    if request.method == 'GET':
        json_dict = {
            "page_count": "integer",
            "page_number": "integer",
            "page_size": "integer",
            "total_records": "integer",
            "users": [
                {
                    "id": "string",
                    "first_name": "string",
                    "last_name": "string",
                    "email": "string",
                    "type": "integer",
                    "pmi": "string",
                    "timezone": "string",
                    "dept": "string",
                    "created_at": "string [date-time]",
                    "last_login_time": "string [date-time]",
                    "last_client_version": "string"
                    }
                ]
            }
        response = make_response(json.dumps(json_dict), 200)
        response.headers['Content Type'] = 'application/json'
    elif request.method == 'POST':
        response = make_response('Success', 201)
        response.headers['Content Type'] = 'text/plain'
    else:
        request = make_response('Method Not Allowed', 405)
        response.headers['Content Type'] = 'text/plain'
    return response

Трассировка стека ясна, от декоратора ожидается, что «запрос» будет передан декорируемой функции, и если я передам «запрос» явно, ошибка исчезнет. Вот переработанный код, который работает.

from functools import wraps
import logging
import json

from flask import Flask
from flask import request
from flask import make_response

from mock_zoom_api.auth import check_token
from mock_zoom_api.auth import InvalidTokenError


app = Flask(__name__)

logging.basicConfig()
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)


def require_token(f):
    @wraps(f)
    def decorated_function(*args, **kwargs):
        logger.debug('%s', request.headers)
        try:
            token = request.headers['Authorization']
        except KeyError, InvalidTokenError:
            return make_response('Unauthorized', 401)
        return f(request, *args, **kwargs)
    return decorated_function


@app.route('/v2/users', methods=['GET', 'POST'])
@require_token
def users(request):
    if request.method == 'GET':
        json_dict = {
            "page_count": "integer",
            "page_number": "integer",
            "page_size": "integer",
            "total_records": "integer",
            "users": [
                {
                    "id": "string",
                    "first_name": "string",
                    "last_name": "string",
                    "email": "string",
                    "type": "integer",
                    "pmi": "string",
                    "timezone": "string",
                    "dept": "string",
                    "created_at": "string [date-time]",
                    "last_login_time": "string [date-time]",
                    "last_client_version": "string"
                    }
                ]
            }
        response = make_response(json.dumps(json_dict), 200)
        response.headers['Content Type'] = 'application/json'
    elif request.method == 'POST':
        response = make_response('Success', 201)
        response.headers['Content Type'] = 'text/plain'
    else:
        request = make_response('Method Not Allowed', 405)
        response.headers['Content Type'] = 'text/plain'
    return response

Смешно пахнет следующее. Почему я должен передавать 'request' из декоратора в обернутую функцию, но мне не нужно передавать 'json'? Оба импортированы в модуль и на них ссылаются внутри моего представления. Но только «запрос» вызывает UnboundLocalError, а не «json».

Вот информация о версии для моей среды.

(mock-zoom-api)[0]mock-zoom-api$ pip freeze
click==6.7
Flask==0.12.2
itsdangerous==0.24
Jinja2==2.10
MarkupSafe==1.0
Werkzeug==0.14.1
(mock-zoom-api)[0]mock-zoom-api$ python --version
Python 2.7.10

1 Ответ

0 голосов
/ 27 апреля 2018

request приходит автоматически с маршрутизацией. Изменения:

def users(request):

до

def users():
...