mirror of
https://github.com/astral-sh/ruff.git
synced 2025-09-29 13:25:17 +00:00

Improves error message for [except*](https://peps.python.org/pep-0654/) (Rules: B025, B029, B030, B904) Example python snippet: ```python try: a = 1 except* ValueError: a = 2 except* ValueError: a = 2 try: pass except* (): pass try: pass except* 1: # error pass try: raise ValueError except* ValueError: raise UserWarning ``` Error messages Before: ``` $ ruff check --select=B foo.py foo.py:6:9: B025 try-except block with duplicate exception `ValueError` foo.py:11:1: B029 Using `except ():` with an empty tuple does not catch anything; add exceptions to handle foo.py:16:9: B030 `except` handlers should only be exception classes or tuples of exception classes foo.py:22:5: B904 Within an `except` clause, raise exceptions with `raise ... from err` or `raise ... from None` to distinguish them from errors in exception handling Found 4 errors. ``` After: ``` $ ruff check --select=B foo.py foo.py:6:9: B025 try-except* block with duplicate exception `ValueError` foo.py:11:1: B029 Using `except* ():` with an empty tuple does not catch anything; add exceptions to handle foo.py:16:9: B030 `except*` handlers should only be exception classes or tuples of exception classes foo.py:22:5: B904 Within an `except*` clause, raise exceptions with `raise ... from err` or `raise ... from None` to distinguish them from errors in exception handling Found 4 errors. ``` Closes https://github.com/astral-sh/ruff/issues/14791 --------- Co-authored-by: Micha Reiser <micha@reiser.io>
152 lines
1.8 KiB
Python
152 lines
1.8 KiB
Python
"""
|
|
Should emit:
|
|
B030:
|
|
- line 12, column 8
|
|
- line 17, column 9
|
|
- line 22, column 21
|
|
- line 27, column 37
|
|
"""
|
|
|
|
try:
|
|
pass
|
|
except 1: # Error
|
|
pass
|
|
|
|
try:
|
|
pass
|
|
except (1, ValueError): # Error
|
|
pass
|
|
|
|
try:
|
|
pass
|
|
except (ValueError, (RuntimeError, (KeyError, TypeError))): # Error
|
|
pass
|
|
|
|
try:
|
|
pass
|
|
except (ValueError, *(RuntimeError, (KeyError, TypeError))): # Error
|
|
pass
|
|
|
|
|
|
try:
|
|
pass
|
|
except (*a, *(RuntimeError, (KeyError, TypeError))): # Error
|
|
pass
|
|
|
|
|
|
try:
|
|
pass
|
|
except* a + (RuntimeError, (KeyError, TypeError)): # Error
|
|
pass
|
|
|
|
|
|
try:
|
|
pass
|
|
except (ValueError, *(RuntimeError, TypeError)): # OK
|
|
pass
|
|
|
|
try:
|
|
pass
|
|
except (ValueError, *[RuntimeError, *(TypeError,)]): # OK
|
|
pass
|
|
|
|
|
|
try:
|
|
pass
|
|
except (*a, *b): # OK
|
|
pass
|
|
|
|
|
|
try:
|
|
pass
|
|
except (*a, *(RuntimeError, TypeError)): # OK
|
|
pass
|
|
|
|
|
|
try:
|
|
pass
|
|
except (*a, *(b, c)): # OK
|
|
pass
|
|
|
|
|
|
try:
|
|
pass
|
|
except (*a, *(*b, *c)): # OK
|
|
pass
|
|
|
|
|
|
def what_to_catch():
|
|
return ...
|
|
|
|
|
|
try:
|
|
pass
|
|
except what_to_catch(): # OK
|
|
pass
|
|
|
|
|
|
try:
|
|
pass
|
|
except (a, b) + (c, d): # OK
|
|
pass
|
|
|
|
|
|
try:
|
|
pass
|
|
except* (a, b) + (c, d): # OK
|
|
pass
|
|
|
|
|
|
try:
|
|
pass
|
|
except* (a, (b) + (c)): # OK
|
|
pass
|
|
|
|
|
|
try:
|
|
pass
|
|
except (a, b) + (c, d) + (e, f): # OK
|
|
pass
|
|
|
|
|
|
try:
|
|
pass
|
|
except a + (b, c): # OK
|
|
pass
|
|
|
|
|
|
try:
|
|
pass
|
|
except (ValueError, *(RuntimeError, TypeError), *((ArithmeticError,) + (EOFError,))):
|
|
pass
|
|
|
|
|
|
try:
|
|
pass
|
|
except ((a, b) + (c, d)) + ((e, f) + (g)): # OK
|
|
pass
|
|
|
|
try:
|
|
pass
|
|
except (a, b) * (c, d): # B030
|
|
pass
|
|
|
|
try:
|
|
pass
|
|
except* 1: # Error
|
|
pass
|
|
|
|
try:
|
|
pass
|
|
except* (1, ValueError): # Error
|
|
pass
|
|
|
|
try:
|
|
pass
|
|
except* (ValueError, (RuntimeError, (KeyError, TypeError))): # Error
|
|
pass
|
|
|
|
try:
|
|
pass
|
|
except* (a, b) * (c, d): # B030
|
|
pass
|