Description
Rule request
I want to highlight a blog article from Ray Rachum (@cool-RR) about such an interesting - but as he tells rarely used - Python feature named "raise for exception". For me it was immediately clear why to use it and I will adopt it for my code. Ram already incorporated a rule for that in pylint
(see this MR)
Thesis
Just quoting Ray's blog article
Exception causes, or raise new from old
I’m going to show you both sides of this feature: How to tell Python that you’re catching an exception to replace it with a friendlier one, and how to understand when Python is telling you that this is what’s happening in code that you’re debugging.
For the first part, here’s a good example from MyPy’s codebase:
try:
self.connection, _ = self.sock.accept()
except socket.timeout as e:
raise IPCException('The socket timed out') from e
See the from e bit at the end? That’s the bit that tells Python: The IPCException that we’re raising is just a friendlier version of the socket.timeout that we just caught.
When we run that code and reach that exception, the traceback is going to look like this:
Traceback (most recent call last):
File "foo.py", line 19, in
self.connection, _ = self.sock.accept()
File "foo.py", line 7, in accept
raise socket.timeout
socket.timeout
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "foo.py", line 21, in
raise IPCException('The socket timed out') from e
IPCException: The socket timed out
I think we should provide a violation to force usage of that syntax feature.
Reasoning
Quoting again:
See that message in the middle, about the exception above being the direct cause of the exception below? That’s the important bit. That’s how you know you have a case of a friendly wrapping of an exception.
If you were dealing with the first case, i.e. an exception handler that has an error in it, the message between the two tracebacks would be:
During handling of the above exception, another exception occurred
That’s it. Now you can tell the two cases apart.