Заставить Python-декораторы работать со структурой Hug API
Я довольно новичок в Python. Я строю простой API с помощью Hug. Я пытаюсь использовать декоратор для обработки всех не обработанных исключений, как в коде ниже. Но, похоже, я не передаю входные данные, требуемые Hug, в декоратор правильно.
auth.py
from functools import wraps
import hug
from falcon import HTTP_400, HTTP_500
import store
import validator
from user_entity import UserEntity
def _error(dict, response, status=HTTP_400):
response.status = status
return {'errors': dict}
def handle_exceptions(f):
"""Handle all non-handled exceptions."""
@wraps(f)
def decorated(*args, **kwargs):
try:
return f(*args, **kwargs)
except Exception as e:
return _error({'message': str(e)}, HTTP_500)
return decorated
@hug.post('/')
@handle_exceptions
def create_user(username, password, response):
"""Validate and create a user in the database."""
is_valid, vres = validator.validate_user(username, password)
if not is_valid:
return _error(
{k: v for k, v in vres.items() if v is not None}, response)
user = UserEntity(username=username, password=password)
urn, usr = user.db_view()
store.create_user(urn, usr)
return user.public_view()
Вот ошибка, которую я получаю:
Traceback (most recent call last):
File "auth.py", line 23, in decorated
return f(*args, **kwargs)
TypeError: create_user() missing 1 required positional argument: 'response'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/wsgiref/handlers.py", line 137, in run
self.result = application(self.environ, self.start_response)
File "/Users/munjal/.virtualenvs/utl-identity-auth-server/lib/python3.6/site-packages/falcon/api.py", line 189, in __call__
responder(req, resp, **params)
File "/Users/munjal/.virtualenvs/utl-identity-auth-server/lib/python3.6/site-packages/hug/interface.py", line 651, in __call__
self.render_content(self.call_function(**input_parameters), request, response, **kwargs)
File "/Users/munjal/.virtualenvs/utl-identity-auth-server/lib/python3.6/site-packages/hug/interface.py", line 595, in call_function
return self.interface(**parameters)
File "/Users/munjal/.virtualenvs/utl-identity-auth-server/lib/python3.6/site-packages/hug/interface.py", line 117, in __call__
return __hug_internal_self._function(*args, **kwargs)
File "auth.py", line 25, in decorated
return _error({'message': str(e)}, HTTP_500)
File "auth.py", line 14, in _error
response.status = status
AttributeError: 'str' object has no attribute 'status'
2 ответа
Вы забыли response
параметр в
return _error({'message': str(e)}, HTTP_500)
И я не думаю, что декоратор работает вообще. Hug определяет необходимые параметры по function.__code__.co_varnames
, Это не изменено functools.wraps
, После использования декоратора, что hug.post
можно увидеть это функция с аргументами *args, *kwargs
, что не полезно.
Вы можете связать свой роутер с ExceptionRouter
У меня точно такая же потребность. Я нашел способ сделать это, хотя я не уверен, что это идеально.
def handle_exceptions(f):
@wraps(f)
def decorated(*args, response, **kwargs):
try:
return f(*args, response=response, **kwargs)
except MyError as e:
response.status = HTTP_400
return {'errors': str(e)}
except Exception as e:
response.status = HTTP_500
return {'errors': 'internal server error'}
return decorated
@hug.post('/login')
def login(user_id: btext, user_email: btext, request, response):
load_session_data(request, response)
validate_user(user_id, user_email)
assert 3 < 2
update_session_data(request, response, user_id=user_id, user_email=user_email)
Тест 'assert' показывает, что возвращаемый контент 'internal server error'
вместо по умолчанию 'A server error occurred. Please contact the administrator.'
wraps
является hug.decorators.wraps
не functools.wraps
, Последний вернет значение по умолчанию 'A server error occurred. Please contact the administrator.'