Skip to content

Commit

Permalink
Improve error message output:
Browse files Browse the repository at this point in the history
* Stringify args for FURB123
* Use double quotes for byte exprs
  • Loading branch information
dosisod committed Jan 10, 2024
1 parent 559e9b3 commit dbad1ea
Show file tree
Hide file tree
Showing 10 changed files with 100 additions and 62 deletions.
38 changes: 36 additions & 2 deletions refurb/checks/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@
BytesExpr,
CallExpr,
ComparisonExpr,
ComplexExpr,
DictExpr,
DictionaryComprehension,
Expression,
FloatExpr,
ForStmt,
GeneratorExpr,
IndexExpr,
Expand All @@ -26,6 +28,7 @@
SliceExpr,
StarExpr,
Statement,
StrExpr,
TupleExpr,
UnaryExpr,
)
Expand Down Expand Up @@ -291,12 +294,43 @@ def _stringify(node: Node) -> str:

case BytesExpr(value=value):
# TODO: use same formatting as source line
return repr(value.encode())
value = value.replace('"', r"\"")

return f'b"{value}"'

case IntExpr(value=value):
# TODO: use same formatting as source line
return str(value)

case ComplexExpr(value=value):
# TODO: use same formatting as source line
return str(value)

case FloatExpr(value=value):
return str(value)

case StrExpr(value=value):
value = value.replace('"', r"\"")

return f'"{value}"'

case DictExpr(items=items):
parts: list[str] = []

for k, v in items:
if k:
parts.append(f"{stringify(k)}: {stringify(v)}")

else:
parts.append(f"**{stringify(v)}")

return f"{{{', '.join(parts)}}}"

case TupleExpr(items=items):
inner = ", ".join(stringify(x) for x in items)

return f"({inner})"

case CallExpr():
name = _stringify(node.callee)

Expand All @@ -308,7 +342,7 @@ def _stringify(node: Node) -> str:
return f"{_stringify(left)} {op} {_stringify(right)}"

case ComparisonExpr():
parts: list[str] = []
parts = []

for op, operand in zip(node.operators, node.operands):
parts.extend((_stringify(operand), op))
Expand Down
35 changes: 18 additions & 17 deletions refurb/checks/readability/no_unnecessary_cast.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
Var,
)

from refurb.checks.common import stringify
from refurb.error import Error


Expand Down Expand Up @@ -59,16 +60,16 @@ class ErrorInfo(Error):


FUNC_NAMES = {
"builtins.bool": (None, "x"),
"builtins.bytes": (BytesExpr, "x"),
"builtins.complex": (ComplexExpr, "x"),
"builtins.dict": (DictExpr, "x.copy()"),
"builtins.float": (FloatExpr, "x"),
"builtins.int": (IntExpr, "x"),
"builtins.list": (ListExpr, "x.copy()"),
"builtins.str": (StrExpr, "x"),
"builtins.tuple": (TupleExpr, "x"),
"tuple[]": (TupleExpr, "x"),
"builtins.bool": (None, ""),
"builtins.bytes": (BytesExpr, ""),
"builtins.complex": (ComplexExpr, ""),
"builtins.dict": (DictExpr, ".copy()"),
"builtins.float": (FloatExpr, ""),
"builtins.int": (IntExpr, ""),
"builtins.list": (ListExpr, ".copy()"),
"builtins.str": (StrExpr, ""),
"builtins.tuple": (TupleExpr, ""),
"tuple[]": (TupleExpr, ""),
}


Expand All @@ -86,13 +87,9 @@ def check(node: CallExpr, errors: list[Error]) -> None:
args=[arg],
arg_kinds=[arg_kind],
) if arg_kind != ArgKind.ARG_STAR2 and fullname in FUNC_NAMES:
node_type, msg = FUNC_NAMES[fullname]
node_type, suffix = FUNC_NAMES[fullname]

if type(arg) == node_type:
if isinstance(arg, DictExpr | ListExpr):
msg = "x"

elif is_boolean_literal(arg) and name == "bool":
if (type(arg) == node_type) or (is_boolean_literal(arg) and name == "bool"):
pass

else:
Expand All @@ -106,4 +103,8 @@ def check(node: CallExpr, errors: list[Error]) -> None:
case _:
return

errors.append(ErrorInfo.from_node(node, f"Replace `{name}(x)` with `{msg}`"))
expr = stringify(arg)

msg = f"Replace `{name}({stringify(arg)})` with `{expr}{suffix}`"

errors.append(ErrorInfo.from_node(node, msg))
2 changes: 1 addition & 1 deletion test/data/bug_cast.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
test/data/bug_cast.py:7:11 [FURB123]: Replace `int(x)` with `x`
test/data/bug_cast.py:7:11 [FURB123]: Replace `int(0)` with `0`
2 changes: 1 addition & 1 deletion test/data/bug_type_reassignment.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
test/data/bug_type_reassignment.py:18:6 [FURB123]: Replace `str(x)` with `x`
test/data/bug_type_reassignment.py:18:6 [FURB123]: Replace `str(x2)` with `x2`
34 changes: 17 additions & 17 deletions test/data/err_123.txt
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
test/data/err_123.py:3:5 [FURB123]: Replace `bool(x)` with `x`
test/data/err_123.py:4:5 [FURB123]: Replace `bytes(x)` with `x`
test/data/err_123.py:5:5 [FURB123]: Replace `complex(x)` with `x`
test/data/err_123.py:6:5 [FURB123]: Replace `dict(x)` with `x`
test/data/err_123.py:7:5 [FURB123]: Replace `float(x)` with `x`
test/data/err_123.py:8:5 [FURB123]: Replace `list(x)` with `x`
test/data/err_123.py:9:5 [FURB123]: Replace `str(x)` with `x`
test/data/err_123.py:10:5 [FURB123]: Replace `tuple(x)` with `x`
test/data/err_123.py:11:5 [FURB123]: Replace `int(x)` with `x`
test/data/err_123.py:14:5 [FURB123]: Replace `bool(x)` with `x`
test/data/err_123.py:17:5 [FURB123]: Replace `bytes(x)` with `x`
test/data/err_123.py:20:5 [FURB123]: Replace `complex(x)` with `x`
test/data/err_123.py:23:5 [FURB123]: Replace `dict(x)` with `x.copy()`
test/data/err_123.py:26:5 [FURB123]: Replace `float(x)` with `x`
test/data/err_123.py:29:5 [FURB123]: Replace `list(x)` with `x.copy()`
test/data/err_123.py:32:5 [FURB123]: Replace `str(x)` with `x`
test/data/err_123.py:35:5 [FURB123]: Replace `tuple(x)` with `x`
test/data/err_123.py:3:5 [FURB123]: Replace `bool(True)` with `True`
test/data/err_123.py:4:5 [FURB123]: Replace `bytes(b"hello world")` with `b"hello world"`
test/data/err_123.py:5:5 [FURB123]: Replace `complex(1j)` with `1j`
test/data/err_123.py:6:5 [FURB123]: Replace `dict({"a": 1})` with `{"a": 1}.copy()`
test/data/err_123.py:7:5 [FURB123]: Replace `float(123.456)` with `123.456`
test/data/err_123.py:8:5 [FURB123]: Replace `list([1, 2, 3])` with `[1, 2, 3].copy()`
test/data/err_123.py:9:5 [FURB123]: Replace `str("hello world")` with `"hello world"`
test/data/err_123.py:10:5 [FURB123]: Replace `tuple((1, 2, 3))` with `(1, 2, 3)`
test/data/err_123.py:11:5 [FURB123]: Replace `int(123)` with `123`
test/data/err_123.py:14:5 [FURB123]: Replace `bool(a)` with `a`
test/data/err_123.py:17:5 [FURB123]: Replace `bytes(b)` with `b`
test/data/err_123.py:20:5 [FURB123]: Replace `complex(c)` with `c`
test/data/err_123.py:23:5 [FURB123]: Replace `dict(d)` with `d.copy()`
test/data/err_123.py:26:5 [FURB123]: Replace `float(e)` with `e`
test/data/err_123.py:29:5 [FURB123]: Replace `list(f)` with `f.copy()`
test/data/err_123.py:32:5 [FURB123]: Replace `str(g)` with `g`
test/data/err_123.py:35:5 [FURB123]: Replace `tuple(t)` with `t`
2 changes: 1 addition & 1 deletion test/data/err_181.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,6 @@ test/data/err_181.py:30:1 [FURB181]: Replace `sha512().digest().hex()` with `sha
test/data/err_181.py:31:1 [FURB181]: Replace `shake_128().digest(10).hex()` with `shake_128().hexdigest(10)`
test/data/err_181.py:32:1 [FURB181]: Replace `shake_256().digest(10).hex()` with `shake_256().hexdigest(10)`
test/data/err_181.py:34:1 [FURB181]: Replace `hashlib.sha256().digest().hex()` with `hashlib.sha256().hexdigest()`
test/data/err_181.py:36:1 [FURB181]: Replace `sha256(b'text').digest().hex()` with `sha256(b'text').hexdigest()`
test/data/err_181.py:36:1 [FURB181]: Replace `sha256(b"text").digest().hex()` with `sha256(b"text").hexdigest()`
test/data/err_181.py:38:1 [FURB181]: Replace `hash_algo().digest().hex()` with `hash_algo().hexdigest()`
test/data/err_181.py:41:1 [FURB181]: Replace `h.digest().hex()` with `h.hexdigest()`
32 changes: 16 additions & 16 deletions test/data/err_182.txt
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
test/data/err_182.py:19:1 [FURB182]: Replace `h1 = blake2b(); h1.update(b'data')` with `h1 = blake2b(b'data')`
test/data/err_182.py:22:1 [FURB182]: Replace `h2 = blake2s(); h2.update(b'data')` with `h2 = blake2s(b'data')`
test/data/err_182.py:25:1 [FURB182]: Replace `h3 = md5(); h3.update(b'data')` with `h3 = md5(b'data')`
test/data/err_182.py:28:1 [FURB182]: Replace `h4 = sha1(); h4.update(b'data')` with `h4 = sha1(b'data')`
test/data/err_182.py:31:1 [FURB182]: Replace `h5 = sha224(); h5.update(b'data')` with `h5 = sha224(b'data')`
test/data/err_182.py:34:1 [FURB182]: Replace `h6 = sha256(); h6.update(b'data')` with `h6 = sha256(b'data')`
test/data/err_182.py:37:1 [FURB182]: Replace `h7 = sha384(); h7.update(b'data')` with `h7 = sha384(b'data')`
test/data/err_182.py:40:1 [FURB182]: Replace `h8 = sha3_224(); h8.update(b'data')` with `h8 = sha3_224(b'data')`
test/data/err_182.py:43:1 [FURB182]: Replace `h9 = sha3_256(); h9.update(b'data')` with `h9 = sha3_256(b'data')`
test/data/err_182.py:46:1 [FURB182]: Replace `h10 = sha3_384(); h10.update(b'data')` with `h10 = sha3_384(b'data')`
test/data/err_182.py:49:1 [FURB182]: Replace `h11 = sha3_512(); h11.update(b'data')` with `h11 = sha3_512(b'data')`
test/data/err_182.py:52:1 [FURB182]: Replace `h12 = sha512(); h12.update(b'data')` with `h12 = sha512(b'data')`
test/data/err_182.py:55:1 [FURB182]: Replace `h13 = shake_128(); h13.update(b'data')` with `h13 = shake_128(b'data')`
test/data/err_182.py:58:1 [FURB182]: Replace `h14 = shake_256(); h14.update(b'data')` with `h14 = shake_256(b'data')`
test/data/err_182.py:61:1 [FURB182]: Replace `h15 = hashlib.sha256(); h15.update(b'data')` with `h15 = hashlib.sha256(b'data')`
test/data/err_182.py:64:1 [FURB182]: Replace `h16 = hash_algo(); h16.update(b'data')` with `h16 = hash_algo(b'data')`
test/data/err_182.py:19:1 [FURB182]: Replace `h1 = blake2b(); h1.update(b"data")` with `h1 = blake2b(b"data")`
test/data/err_182.py:22:1 [FURB182]: Replace `h2 = blake2s(); h2.update(b"data")` with `h2 = blake2s(b"data")`
test/data/err_182.py:25:1 [FURB182]: Replace `h3 = md5(); h3.update(b"data")` with `h3 = md5(b"data")`
test/data/err_182.py:28:1 [FURB182]: Replace `h4 = sha1(); h4.update(b"data")` with `h4 = sha1(b"data")`
test/data/err_182.py:31:1 [FURB182]: Replace `h5 = sha224(); h5.update(b"data")` with `h5 = sha224(b"data")`
test/data/err_182.py:34:1 [FURB182]: Replace `h6 = sha256(); h6.update(b"data")` with `h6 = sha256(b"data")`
test/data/err_182.py:37:1 [FURB182]: Replace `h7 = sha384(); h7.update(b"data")` with `h7 = sha384(b"data")`
test/data/err_182.py:40:1 [FURB182]: Replace `h8 = sha3_224(); h8.update(b"data")` with `h8 = sha3_224(b"data")`
test/data/err_182.py:43:1 [FURB182]: Replace `h9 = sha3_256(); h9.update(b"data")` with `h9 = sha3_256(b"data")`
test/data/err_182.py:46:1 [FURB182]: Replace `h10 = sha3_384(); h10.update(b"data")` with `h10 = sha3_384(b"data")`
test/data/err_182.py:49:1 [FURB182]: Replace `h11 = sha3_512(); h11.update(b"data")` with `h11 = sha3_512(b"data")`
test/data/err_182.py:52:1 [FURB182]: Replace `h12 = sha512(); h12.update(b"data")` with `h12 = sha512(b"data")`
test/data/err_182.py:55:1 [FURB182]: Replace `h13 = shake_128(); h13.update(b"data")` with `h13 = shake_128(b"data")`
test/data/err_182.py:58:1 [FURB182]: Replace `h14 = shake_256(); h14.update(b"data")` with `h14 = shake_256(b"data")`
test/data/err_182.py:61:1 [FURB182]: Replace `h15 = hashlib.sha256(); h15.update(b"data")` with `h15 = hashlib.sha256(b"data")`
test/data/err_182.py:64:1 [FURB182]: Replace `h16 = hash_algo(); h16.update(b"data")` with `h16 = hash_algo(b"data")`
14 changes: 7 additions & 7 deletions test/data/inline_comments.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
test/data/inline_comments.py:18:5 [FURB123]: Replace `int(x)` with `x`
test/data/inline_comments.py:19:5 [FURB123]: Replace `int(x)` with `x`
test/data/inline_comments.py:20:5 [FURB123]: Replace `int(x)` with `x`
test/data/inline_comments.py:21:5 [FURB123]: Replace `int(x)` with `x`
test/data/inline_comments.py:22:5 [FURB123]: Replace `int(x)` with `x`
test/data/inline_comments.py:23:5 [FURB123]: Replace `str(x)` with `x`
test/data/inline_comments.py:24:5 [FURB123]: Replace `str(x)` with `x`
test/data/inline_comments.py:18:5 [FURB123]: Replace `int(0)` with `0`
test/data/inline_comments.py:19:5 [FURB123]: Replace `int(0)` with `0`
test/data/inline_comments.py:20:5 [FURB123]: Replace `int(0)` with `0`
test/data/inline_comments.py:21:5 [FURB123]: Replace `int(0)` with `0`
test/data/inline_comments.py:22:5 [FURB123]: Replace `int(0)` with `0`
test/data/inline_comments.py:23:5 [FURB123]: Replace `str("# noqa: FURB123 ")` with `"# noqa: FURB123 "`
test/data/inline_comments.py:24:5 [FURB123]: Replace `str("# noqa: FURB123 ")` with `"# noqa: FURB123 "`
2 changes: 2 additions & 0 deletions test/data/stringify.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# test double star in dict expr
_ = dict({**{}})
1 change: 1 addition & 0 deletions test/data/stringify.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
test/data/stringify.py:2:5 [FURB123]: Replace `dict({**{}})` with `{**{}}.copy()`

0 comments on commit dbad1ea

Please sign in to comment.