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>
99 lines
2 KiB
Python
99 lines
2 KiB
Python
"""
|
|
Should emit:
|
|
B904 - on lines 10, 11, 16, 62, 64, 79, 81, 87, 88, 93 and 97
|
|
"""
|
|
|
|
try:
|
|
raise ValueError
|
|
except ValueError:
|
|
if "abc":
|
|
raise TypeError
|
|
raise UserWarning
|
|
except AssertionError:
|
|
raise # Bare `raise` should not be an error
|
|
except Exception as err:
|
|
assert err
|
|
raise Exception("No cause here...")
|
|
except BaseException as err:
|
|
raise err
|
|
except BaseException as err:
|
|
raise some_other_err
|
|
finally:
|
|
raise Exception("Nothing to chain from, so no warning here")
|
|
|
|
try:
|
|
raise ValueError
|
|
except ValueError:
|
|
# should not emit, since we are not raising something
|
|
def proxy():
|
|
raise NameError
|
|
|
|
|
|
try:
|
|
from preferred_library import Thing
|
|
except ImportError:
|
|
try:
|
|
from fallback_library import Thing
|
|
except ImportError:
|
|
|
|
class Thing:
|
|
def __getattr__(self, name):
|
|
# same as the case above, should not emit.
|
|
raise AttributeError
|
|
|
|
|
|
try:
|
|
from preferred_library import Thing
|
|
except ImportError:
|
|
try:
|
|
from fallback_library import Thing
|
|
except ImportError:
|
|
|
|
def context_switch():
|
|
try:
|
|
raise ValueError
|
|
except ValueError:
|
|
raise
|
|
|
|
|
|
try:
|
|
...
|
|
except Exception as e:
|
|
if ...:
|
|
raise RuntimeError("boom!")
|
|
else:
|
|
raise RuntimeError("bang!")
|
|
|
|
|
|
try:
|
|
...
|
|
except Exception as e:
|
|
match 0:
|
|
case 0:
|
|
raise RuntimeError("boom!")
|
|
|
|
try:
|
|
...
|
|
except* Exception as e:
|
|
if ...:
|
|
raise RuntimeError("boom!")
|
|
else:
|
|
raise RuntimeError("bang!")
|
|
|
|
try:
|
|
raise ValueError
|
|
except* ValueError:
|
|
if "abc":
|
|
raise TypeError
|
|
raise UserWarning
|
|
except* AssertionError:
|
|
raise # Bare `raise` should not be an error
|
|
except* Exception as err:
|
|
assert err
|
|
raise Exception("No cause here...")
|
|
except* BaseException as err:
|
|
raise err
|
|
except* BaseException as err:
|
|
raise some_other_err
|
|
finally:
|
|
raise Exception("Nothing to chain from, so no warning here")
|