Skip to content

Commit 06bc0a6

Browse files
ksaketouDanielNoordPierre-Sassoulas
authored
Add new message called duplicate-value for sets (#5928)
Adds some new functionality which checks for duplicate values inside sets. For that reason, we create a new message called duplicate-value. Co-authored-by: Daniël van Noord <[email protected]> Co-authored-by: Pierre Sassoulas <[email protected]>
1 parent 79f3e1d commit 06bc0a6

File tree

8 files changed

+61
-5
lines changed

8 files changed

+61
-5
lines changed

ChangeLog

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@ Release date: TBA
4040

4141
* Fix bug where specifically enabling just ``await-outside-async`` was not possible.
4242

43+
* Added new message called ``duplicate-value`` which identifies duplicate values inside sets.
44+
45+
Closes #5880
46+
4347
..
4448
Insert your changelog randomly, it will reduce merge conflicts
4549
(Ie. not necessarily at the end)
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
incorrect_set = {'value1', 23, 5, 'value1'} # [duplicate-value]
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
correct_set = {'value1', 23, 5}

doc/whatsnew/2.14.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@ New checkers
2727

2828
Closes #4525
2929

30+
* Added new message called ``duplicate-value`` which identifies duplicate values inside sets.
31+
32+
Closes #5880
33+
3034
Removed checkers
3135
================
3236

pylint/checkers/base/basic_checker.py

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
from pylint import interfaces
1616
from pylint import utils as lint_utils
1717
from pylint.checkers import BaseChecker, utils
18-
from pylint.interfaces import IAstroidChecker
18+
from pylint.interfaces import HIGH, IAstroidChecker
1919
from pylint.reporters.ureports import nodes as reporter_nodes
2020
from pylint.utils import LinterStats
2121
from pylint.utils.utils import get_global_option
@@ -246,6 +246,11 @@ class BasicChecker(_BasicChecker):
246246
"Used when an assert statement has a string literal as its first argument, which will "
247247
"cause the assert to always pass.",
248248
),
249+
"W0130": (
250+
"Duplicate value %r in set",
251+
"duplicate-value",
252+
"This message is emitted when a set contains the same value two or more times.",
253+
),
249254
}
250255

251256
reports = (("RP0101", "Statistics by type", report_by_type_stats),)
@@ -637,6 +642,21 @@ def visit_dict(self, node: nodes.Dict) -> None:
637642
self.add_message("duplicate-key", node=node, args=key)
638643
keys.add(key)
639644

645+
@utils.check_messages("duplicate-value")
646+
def visit_set(self, node: nodes.Set) -> None:
647+
"""Check duplicate value in set."""
648+
values = set()
649+
for v in node.elts:
650+
if isinstance(v, nodes.Const):
651+
value = v.value
652+
else:
653+
continue
654+
if value in values:
655+
self.add_message(
656+
"duplicate-value", node=node, args=value, confidence=HIGH
657+
)
658+
values.add(value)
659+
640660
def visit_tryfinally(self, node: nodes.TryFinally) -> None:
641661
"""Update try...finally flag."""
642662
self._tryfinallys.append(node)

pylint/checkers/format.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -673,10 +673,8 @@ def is_line_length_check_activated(pylint_pattern_match_object) -> bool:
673673
def specific_splitlines(lines: str) -> List[str]:
674674
"""Split lines according to universal newlines except those in a specific sets."""
675675
unsplit_ends = {
676-
"\v",
677-
"\x0b",
678-
"\f",
679-
"\x0c",
676+
"\x0b", # synonym of \v
677+
"\x0c", # synonym of \f
680678
"\x1c",
681679
"\x1d",
682680
"\x1e",

tests/functional/d/duplicate_value.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# pylint: disable = invalid-name, line-too-long
2+
"""Simple test sets for checking duplicate values"""
3+
4+
set1 = {1, 2, 3, 4}
5+
set2 = {1, 1, 2} # [duplicate-value]
6+
set3 = {1, 2, 2} # [duplicate-value]
7+
8+
set4 = {'one', 'two', 'three'}
9+
set5 = {'one', 'two', 'one'} # [duplicate-value]
10+
set6 = {'one', 'two', 'two'} # [duplicate-value]
11+
12+
wrong_set = {12, 23, True, 6, True, 0, 12} # [duplicate-value, duplicate-value]
13+
correct_set = {12, 13, 23, 24, 89}
14+
15+
wrong_set_mixed = {1, 2, 'value', 1} # [duplicate-value]
16+
wrong_set = {'arg1', 'arg2', False, 'arg1', True} # [duplicate-value]
17+
18+
another_wrong_set = {2, 3, 'arg1', True, 'arg1', False, True} # [duplicate-value, duplicate-value]
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
duplicate-value:5:7:5:16::Duplicate value 1 in set:HIGH
2+
duplicate-value:6:7:6:16::Duplicate value 2 in set:HIGH
3+
duplicate-value:9:7:9:28::Duplicate value 'one' in set:HIGH
4+
duplicate-value:10:7:10:28::Duplicate value 'two' in set:HIGH
5+
duplicate-value:12:12:12:42::Duplicate value 12 in set:HIGH
6+
duplicate-value:12:12:12:42::Duplicate value True in set:HIGH
7+
duplicate-value:15:18:15:36::Duplicate value 1 in set:HIGH
8+
duplicate-value:16:12:16:49::Duplicate value 'arg1' in set:HIGH
9+
duplicate-value:18:20:18:61::Duplicate value 'arg1' in set:HIGH
10+
duplicate-value:18:20:18:61::Duplicate value True in set:HIGH

0 commit comments

Comments
 (0)