Exception chaining enables users to see if an exception was triggered by another exception (see PEP-3134). Exceptions are chained using either of the following syntax:
raise NewException() from chained_exception new_exception.__cause__ = chained_exception It is also possible to erase a chaining by setting new_exception.__cause__ = None or using except ... from None (see PEP-409).
Chaining will fail and raise a TypeError if something else than None or a valid exception, i.e. an instance of
BaseException or of a subclass, is provided.
class A:
pass
try:
raise ValueError("orig")
except ValueError as e:
new_exc = TypeError("new")
new_exc.__cause__ = A() # Noncompliant
raise new_exc
try:
raise ValueError("orig")
except ValueError as e:
raise TypeError("new") from "test" # Noncompliant
try:
raise ValueError("orig")
except ValueError as e:
new_exc = TypeError("new")
new_exc.__cause__ = None # Ok
raise new_exc
try:
raise ValueError("orig")
except ValueError as e:
new_exc = TypeError("new")
new_exc.__cause__ = e # Ok
raise new_exc
try:
raise ValueError("orig")
except ValueError as e:
raise TypeError("new") from None # Ok
try:
raise ValueError("orig")
except ValueError as e:
raise TypeError("new") from e # Ok