
When an include is not surrounded by empty lines, its content is inlined on the same line as the adjacent content. That can lead to broken tags and other display issues. This PR fixes all such includes and introduces a validation step that forbids introducing the same problem again.
108 lines
3.3 KiB
Plaintext
108 lines
3.3 KiB
Plaintext
== Why is this an issue?
|
|
|
|
Exceptions handlers (``++except:++``) are evaluated in the order they are written. Once a match is found, the evaluation stops.
|
|
|
|
|
|
In some contexts an except block is dead code as it will never catch any exception:
|
|
|
|
* If there is a handler for a base class followed by a handler for class derived from that base class, the second handler will never trigger: The handler for the base class will match the derived class, and will be the only executed handler.
|
|
* When multiple ``++except++`` statements try to catch the same exception class, only the first one will be executed.
|
|
* In python 3, ``++BaseException++`` is the parent of every exception class. When ``++BaseException++`` is caught and the same try-except block has a bare ``++except:++`` statement, i.e. an ``++except++`` with no expression, the bare except will never catch anything.
|
|
|
|
This rule raises an issue when an ``++except++`` block catches every exception before a later ``++except++`` block could catch it.
|
|
|
|
=== Noncompliant code example
|
|
|
|
[source,python]
|
|
----
|
|
def foo():
|
|
try:
|
|
raise FloatingPointError()
|
|
except (ArithmeticError, RuntimeError) as e:
|
|
print(e)
|
|
except FloatingPointError as e: # Noncompliant. FloatingPointError is a subclass of ArithmeticError
|
|
print("Never executed")
|
|
except OverflowError as e: # Noncompliant. OverflowError is a subclass of ArithmeticError
|
|
print("Never executed")
|
|
|
|
try:
|
|
raise TypeError()
|
|
except TypeError as e:
|
|
print(e)
|
|
except TypeError as e: # Noncompliant. Duplicate Except.
|
|
print("Never executed")
|
|
|
|
try:
|
|
raise ValueError()
|
|
except BaseException as e:
|
|
print(e)
|
|
except: # Noncompliant. This is equivalent to "except BaseException" block
|
|
print("Never executed")
|
|
----
|
|
|
|
=== Compliant solution
|
|
|
|
[source,python]
|
|
----
|
|
def foo():
|
|
try:
|
|
raise FloatingPointError()
|
|
except FloatingPointError as e:
|
|
print("Executed")
|
|
except OverflowError as e:
|
|
print("Executed")
|
|
except (ArithmeticError, RuntimeError) as e:
|
|
print(e)
|
|
|
|
try:
|
|
raise TypeError()
|
|
except TypeError as e:
|
|
print(e)
|
|
|
|
try:
|
|
raise ValueError()
|
|
except BaseException as e:
|
|
print(e)
|
|
----
|
|
|
|
== Resources
|
|
|
|
* Python Documentation - https://docs.python.org/3/reference/compound_stmts.html#the-try-statement[The ``++try++`` statement]
|
|
|
|
ifdef::env-github,rspecator-view[]
|
|
|
|
'''
|
|
== Implementation Specification
|
|
(visible only on this page)
|
|
|
|
=== Highlighting
|
|
|
|
Primary:
|
|
|
|
* All exceptions which will never match because they are subclasses or duplicate of the first exception caught.
|
|
* The "except:" statement if "BaseException" is caught before.
|
|
|
|
Secondary:
|
|
|
|
* The exception class which shadows other except blocks.
|
|
message should be: 'Exceptions will be caught here.'
|
|
|
|
|
|
=== Message
|
|
|
|
* When a parent except block is caught before derived classes
|
|
* Catch this exception only once; it is already handled by a previous except clause.
|
|
* When the same exception class is caught multiple times:
|
|
* Catch this exception only once; it is already handled by a previous except clause.
|
|
* When an "BaseException" is caught in the same try-except as a bare "except:"
|
|
* Merge this bare "except:" with the "BaseException" catch
|
|
|
|
|
|
'''
|
|
== Comments And Links
|
|
(visible only on this page)
|
|
|
|
include::../comments-and-links.adoc[]
|
|
|
|
endif::env-github,rspecator-view[]
|