Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add new message called duplicate-value #5928

Merged
merged 16 commits into from
Apr 2, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,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