Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Misleading descriptions for raise-from exception chaining rules (B904 and TRY200) #8736

Closed
theemathas opened this issue Nov 17, 2023 · 1 comment · Fixed by #9680
Closed
Labels
documentation Improvements or additions to documentation good first issue Good for newcomers
Milestone

Comments

@theemathas
Copy link

In my understanding, the description pages for rules B904 and TRY200 say (paraphrased): "Re-raising an exception (i.e., catching an exception and then raising a different exception) without specifying a cause with the from keyword will make the raised exception not be chained, which means we won't have the full stack trace information."

This is incorrect. As per the official documentation, if an exception is re-raised without explicit chaining, it will be implicitly chained with the caught exception. Therefore, a re-raised exception without explicit chaining (which the linter rule says is bad) has similar behavior as explicit chaining (which the linter rule recommends). The main difference seems to be a slight difference in the wording of the stack trace. This behavior was not as well-documented in previous python versions, but it has been like this since at least version 3.5.9, if not older.

Side note: the fact that these two lint rules are duplicates is a known issue as per #2186

@zanieb
Copy link
Member

zanieb commented Nov 17, 2023

For those who are unfamiliar, here are the various outputs:

Implicit chaining

try:
    raise ValueError(1)
except Exception:
    raise ValueError(2)
Traceback (most recent call last):
  File "example.py", line 2, in <module>
    raise ValueError(1)
ValueError: 1

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "example.py", line 4, in <module>
    raise ValueError(2)
ValueError: 2

Explicit chaining

try:
    raise ValueError(1)
except Exception as exc:
    raise ValueError(2) from exc
Traceback (most recent call last):
  File "example.py", line 19, in <module>
    raise ValueError(1)
ValueError: 1

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "example.py", line 21, in <module>
    raise ValueError(2) from exc
ValueError: 2

Explicit break of chain

try:
    raise ValueError(1)
except Exception:
    raise ValueError(2) from None
Traceback (most recent call last):
  File "example.py", line 39, in <module>
    raise ValueError(2) from None
ValueError: 2

I agree the rule documentation is confusing as written. However "During handling of the above exception, another exception occurred" and "The above exception was the direct cause of the following exception" signal different things to a user. Intentionally raising an exception in an except block should always use from for clarity. It'd be great to update the documentation for these rules and add some examples

@zanieb zanieb added the documentation Improvements or additions to documentation label Nov 17, 2023
@charliermarsh charliermarsh mentioned this issue Jan 11, 2024
13 tasks
@MichaReiser MichaReiser added this to the v0.2.0 milestone Jan 19, 2024
@zanieb zanieb added the good first issue Good for newcomers label Jan 30, 2024
@zanieb zanieb mentioned this issue Jan 30, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation Improvements or additions to documentation good first issue Good for newcomers
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants