diff --git a/.copyrite_aliases b/.copyrite_aliases index 3dea23b4f7..773b12d61c 100644 --- a/.copyrite_aliases +++ b/.copyrite_aliases @@ -108,5 +108,10 @@ ], "authoritative_mail": "bot@noreply.github.com", "name": "bot" + }, + { + "mails": ["tushar.sadhwani000@gmail.com", "tushar@deepsource.io"], + "authoritative_mail": "tushar.sadhwani000@gmail.com", + "name": "Tushar Sadhwani" } ] diff --git a/ChangeLog b/ChangeLog index 19a3b73ea9..1e8d79d436 100644 --- a/ChangeLog +++ b/ChangeLog @@ -11,6 +11,11 @@ Release date: TBA .. Put new features here and also in 'doc/whatsnew/2.13.rst' +* Fixed false positive ``consider-using-dict-comprehension`` when creating a dict + using a list of tuples where key AND value vary depending on the same condition. + + Closes #5588 + * When run in parallel mode ``pylint`` now pickles the data passed to subprocesses with the ``dill`` package. The ``dill`` package has therefore been added as a dependency. diff --git a/doc/whatsnew/2.13.rst b/doc/whatsnew/2.13.rst index 9510cd54a9..df1a997570 100644 --- a/doc/whatsnew/2.13.rst +++ b/doc/whatsnew/2.13.rst @@ -32,6 +32,11 @@ Extensions Other Changes ============= +* Fixed false positive ``consider-using-dict-comprehension`` when creating a dict + using a list of tuples where key AND value vary depending on the same condition. + + Closes #5588 + * When run in parallel mode ``pylint`` now pickles the data passed to subprocesses with the ``dill`` package. The ``dill`` package has therefore been added as a dependency. diff --git a/pylint/checkers/refactoring/refactoring_checker.py b/pylint/checkers/refactoring/refactoring_checker.py index d08ad8bdc6..40a72a53f3 100644 --- a/pylint/checkers/refactoring/refactoring_checker.py +++ b/pylint/checkers/refactoring/refactoring_checker.py @@ -934,9 +934,28 @@ def _check_consider_using_comprehension_constructor(self, node): and node.args and isinstance(node.args[0], nodes.ListComp) ): - if node.func.name == "dict" and not isinstance( - node.args[0].elt, nodes.Call - ): + if node.func.name == "dict": + element = node.args[0].elt + if isinstance(element, nodes.Call): + return + + # If we have an `IfExp` here where both the key AND value + # are different, then don't raise the issue. See #5588 + if ( + isinstance(element, nodes.IfExp) + and isinstance(element.body, (nodes.Tuple, nodes.List)) + and len(element.body.elts) == 2 + and isinstance(element.orelse, (nodes.Tuple, nodes.List)) + and len(element.orelse.elts) == 2 + ): + key1, value1 = element.body.elts + key2, value2 = element.orelse.elts + if ( + key1.as_string() != key2.as_string() + and value1.as_string() != value2.as_string() + ): + return + message_name = "consider-using-dict-comprehension" self.add_message(message_name, node=node) elif node.func.name == "set": diff --git a/tests/functional/c/consider/consider_using_dict_comprehension.py b/tests/functional/c/consider/consider_using_dict_comprehension.py index c9d740e18c..ef9ee3f012 100644 --- a/tests/functional/c/consider/consider_using_dict_comprehension.py +++ b/tests/functional/c/consider/consider_using_dict_comprehension.py @@ -1,4 +1,4 @@ -# pylint: disable=missing-docstring, invalid-name, use-dict-literal +# pylint: disable=missing-docstring, invalid-name, use-dict-literal, line-too-long numbers = [1, 2, 3, 4, 5, 6] @@ -8,5 +8,10 @@ dict([(number, number*2) for number in numbers]) # [consider-using-dict-comprehension] +stuff = {1: 10, 2: -20} +dict([(k, v) if v > 0 else (k, 0) for k, v in stuff.items()]) # [consider-using-dict-comprehension] +dict([(k, v) if v > 0 else (k*2, v) for k, v in stuff.items()]) # [consider-using-dict-comprehension] +dict([(k, v) if v > 0 else (k * 2, 0) for k, v in stuff.items()]) + # Cannot emit as this cannot be written as a comprehension dict([value.split("=") for value in ["a=b", "c=d"]]) diff --git a/tests/functional/c/consider/consider_using_dict_comprehension.txt b/tests/functional/c/consider/consider_using_dict_comprehension.txt index a241d19078..2bde7ffa23 100644 --- a/tests/functional/c/consider/consider_using_dict_comprehension.txt +++ b/tests/functional/c/consider/consider_using_dict_comprehension.txt @@ -1 +1,3 @@ consider-using-dict-comprehension:9:0:9:48::Consider using a dictionary comprehension:UNDEFINED +consider-using-dict-comprehension:12:0:12:61::Consider using a dictionary comprehension:UNDEFINED +consider-using-dict-comprehension:13:0:13:63::Consider using a dictionary comprehension:UNDEFINED