A python microservice framework
Overview
Quick start
Project files
OpenAPI specification
API objects
Server code
Deployment pipeline
Docker packaging
JWT authentication
Configuration
Error handling
Asynchronous execution
Database serialisation
Testing
Monitoring
Pymacaron expects endpoints to return a valid apipool model instance on success, and to raise a PyMacaronException upon failure.
A PyMacaronException has the attributes:
All exceptions raised by your endpoints should inherit from ‘pymacaron.exceptions.PyMacaronException’, as in:
from pymacaron.exceptions import PyMacaronException
class InvalidUserError(PyMacaronException):
code = 'INVALID_USER' # Sets the value of the 'error' field in the error json object
status = 401 # The HTTP reply status, and 'status' field of the error json object
# An endpoint implementation...
def do_login(userdata):
raise InvalidUserError("Sorry, we don't know you")
Any exception raised by your endpoint that does not inherit from PyMacaronException will be converted to the generic ‘SERVER_ERROR’ exception:
class UnhandledServerError(PyMacaronException):
code = 'SERVER_ERROR'
status = 500
Other python exceptions will be caught and reported as
When an endpoint raises a python exception, it gets caught by pymacaron and returned to the caller as a json dict with the structure:
{
"error": "INVALID_USER", # The exception's code
"error_description": "DB entry not found", # String representation of the exception
"user_message": "Sorry, we don't know you", # User friendly explanation (optional)
"status": 401 # Same as the response's HTTP status code
}
To implement your own json format for API errors, declare an ‘error_callback’ when instantiating the pymacaron.API object:
from pymacaron import API, letsgo
def custom_error_callback(e):
"""Takes a PyMacaronException and returns a json dict representing it in your API's own error format"""
return {
...
}
def start(port=None, debug=None):
# ...
api = API(
app,
port=port,
debug=debug,
error_callback=custom_error_callback,
)
api.load_apis(...)
api.start()
letsgo(__name__, callback=start)
You can instruct pymcaron to report exceptions to a method of your choice. This error reporter method should have the signature:
def my_error_reporter(title='', data={}, exception=None):
"""Takes a 'title', a data dict containing details about the trace and request context, and the exception instance.
If called via 'report_warning()', the exception is undefined.
"""
pass
A custom error reporter is defined when instantiating pymacaron.API:
def start(port=None, debug=None):
# ...
api = API(
app,
port=port,
debug=debug,
error_reporter=my_error_reporter,
)
api.load_apis(...)
api.start()
letsgo(__name__, callback=start)
You can trigger a call to your error reporter from anywhere in your endpoint by calling ‘report_warning(“custom message”)’.
See pymacaron.crash for details.
As an alternative to subclassing PyMacaronException, you can also define your own PyMacaronExceptions by calling ‘pymacaron.exceptions.add_error()’:
from pymacaron.exceptions import add_error
# add_error() generates a class named MyOwnException that inherits from
# PyMacaronException and is properly handled by
# pymacaron. add_error() returns the MyOwnException class
exceptionclass = add_error(
name='MyOwnException',
code='MY_OWN_EXCEPTION',
status=401,
)
# You can then inject MyOwnException into the current module's namespace
globals()['MyOwnException'] = exceptionclass
# And now you can import it in other modules as well
# from myexceptions import MyOwnException
This is convenient if you want to define a large number of custom exceptions at once.