Заставить 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.'

Другие вопросы по тегам