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:

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.

Noncompliant Code Example

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

Compliant Solution

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

See