
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.
121 lines
4.0 KiB
Plaintext
121 lines
4.0 KiB
Plaintext
== Why is this an issue?
|
|
|
|
Raising instances of https://docs.python.org/3/library/exceptions.html#Exception[``++Exception++``] and https://docs.python.org/3/library/exceptions.html#BaseException[``++BaseException++``] will have a negative impact on any code trying to catch these exceptions.
|
|
|
|
|
|
First, the only way to handle differently multiple Exceptions is to check their message, which is error-prone and difficult to maintain.
|
|
|
|
|
|
What's more, it becomes difficult to catch only your exception. The best practice is to catch only exceptions which require a specific handling. When you raise ``++Exception++`` or ``++BaseException++`` in a function the caller will have to add an ``++except Exception++`` or ``++except BaseException++`` and re-raise all exceptions which were unintentionally caught. This can create tricky bugs when the caller forgets to re-raise exceptions such as ``++SystemExit++`` and the software cannot be stopped.
|
|
|
|
|
|
It is recommended to either:
|
|
|
|
* raise a more specific https://docs.python.org/3/library/exceptions.html[Built-in exception] when one matches. For example ``++TypeError++`` should be raised when the type of a parameter is not the one expected.
|
|
* create a custom exception class deriving from ``++Exception++`` or one of its subclasses. A common practice for libraries is to have one custom root exception class from which every other custom exception class inherits. It enables other projects using this library to catch all errors coming from the library with a single "except" statement
|
|
|
|
This rule raises an issue when ``++Exception++`` or ``++BaseException++`` are raised.
|
|
|
|
=== Noncompliant code example
|
|
|
|
[source,python]
|
|
----
|
|
def process1():
|
|
raise BaseException("Wrong user input for field X") # Noncompliant
|
|
|
|
def process2():
|
|
raise BaseException("Wrong configuration") # Noncompliant
|
|
|
|
def process3(param):
|
|
if not isinstance(param, int):
|
|
raise Exception("param should be an integer") # Noncompliant
|
|
|
|
def caller():
|
|
try:
|
|
process1()
|
|
process2()
|
|
process3()
|
|
except BaseException as e:
|
|
if e.args[0] == "Wrong user input for field X":
|
|
# process error
|
|
pass
|
|
elif e.args[0] == "Wrong configuration":
|
|
# process error
|
|
pass
|
|
else:
|
|
# re-raise other exceptions
|
|
raise
|
|
----
|
|
|
|
=== Compliant solution
|
|
|
|
[source,python]
|
|
----
|
|
class MyProjectError(Exception):
|
|
"""Exception class from which every exception in this library will derive.
|
|
It enables other projects using this library to catch all errors coming
|
|
from the library with a single "except" statement
|
|
"""
|
|
pass
|
|
|
|
class BadUserInputError(MyProjectError):
|
|
"""A specific error"""
|
|
pass
|
|
|
|
class ConfigurationError(MyProjectError):
|
|
"""A specific error"""
|
|
pass
|
|
|
|
def process1():
|
|
raise BadUserInputError("Wrong user input for field X")
|
|
|
|
def process2():
|
|
raise ConfigurationError("Wrong configuration")
|
|
|
|
def process3(param):
|
|
if not isinstance(param, int):
|
|
raise TypeError("param should be an integer")
|
|
|
|
def caller():
|
|
try:
|
|
process1()
|
|
process2()
|
|
process3()
|
|
except BadUserInputError as e:
|
|
# process error
|
|
pass
|
|
except ConfigurationError as e:
|
|
# process error
|
|
pass
|
|
----
|
|
|
|
== Resources
|
|
|
|
* PEP 352 - https://www.python.org/dev/peps/pep-0352/#exception-hierarchy-changes[Required Superclass for Exceptions]
|
|
* Python Documentation - https://docs.python.org/3/library/exceptions.html#BaseException[Built-in exceptions]
|
|
* https://cwe.mitre.org/data/definitions/397[MITRE, CWE-397] - Declaration of Throws for Generic Exception
|
|
|
|
ifdef::env-github,rspecator-view[]
|
|
|
|
'''
|
|
== Implementation Specification
|
|
(visible only on this page)
|
|
|
|
=== Message
|
|
|
|
Replace this generic exception class with a more specific one.
|
|
|
|
|
|
=== Highlighting
|
|
|
|
The "Exception" or "BaseException" class instantiation
|
|
|
|
|
|
'''
|
|
== Comments And Links
|
|
(visible only on this page)
|
|
|
|
include::../comments-and-links.adoc[]
|
|
|
|
endif::env-github,rspecator-view[]
|