Skip to content

Commit 6ae2b77

Browse files
committed
'trailing-comma-tuple' check was added
This message is emitted when pylint finds an one-element tuple, created by a stray comma. This can suggest a potential problem in the code and it is recommended to use parantheses in order to emphasise the creation of a tuple, rather than relying on the comma itself. Close #300
1 parent 7aee3e3 commit 6ae2b77

File tree

6 files changed

+78
-3
lines changed

6 files changed

+78
-3
lines changed

ChangeLog

+7
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,13 @@ What's New in Pylint 2.0?
77

88
Release date: tba
99

10+
* 'trailing-comma-tuple' check was added
11+
12+
This message is emitted when pylint finds an one-element tuple,
13+
created by a stray comma. This can suggest a potential problem in the
14+
code and it is recommended to use parantheses in order to emphasise the
15+
creation of a tuple, rather than relying on the comma itself.
16+
1017
* Don't emit not-callable for instances with unknown bases.
1118

1219
Close #1213

doc/whatsnew/2.0.rst

+19
Original file line numberDiff line numberDiff line change
@@ -455,6 +455,25 @@ New checkers
455455
value = truth_value if condition else false_value
456456
457457
458+
* A new refactoring check was added, 'trailing-comma-tuple', which is emitted
459+
when pylint finds an one-element tuple, created by a stray comma. This can
460+
suggest a potential problem in the code and it is recommended to use parantheses
461+
in order to emphasise the creation of a tuple, rather than relying on the comma
462+
itself.
463+
464+
The warning is emitted for such a construct:
465+
466+
.. code-block:: python
467+
468+
a = 1,
469+
470+
The warning can be fixed by adding parantheses:
471+
472+
.. code-block:: python
473+
474+
a = (1, )
475+
476+
458477
Other Changes
459478
=============
460479

pylint/checkers/refactoring.py

+33-3
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
import collections
1212
import itertools
13+
import tokenize
1314

1415
import astroid
1516
from astroid import decorators
@@ -93,6 +94,14 @@ class RefactoringChecker(checkers.BaseTokenChecker):
9394
'following a chain of ifs, all of them containing a '
9495
'return statement.'
9596
),
97+
'R1707': ('Disallow trailing comma tuple',
98+
'trailing-comma-tuple',
99+
'In Python, a tuple is actually created by the comma symbol, '
100+
'not by the parentheses. Unfortunately, one can actually create a '
101+
'tuple by misplacing a trailing comma, which can lead to potential '
102+
'weird bugs in your code. You should always use parentheses '
103+
'explicitly for creating a tuple.',
104+
{'minversion': (3, 0)}),
96105
}
97106
options = (('max-nested-blocks',
98107
{'default': 5, 'type': 'int', 'metavar': '<int>',
@@ -196,11 +205,32 @@ def _check_simplifiable_if(self, node):
196205

197206
def process_tokens(self, tokens):
198207
# Process tokens and look for 'if' or 'elif'
199-
for _, token, _, _, _ in tokens:
200-
if token == 'elif':
208+
for index, token in enumerate(tokens):
209+
if token.string == 'elif':
201210
self._elifs.append(True)
202-
elif token == 'if':
211+
elif token.string == 'if':
203212
self._elifs.append(False)
213+
elif six.PY3 and token.exact_type == tokenize.COMMA:
214+
self._check_one_element_trailing_comma_tuple(tokens, token, index)
215+
216+
def _check_one_element_trailing_comma_tuple(self, tokens, token, index):
217+
left_tokens = itertools.islice(tokens, index + 1, None)
218+
same_line_tokens = (
219+
other_token for other_token in left_tokens
220+
if other_token.start[0] == token.start[0]
221+
)
222+
is_last_element = all(
223+
token.type in (tokenize.NEWLINE, tokenize.COMMENT)
224+
for token in same_line_tokens
225+
)
226+
if not is_last_element:
227+
return
228+
229+
assign_token = tokens[index-2:index-1]
230+
if assign_token and assign_token[0].string == '=':
231+
if self.linter.is_message_enabled('trailing-comma-tuple'):
232+
self.add_message('trailing-comma-tuple',
233+
line=token.start[0])
204234

205235
def leave_module(self, _):
206236
self._init()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
"""Check trailing comma one element tuples."""
2+
# pylint: disable=bad-whitespace
3+
AAA = 1, # [trailing-comma-tuple]
4+
BBB = "aaaa", # [trailing-comma-tuple]
5+
CCC="aaa", # [trailing-comma-tuple]
6+
7+
BBB = 1, 2
8+
CCC = (1, 2, 3)
9+
DDD = (
10+
1, 2, 3,
11+
)
12+
EEE = (
13+
"aaa",
14+
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
[testoptions]
2+
min_pyver=3.0
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
trailing-comma-tuple:3::Disallow trailing comma tuple
2+
trailing-comma-tuple:4::Disallow trailing comma tuple
3+
trailing-comma-tuple:5::Disallow trailing comma tuple

0 commit comments

Comments
 (0)