microdot
microdot copied to clipboard
Error handler with exception class
Hi there!
I'm using the second form of the error handler decorator to process some custom exceptions.
The error handler only works when the class of exception thrown is exactly the same as the one specified in the decorator, but it doesn't work if it is a subclass. I was expecting that the exceptions that are subclasses of the one specified in the decorator would be handled as well, pretty much as a try/except block would.
I'm trying to do something like this:
class NotFound(Exception): pass
class FileNotFound(NotFound): pass
class UserNotFound(NotFound): pass
class EntryNotFound(NotFound): pass
...
...
...
@app.errorhandler(NotFound)
def not_found(request, exception):
return {"error": str(exception)}, 404
So that I can keep the Microdot error handling decoupled from the specific error handling down the line. But I get 500 errors if I raise anything other than NotFound
Is this a conscious design choice?
I don't have a problem with expanding the way this works so that you get the handler for a parent class invoked, provided that the child class doesn't have a handler defined.
The logic that dispatches the error to a handler is here. The if statement would need to be converted to a while loop that traverses the class hierarchy until it finds a handler. Would you like to make a PR for this change?
Sure! I'll give it a try
PR ready for review #75
Feel free to change the additions to the docs if you find a better wording :smile:
@DiegoPomares The MicroPython PR build is not passing. There is no inspect on that platform.
My bad I thought isclass was a builtin and didn't noticed it was added by the IDE, plus I didn't scroll down to see there were issues :facepalm:
I'll fix it
Done
Please let me know if there's anything else that stands out and I'll be happy to take a look :smile:
The only thing that I wanted to think about is if there was a way to select the most specialized exception class instead of just the first one, but I haven't had time to think about this and see if it is feasible yet.
I wanted it to behave exactly as you describe but I couldn't think of a straightforward way to do so, my first instinct was to use the MRO but it's completely different in MicroPython and I'm not sure if coding a method that would produce the equivalent of __mro__ in CPython is a good idea tbh...