-
Notifications
You must be signed in to change notification settings - Fork 33
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Use ast to find candidate fstring expressions (#183)
* draft code between * fix range * rufff? * code_in_chunk + test * test cases for code_between * fix line num, more tests * rely more on original source code - for quote type * replace unneeded generator * ruff * WIP 106 failing * WIP 20 failing * WIP 8 failing * WIP 6 failing * WIP 4 failing * WIP 2 failing * it works! * rufff * black! * drop python 3.7; use legacy @cache
- Loading branch information
Showing
13 changed files
with
200 additions
and
28 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
import ast | ||
from typing import List | ||
|
||
from flynt.state import State | ||
|
||
from .ast_chunk import AstChunk | ||
|
||
|
||
def is_call_format(node): | ||
return ( | ||
isinstance(node, ast.Call) | ||
and isinstance(node.func, ast.Attribute) | ||
and node.func.attr == "format" | ||
and isinstance(node.func.value, (ast.Str, ast.Name)) | ||
) | ||
|
||
|
||
class CallFmtFinder(ast.NodeVisitor): | ||
def __init__(self) -> None: | ||
super().__init__() | ||
self.candidates: List[AstChunk] = [] | ||
|
||
def visit_Call(self, node: ast.Call) -> None: | ||
""" | ||
Finds all nodes that are string concatenations with a literal. | ||
""" | ||
if is_call_format(node): | ||
self.candidates.append(AstChunk(node)) | ||
else: | ||
self.generic_visit(node) | ||
|
||
|
||
def call_candidates(code: str, state: State) -> List[AstChunk]: | ||
tree = ast.parse(code) | ||
|
||
finder = CallFmtFinder() | ||
finder.visit(tree) | ||
|
||
state.call_candidates += len(finder.candidates) | ||
return finder.candidates |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
import ast | ||
from typing import List | ||
|
||
from flynt.state import State | ||
|
||
from .ast_chunk import AstChunk | ||
|
||
|
||
def is_percent_format(node): | ||
return ( | ||
isinstance(node, ast.BinOp) | ||
and isinstance(node.op, ast.Mod) | ||
and isinstance(node.left, ast.Str) | ||
) | ||
|
||
|
||
class PercentFmtFinder(ast.NodeVisitor): | ||
def __init__(self) -> None: | ||
super().__init__() | ||
self.candidates: List[AstChunk] = [] | ||
|
||
def visit_BinOp(self, node: ast.BinOp) -> None: | ||
""" | ||
Finds all nodes that are string concatenations with a literal. | ||
""" | ||
if is_percent_format(node): | ||
self.candidates.append(AstChunk(node)) | ||
else: | ||
self.generic_visit(node) | ||
|
||
|
||
def percent_candidates(code: str, state: State) -> List[AstChunk]: | ||
tree = ast.parse(code) | ||
|
||
finder = PercentFmtFinder() | ||
finder.visit(tree) | ||
|
||
state.percent_candidates += len(finder.candidates) | ||
|
||
return finder.candidates |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
import pytest | ||
|
||
from flynt.candidates import split | ||
from flynt.code_editor import CodeEditor | ||
from flynt.format import get_quote_type | ||
|
||
s0 = """'%s' % ( | ||
v['key'])""" | ||
s1 = """s = '%s' % ( | ||
v['key'])""" | ||
|
||
s2 = """\"%(a)-6d %(a)s" % d""" | ||
|
||
|
||
@pytest.mark.parametrize( | ||
"s_in", | ||
[s1, s2], | ||
) | ||
def test_code_between_qoute_types(s_in): | ||
|
||
chunk = set(split.get_fstringify_chunks(s_in)).pop() | ||
editor = CodeEditor(s_in, None, lambda *args: None, None) | ||
|
||
assert get_quote_type(editor.code_in_chunk(chunk)) == get_quote_type(str(chunk)) | ||
|
||
|
||
@pytest.mark.parametrize( | ||
"s_in", | ||
[s0, s2], | ||
) | ||
def test_code_between_exact(s_in): | ||
chunk = set(split.get_fstringify_chunks(s_in)).pop() | ||
editor = CodeEditor(s_in, None, lambda *args: None, None) | ||
|
||
assert editor.code_in_chunk(chunk) == s_in |
Oops, something went wrong.