This rule raises an issue when a bare raise statement is not in an except or finally block.
A bare raise statement, i.e. a raise with no exception provided, will re-raise the last active exception in the current
scope:
def foo():
try:
...
except ValueError as e:
raise # this will re-raise "e"
If the raise statement is not in an except or finally block, no exception is active and a
RuntimeError is raised instead.
If the bare raise statement is in a function called in an except block, the exception caught by the except
will be re-raised. However, this behavior is not reliable as nothing prevents a developer from calling the function from a different context.
Overall, having bare raise statements outside of except blocks is discouraged as it is hard to understand and
maintain.
In a finally block, an exception is still active only when it hasn’t been caught in a previous except clause or if it has
been raised in an except block. In both cases, it is better to let the exception propagate automatically than to re-raise it. This
pattern is covered by rule {rule:python:S5704}.
To fix this issue, make sure to specify which exception needs to be raised when outside of an except block.
raise # Noncompliant: no active exception
def foo():
raise # Noncompliant: no active exception
try:
raise # Noncompliant: no active exception
except ValueError:
handle_error()
def handle_error():
raise # Noncompliant: this is not reliable
raise ValueError()
def foo():
raise ValueError()
try:
raise ValueError()
except ValueError:
raise
raise statement