Skip to content
This repository was archived by the owner on Feb 19, 2023. It is now read-only.

Commit ca1fec6

Browse files
authored
Merge pull request #26 from vrserpa/generator_expressions_join_strings_check
Linting check of use of string join() with generator expression
2 parents 8be2d08 + f39b9fe commit ca1fec6

File tree

4 files changed

+118
-0
lines changed

4 files changed

+118
-0
lines changed

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ a linter for pandas usage, please see [pandas-vet](https://github.com/deppen8/pa
4040
| PDF021 | found 'np.bool' or 'np.object' (use 'np.bool_' or 'np.object_' instead) |
4141
| PDF022 | found import from 'numpy.random' |
4242
| PDF023 | found assignment to single-letter variable |
43+
| PDF024 | found string join() with generator expressions |
4344
## contributing
4445

4546
See `contributing.md` for how to get started.

pandas_dev_flaker/_ast_helpers.py

+17
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import ast
2+
import sys
23
from typing import Container, Dict, Sequence, Set
34

45

@@ -30,3 +31,19 @@ def check_for_wrong_alias(
3031
return name_.asname != alias
3132
else:
3233
return False
34+
35+
36+
def is_str_constant(
37+
node: ast.Call,
38+
) -> bool:
39+
return isinstance(node.func, ast.Attribute) and (
40+
(
41+
sys.version_info < (3, 8)
42+
and isinstance(node.func.value, ast.Str)
43+
)
44+
or (
45+
sys.version_info >= (3, 8)
46+
and isinstance(node.func.value, ast.Constant)
47+
and isinstance(node.func.value.value, str)
48+
)
49+
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
"""
2+
Based on
3+
4+
https://github.com/asottile/pyupgrade/blob/5fb168667ae73f157dd579344708e1cdfb0c0341/pyupgrade/_plugins/generator_expressions_pep289.py
5+
"""
6+
7+
import ast
8+
from typing import Iterator, Tuple
9+
10+
from pandas_dev_flaker._ast_helpers import is_str_constant
11+
from pandas_dev_flaker._data_tree import State, register
12+
13+
MSG = "PDF024 found string join() with generator expressions"
14+
15+
16+
@register(ast.Call)
17+
def visit_Call(
18+
state: State,
19+
node: ast.Call,
20+
parent: ast.AST,
21+
) -> Iterator[Tuple[int, int, str]]:
22+
if (
23+
isinstance(node.func, ast.Attribute)
24+
and node.func.attr == "join"
25+
and is_str_constant(node)
26+
and node.args
27+
and isinstance(node.args[0], ast.GeneratorExp)
28+
):
29+
yield (node.lineno, node.col_offset, MSG)

tests/generator_join_strings_test.py

+71
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
"""
2+
Based on
3+
4+
https://github.com/asottile/pyupgrade/blob/5fb168667ae73f157dd579344708e1cdfb0c0341/pyupgrade/_plugins/generator_expressions_pep289.py
5+
"""
6+
7+
import ast
8+
import tokenize
9+
from io import StringIO
10+
11+
import pytest
12+
13+
from pandas_dev_flaker.__main__ import run
14+
15+
16+
def results(s):
17+
return {
18+
"{}:{}: {}".format(*r)
19+
for r in run(
20+
ast.parse(s),
21+
list(tokenize.generate_tokens(StringIO(s).readline)),
22+
)
23+
}
24+
25+
26+
@pytest.mark.parametrize(
27+
"source",
28+
(
29+
pytest.param(
30+
"''.join([str(i) for i in range(5)])",
31+
id="String join() with list comprehension",
32+
),
33+
pytest.param(
34+
"''.join([\n"
35+
" str(i) for i in range(5)\n"
36+
" ]\n"
37+
")\n",
38+
id="String join() with multiline list comprehension",
39+
),
40+
),
41+
)
42+
def test_list_comprehensions(source):
43+
assert not results(source)
44+
45+
46+
@pytest.mark.parametrize(
47+
"source, expected",
48+
(
49+
pytest.param(
50+
"''.join(str(i) for i in range(5))",
51+
"1:0: PDF024 found string join() with generator expressions",
52+
id="String join() with generator expression",
53+
),
54+
pytest.param(
55+
"''.join((str(i) for i in range(5)))",
56+
"1:0: PDF024 found string join() with generator expressions",
57+
id="String join() with parenthesised generator expression",
58+
),
59+
pytest.param(
60+
"''.join((\n"
61+
" str(i) for i in range(5)\n"
62+
" )\n"
63+
")\n",
64+
"1:0: PDF024 found string join() with generator expressions",
65+
id="String join() with multiline generator expression",
66+
),
67+
),
68+
)
69+
def test_generator_expressions(source, expected):
70+
(result,) = results(source)
71+
assert result == expected

0 commit comments

Comments
 (0)