diff options
author | Marc Mueller <30130371+cdce8p@users.noreply.github.com> | 2021-08-13 19:34:19 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-08-13 19:34:19 +0200 |
commit | 61b4db0dc31fd31fcfda36e4730cb44848af2d30 (patch) | |
tree | 99969d59b7509b0c1fa718923c712d6f02d9fe00 | |
parent | 4f5732095a65a50828d621ba19d67b0753cc0133 (diff) | |
parent | 941dd78d91850471cea0cac51581cd51eaae4cd7 (diff) | |
download | pylint-git-61b4db0dc31fd31fcfda36e4730cb44848af2d30.tar.gz |
Merge pull request #4835 from cdce8p/feature-sequence_for_iteration
Add `use-sequence-for-iteration` checker
-rw-r--r-- | ChangeLog | 2 | ||||
-rw-r--r-- | doc/whatsnew/2.10.rst | 2 | ||||
-rw-r--r-- | pylint/checkers/refactoring/recommendation_checker.py | 34 | ||||
-rw-r--r-- | tests/functional/ext/code_style/code_style_consider_using_tuple.py | 4 | ||||
-rw-r--r-- | tests/functional/ext/code_style/code_style_consider_using_tuple.txt | 2 | ||||
-rw-r--r-- | tests/functional/u/undefined/undefined_loop_variable.py | 2 | ||||
-rw-r--r-- | tests/functional/u/use/use_sequence_for_iteration.py | 16 | ||||
-rw-r--r-- | tests/functional/u/use/use_sequence_for_iteration.txt | 4 |
8 files changed, 60 insertions, 6 deletions
@@ -118,6 +118,8 @@ Release date: TBA Closes #4828 +* Added ``use-sequence-for-iteration``: Emitted when iterating over an in-place defined ``set``. + What's New in Pylint 2.9.6? =========================== diff --git a/doc/whatsnew/2.10.rst b/doc/whatsnew/2.10.rst index 585ac8cc7..d13099989 100644 --- a/doc/whatsnew/2.10.rst +++ b/doc/whatsnew/2.10.rst @@ -28,6 +28,8 @@ New checkers Closes #3692 +* Added ``use-sequence-for-iteration``: Emitted when iterating over an in-place defined ``set``. + Other Changes ============= diff --git a/pylint/checkers/refactoring/recommendation_checker.py b/pylint/checkers/refactoring/recommendation_checker.py index 0cb724985..b7bda5754 100644 --- a/pylint/checkers/refactoring/recommendation_checker.py +++ b/pylint/checkers/refactoring/recommendation_checker.py @@ -1,6 +1,6 @@ # Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html # For details: https://github.com/PyCQA/pylint/blob/main/LICENSE -from typing import cast +from typing import Union, cast import astroid @@ -43,6 +43,12 @@ class RecommendationChecker(checkers.BaseChecker): "str.split(sep, maxsplit=1)[0] or str.rsplit(sep, maxsplit=1)[-1] " "instead.", ), + "C0208": ( + "Use a sequence type when iterating over values", + "use-sequence-for-iteration", + "When iterating over values, sequence types (e.g., ``lists``, ``tuples``, ``ranges``) " + "are more efficient than ``sets``.", + ), } @staticmethod @@ -134,10 +140,15 @@ class RecommendationChecker(checkers.BaseChecker): ) self.add_message("use-maxsplit-arg", node=node, args=(new_name,)) - @utils.check_messages("consider-using-enumerate", "consider-using-dict-items") + @utils.check_messages( + "consider-using-enumerate", + "consider-using-dict-items", + "use-sequence-for-iteration", + ) def visit_for(self, node: astroid.For) -> None: self._check_consider_using_enumerate(node) self._check_consider_using_dict_items(node) + self._check_use_sequence_for_iteration(node) def _check_consider_using_enumerate(self, node: astroid.For) -> None: """Emit a convention whenever range and len are used for indexing.""" @@ -262,8 +273,18 @@ class RecommendationChecker(checkers.BaseChecker): self.add_message("consider-using-dict-items", node=node) return - @utils.check_messages("consider-using-dict-items") + @utils.check_messages( + "consider-using-dict-items", + "use-sequence-for-iteration", + ) def visit_comprehension(self, node: astroid.Comprehension) -> None: + self._check_consider_using_dict_items_comprehension(node) + self._check_use_sequence_for_iteration(node) + + def _check_consider_using_dict_items_comprehension( + self, node: astroid.Comprehension + ) -> None: + """Add message when accessing dict values by index lookup.""" iterating_object_name = utils.get_iterating_dictionary_name(node) if iterating_object_name is None: return @@ -285,3 +306,10 @@ class RecommendationChecker(checkers.BaseChecker): self.add_message("consider-using-dict-items", node=node) return + + def _check_use_sequence_for_iteration( + self, node: Union[astroid.For, astroid.Comprehension] + ) -> None: + """Check if code iterates over an in-place defined set.""" + if isinstance(node.iter, astroid.Set): + self.add_message("use-sequence-for-iteration", node=node.iter) diff --git a/tests/functional/ext/code_style/code_style_consider_using_tuple.py b/tests/functional/ext/code_style/code_style_consider_using_tuple.py index 679ef77d2..1bf06d82c 100644 --- a/tests/functional/ext/code_style/code_style_consider_using_tuple.py +++ b/tests/functional/ext/code_style/code_style_consider_using_tuple.py @@ -12,7 +12,7 @@ for x in [1, 2, 3]: # [consider-using-tuple] (x for x in var) (x for x in (1, 2, 3)) (x for x in [1, 2, 3]) # [consider-using-tuple] -(x for x in {1, 2, 3}) # [consider-using-tuple] +(x for x in {1, 2, 3}) # [consider-using-tuple,use-sequence-for-iteration] [x for x in var] [x for x in (1, 2, 3)] @@ -26,4 +26,4 @@ for x in [2, *var]: pass [x for x in [*var, 2]] -[x for x in {*var, 2}] +[x for x in {*var, 2}] # [use-sequence-for-iteration] diff --git a/tests/functional/ext/code_style/code_style_consider_using_tuple.txt b/tests/functional/ext/code_style/code_style_consider_using_tuple.txt index df796b683..622aeb33e 100644 --- a/tests/functional/ext/code_style/code_style_consider_using_tuple.txt +++ b/tests/functional/ext/code_style/code_style_consider_using_tuple.txt @@ -1,4 +1,6 @@ consider-using-tuple:9:9::Consider using an in-place tuple instead of list consider-using-tuple:14:12::Consider using an in-place tuple instead of list consider-using-tuple:15:12::Consider using an in-place tuple instead of set +use-sequence-for-iteration:15:12::Use a sequence type when iterating over values consider-using-tuple:19:12::Consider using an in-place tuple instead of list +use-sequence-for-iteration:29:12::Use a sequence type when iterating over values diff --git a/tests/functional/u/undefined/undefined_loop_variable.py b/tests/functional/u/undefined/undefined_loop_variable.py index 317372749..3df17f7d1 100644 --- a/tests/functional/u/undefined/undefined_loop_variable.py +++ b/tests/functional/u/undefined/undefined_loop_variable.py @@ -44,7 +44,7 @@ def do_stuff_with_a_list(): def do_stuff_with_a_set(): - for var in {1, 2, 3}: + for var in {1, 2, 3}: # pylint: disable=use-sequence-for-iteration pass return var diff --git a/tests/functional/u/use/use_sequence_for_iteration.py b/tests/functional/u/use/use_sequence_for_iteration.py new file mode 100644 index 000000000..2dd1feb18 --- /dev/null +++ b/tests/functional/u/use/use_sequence_for_iteration.py @@ -0,0 +1,16 @@ +# pylint: disable=missing-docstring,pointless-statement,unnecessary-comprehension + +var = {1, 2, 3} + +for x in var: + pass +for x in {1, 2, 3}: # [use-sequence-for-iteration] + pass + +(x for x in var) +(x for x in {1, 2, 3}) # [use-sequence-for-iteration] + +[x for x in var] +[x for x in {1, 2, 3}] # [use-sequence-for-iteration] + +[x for x in {*var, 4}] # [use-sequence-for-iteration] diff --git a/tests/functional/u/use/use_sequence_for_iteration.txt b/tests/functional/u/use/use_sequence_for_iteration.txt new file mode 100644 index 000000000..615df8a30 --- /dev/null +++ b/tests/functional/u/use/use_sequence_for_iteration.txt @@ -0,0 +1,4 @@ +use-sequence-for-iteration:7:9::Use a sequence type when iterating over values:HIGH +use-sequence-for-iteration:11:12::Use a sequence type when iterating over values:HIGH +use-sequence-for-iteration:14:12::Use a sequence type when iterating over values:HIGH +use-sequence-for-iteration:16:12::Use a sequence type when iterating over values:HIGH |