Skip to content

Commit

Permalink
Add new message called duplicate-value for sets (#5928)
Browse files Browse the repository at this point in the history
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 <13665637+DanielNoord@users.noreply.github.com>
Co-authored-by: Pierre Sassoulas <pierre.sassoulas@gmail.com>
  • Loading branch information
3 people committed Apr 2, 2022
1 parent 79f3e1d commit 06bc0a6
Show file tree
Hide file tree
Showing 8 changed files with 61 additions and 5 deletions.
4 changes: 4 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ Release date: TBA

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

* Added new message called ``duplicate-value`` which identifies duplicate values inside sets.

Closes #5880

..
Insert your changelog randomly, it will reduce merge conflicts
(Ie. not necessarily at the end)
Expand Down
1 change: 1 addition & 0 deletions doc/data/messages/d/duplicate-value/bad.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
incorrect_set = {'value1', 23, 5, 'value1'} # [duplicate-value]
1 change: 1 addition & 0 deletions doc/data/messages/d/duplicate-value/good.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
correct_set = {'value1', 23, 5}
4 changes: 4 additions & 0 deletions doc/whatsnew/2.14.rst
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ New checkers

Closes #4525

* Added new message called ``duplicate-value`` which identifies duplicate values inside sets.

Closes #5880

Removed checkers
================

Expand Down
22 changes: 21 additions & 1 deletion pylint/checkers/base/basic_checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
from pylint import interfaces
from pylint import utils as lint_utils
from pylint.checkers import BaseChecker, utils
from pylint.interfaces import IAstroidChecker
from pylint.interfaces import HIGH, IAstroidChecker
from pylint.reporters.ureports import nodes as reporter_nodes
from pylint.utils import LinterStats
from pylint.utils.utils import get_global_option
Expand Down Expand Up @@ -246,6 +246,11 @@ class BasicChecker(_BasicChecker):
"Used when an assert statement has a string literal as its first argument, which will "
"cause the assert to always pass.",
),
"W0130": (
"Duplicate value %r in set",
"duplicate-value",
"This message is emitted when a set contains the same value two or more times.",
),
}

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

@utils.check_messages("duplicate-value")
def visit_set(self, node: nodes.Set) -> None:
"""Check duplicate value in set."""
values = set()
for v in node.elts:
if isinstance(v, nodes.Const):
value = v.value
else:
continue
if value in values:
self.add_message(
"duplicate-value", node=node, args=value, confidence=HIGH
)
values.add(value)

def visit_tryfinally(self, node: nodes.TryFinally) -> None:
"""Update try...finally flag."""
self._tryfinallys.append(node)
Expand Down
6 changes: 2 additions & 4 deletions pylint/checkers/format.py
Original file line number Diff line number Diff line change
Expand Up @@ -673,10 +673,8 @@ def is_line_length_check_activated(pylint_pattern_match_object) -> bool:
def specific_splitlines(lines: str) -> List[str]:
"""Split lines according to universal newlines except those in a specific sets."""
unsplit_ends = {
"\v",
"\x0b",
"\f",
"\x0c",
"\x0b", # synonym of \v
"\x0c", # synonym of \f
"\x1c",
"\x1d",
"\x1e",
Expand Down
18 changes: 18 additions & 0 deletions tests/functional/d/duplicate_value.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# pylint: disable = invalid-name, line-too-long
"""Simple test sets for checking duplicate values"""

set1 = {1, 2, 3, 4}
set2 = {1, 1, 2} # [duplicate-value]
set3 = {1, 2, 2} # [duplicate-value]

set4 = {'one', 'two', 'three'}
set5 = {'one', 'two', 'one'} # [duplicate-value]
set6 = {'one', 'two', 'two'} # [duplicate-value]

wrong_set = {12, 23, True, 6, True, 0, 12} # [duplicate-value, duplicate-value]
correct_set = {12, 13, 23, 24, 89}

wrong_set_mixed = {1, 2, 'value', 1} # [duplicate-value]
wrong_set = {'arg1', 'arg2', False, 'arg1', True} # [duplicate-value]

another_wrong_set = {2, 3, 'arg1', True, 'arg1', False, True} # [duplicate-value, duplicate-value]
10 changes: 10 additions & 0 deletions tests/functional/d/duplicate_value.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
duplicate-value:5:7:5:16::Duplicate value 1 in set:HIGH
duplicate-value:6:7:6:16::Duplicate value 2 in set:HIGH
duplicate-value:9:7:9:28::Duplicate value 'one' in set:HIGH
duplicate-value:10:7:10:28::Duplicate value 'two' in set:HIGH
duplicate-value:12:12:12:42::Duplicate value 12 in set:HIGH
duplicate-value:12:12:12:42::Duplicate value True in set:HIGH
duplicate-value:15:18:15:36::Duplicate value 1 in set:HIGH
duplicate-value:16:12:16:49::Duplicate value 'arg1' in set:HIGH
duplicate-value:18:20:18:61::Duplicate value 'arg1' in set:HIGH
duplicate-value:18:20:18:61::Duplicate value True in set:HIGH

0 comments on commit 06bc0a6

Please sign in to comment.