I am fairly new to Python. I am building a simple API using Hug. I am trying to use a decorator to handle all not handled exceptions as in the code below. But it appears I am not passing inputs required by Hug in the decorator properly.
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()
Here is the error I get:
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'
You forgot the response
parameter in
return _error({'message': str(e)}, HTTP_500)
And I don't think the decorator works in general. Hug identifies the necessary parameters by function.__code__.co_varnames
. This is not modified by functools.wraps
. After you use your decorator, what hug.post
can see is a function with arguments *args, *kwargs
, which is not helpful.
You may chain your router with ExceptionRouter