1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
|
from dataclasses import dataclass
from mypy.nodes import Block, NameExpr, PassStmt, TryStmt, TupleExpr
from refurb.error import Error
@dataclass
class ErrorInfo(Error):
"""
Often times you want to handle an exception and just ignore it. You can do
this with a `try`/`except` block with a single `pass` in the `except`
block, but there is a simpler and more concise way using the `suppress()`
function from `contextlib`:
Bad:
```
try:
f()
except FileNotFoundError:
pass
```
Good:
```
with suppress(FileNotFoundError):
f()
```
Note: `suppress()` is slower than using `try`/`except`, so for performance
critical code you might consider ignoring this check.
"""
name = "use-with-suppress"
code = 107
categories = ("contextlib", "readability")
def check(node: TryStmt, errors: list[Error]) -> None:
match node:
case TryStmt(
handlers=[Block(body=[PassStmt()])],
types=[types],
else_body=None,
finally_body=None,
):
match types:
case NameExpr(name=name):
inner = name
except_inner = f" {inner}"
case TupleExpr(items=items):
if any(not isinstance(item, NameExpr) for item in items):
return
inner = ", ".join(item.name for item in items) # type: ignore
except_inner = f" ({inner})"
case None:
inner = "BaseException"
except_inner = ""
case _:
return
errors.append(
ErrorInfo.from_node(
node,
f"Replace `try: ... except{except_inner}: pass` with `with suppress({inner}): ...`", # noqa: E501
)
)
|