Skip to content

Commit 0796dfa

Browse files
Optionally disable consider-using-join for non-empty separator (#9129)
* Skip consider-using-join for non-empty separators Only suggest joining with separators when a new option 'suggest-join-with-non-empty-separator' is specified. Co-authored-by: Pierre Sassoulas <[email protected]>
1 parent 3afa971 commit 0796dfa

File tree

5 files changed

+63
-2
lines changed

5 files changed

+63
-2
lines changed

doc/user_guide/configuration/all-options.rst

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1196,6 +1196,14 @@ Standard Checkers
11961196
**Default:** ``('sys.exit', 'argparse.parse_error')``
11971197

11981198

1199+
--suggest-join-with-non-empty-separator
1200+
"""""""""""""""""""""""""""""""""""""""
1201+
*Let 'consider-using-join' be raised when the separator to join on would be non-empty (resulting in expected fixes of the type: ``"- " + "
1202+
- ".join(items)``)*
1203+
1204+
**Default:** ``True``
1205+
1206+
11991207

12001208
.. raw:: html
12011209

@@ -1211,6 +1219,8 @@ Standard Checkers
12111219
12121220
never-returning-functions = ["sys.exit", "argparse.parse_error"]
12131221
1222+
suggest-join-with-non-empty-separator = true
1223+
12141224
12151225
12161226
.. raw:: html

doc/whatsnew/fragments/8701.feature

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Skip ``consider-using-join`` check for non-empty separators if an ``suggest-join-with-non-empty-separator`` option is set to ``no``.
2+
3+
Closes #8701

pylint/checkers/refactoring/refactoring_checker.py

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -506,6 +506,19 @@ class RefactoringChecker(checkers.BaseTokenChecker):
506506
"and no message will be printed.",
507507
},
508508
),
509+
(
510+
"suggest-join-with-non-empty-separator",
511+
{
512+
"default": True,
513+
"type": "yn",
514+
"metavar": "<y or n>",
515+
"help": (
516+
"Let 'consider-using-join' be raised when the separator to "
517+
"join on would be non-empty (resulting in expected fixes "
518+
'of the type: ``"- " + "\n- ".join(items)``)'
519+
),
520+
},
521+
),
509522
)
510523

511524
def __init__(self, linter: PyLinter) -> None:
@@ -514,6 +527,7 @@ def __init__(self, linter: PyLinter) -> None:
514527
self._consider_using_with_stack = ConsiderUsingWithStack()
515528
self._init()
516529
self._never_returning_functions: set[str] = set()
530+
self._suggest_join_with_non_empty_separator: bool = False
517531

518532
def _init(self) -> None:
519533
self._nested_blocks: list[NodesWithNestedBlocks] = []
@@ -527,6 +541,9 @@ def open(self) -> None:
527541
self._never_returning_functions = set(
528542
self.linter.config.never_returning_functions
529543
)
544+
self._suggest_join_with_non_empty_separator = (
545+
self.linter.config.suggest_join_with_non_empty_separator
546+
)
530547

531548
@cached_property
532549
def _dummy_rgx(self) -> Pattern[str]:
@@ -1667,8 +1684,7 @@ def _dict_literal_suggestion(node: nodes.Call) -> str:
16671684
suggestion = ", ".join(elements)
16681685
return f"{{{suggestion}{', ... ' if len(suggestion) > 64 else ''}}}"
16691686

1670-
@staticmethod
1671-
def _name_to_concatenate(node: nodes.NodeNG) -> str | None:
1687+
def _name_to_concatenate(self, node: nodes.NodeNG) -> str | None:
16721688
"""Try to extract the name used in a concatenation loop."""
16731689
if isinstance(node, nodes.Name):
16741690
return cast("str | None", node.name)
@@ -1680,6 +1696,12 @@ def _name_to_concatenate(node: nodes.NodeNG) -> str | None:
16801696
]
16811697
if len(values) != 1 or not isinstance(values[0].value, nodes.Name):
16821698
return None
1699+
# If there are more values in joined string than formatted values,
1700+
# they are probably separators.
1701+
# Allow them only if the option `suggest-join-with-non-empty-separator` is set
1702+
with_separators = len(node.values) > len(values)
1703+
if with_separators and not self._suggest_join_with_non_empty_separator:
1704+
return None
16831705
return cast("str | None", values[0].value.name)
16841706

16851707
def _check_consider_using_join(self, aug_assign: nodes.AugAssign) -> None:
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# pylint: disable=missing-docstring,invalid-name,undefined-variable,multiple-statements
2+
3+
result = 'a'
4+
for number in ['1', '2', '3']:
5+
result += f'b{number}'
6+
assert result == 'ab1b2b3'
7+
assert result == 'b'.join(['a', '1', '2', '3'])
8+
9+
result = 'a'
10+
for number in ['1', '2', '3']:
11+
result += f'{number}c'
12+
assert result == 'a1c2c3c'
13+
assert result == 'a' + 'c'.join(['1', '2', '3']) + 'c'
14+
15+
result = 'a'
16+
for number in ['1', '2', '3']:
17+
result += f'b{number}c'
18+
assert result == 'ab1cb2cb3c'
19+
assert result == 'ab' + 'cb'.join(['1', '2', '3']) + 'c'
20+
21+
result = ''
22+
for number in ['1', '2', '3']:
23+
result += f"{number}, "
24+
result = result[:-2]
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
[variables]
2+
suggest-join-with-non-empty-separator=no

0 commit comments

Comments
 (0)