From 499412903fa1497ddd04f55b23822c3b014fec8e Mon Sep 17 00:00:00 2001 From: dosisod <39638017+dosisod@users.noreply.github.com> Date: Sun, 17 Dec 2023 22:40:03 -0800 Subject: [PATCH] Fix FURB183 false positive when using custom formatter --- refurb/checks/readability/use_str_func.py | 23 ++++++++++++++++++++++- test/data/err_183.py | 2 ++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/refurb/checks/readability/use_str_func.py b/refurb/checks/readability/use_str_func.py index fe80625..d8d5c85 100644 --- a/refurb/checks/readability/use_str_func.py +++ b/refurb/checks/readability/use_str_func.py @@ -5,6 +5,7 @@ from refurb.checks.common import stringify from refurb.checks.string.use_fstring_fmt import CONVERSIONS as FURB_119_FUNCS from refurb.error import Error +from refurb.visitor import TraverserVisitor @dataclass @@ -36,6 +37,14 @@ class ErrorInfo(Error): ignore = set[int]() +# TODO: add support for returning False from check to indicate it shouldnt prapogate +class NestedFstringIgnorer(TraverserVisitor): + def visit_call_expr(self, o: CallExpr) -> None: + ignore.add(id(o)) + + super().visit_call_expr(o) + + def check(node: CallExpr, errors: list[Error]) -> None: if id(node) in ignore: return @@ -48,7 +57,10 @@ def check(node: CallExpr, errors: list[Error]) -> None: ), args=[ListExpr(items=items)], ): - ignore.update(id(item) for item in items) + visitor = NestedFstringIgnorer() + + for item in items: + visitor.accept(item) case CallExpr( callee=MemberExpr( @@ -66,3 +78,12 @@ def check(node: CallExpr, errors: list[Error]) -> None: msg = f'Replace `f"{{{x}}}"` with `str({x})`' errors.append(ErrorInfo.from_node(node, msg)) + + case CallExpr( + callee=MemberExpr( + expr=StrExpr(value="{:{}}"), + name="format", + ), + args=[_, arg], + ): + NestedFstringIgnorer().accept(arg) diff --git a/test/data/err_183.py b/test/data/err_183.py index 423d35d..9ab948f 100644 --- a/test/data/err_183.py +++ b/test/data/err_183.py @@ -10,3 +10,5 @@ f"hello{x}world" f"{x} {x}" + +f"{x:{x}}"