Skip to content

Violation to force usage of the raise from exception syntax feature #1620

Closed
@mpibpc-mroose

Description

@mpibpc-mroose

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    duplicateThis issue or pull request already existsrule requestAdding a new rule

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions