summaryrefslogtreecommitdiff
path: root/pylint/checkers/refactoring/refactoring_checker.py
diff options
context:
space:
mode:
authorIkraduya Edian <ikraduya@gmail.com>2021-02-20 21:50:19 +0700
committerGitHub <noreply@github.com>2021-02-20 15:50:19 +0100
commit45c824549f9a7fa38df04ae8648d1647c82ba9b4 (patch)
treec6d05e8979245ddb0c5ed84437ac8219616858bb /pylint/checkers/refactoring/refactoring_checker.py
parent570e65536147b00ab8a5743e761d7caa326afa21 (diff)
downloadpylint-git-45c824549f9a7fa38df04ae8648d1647c82ba9b4.tar.gz
Add new `consider-using-generator` and 'use-a-generator' checkers
See issue #3165 (#3309) See https://github.com/PyCQA/pylint/pull/3309#discussion_r576683109 Co-authored-by: Pierre Sassoulas <pierre.sassoulas@gmail.com> Co-authored-by: Daniel Hahler <github@thequod.de>
Diffstat (limited to 'pylint/checkers/refactoring/refactoring_checker.py')
-rw-r--r--pylint/checkers/refactoring/refactoring_checker.py61
1 files changed, 61 insertions, 0 deletions
diff --git a/pylint/checkers/refactoring/refactoring_checker.py b/pylint/checkers/refactoring/refactoring_checker.py
index 81bb18213..07d9d5f58 100644
--- a/pylint/checkers/refactoring/refactoring_checker.py
+++ b/pylint/checkers/refactoring/refactoring_checker.py
@@ -1,4 +1,22 @@
# -*- coding: utf-8 -*-
+# Copyright (c) 2016-2018 Claudiu Popa <pcmanticore@gmail.com>
+# Copyright (c) 2016-2017 Łukasz Rogalski <rogalski.91@gmail.com>
+# Copyright (c) 2016 Moises Lopez <moylop260@vauxoo.com>
+# Copyright (c) 2016 Alexander Todorov <atodorov@otb.bg>
+# Copyright (c) 2017-2018 hippo91 <guillaume.peillex@gmail.com>
+# Copyright (c) 2017 Ville Skyttä <ville.skytta@iki.fi>
+# Copyright (c) 2017-2018 Bryce Guinta <bryce.paul.guinta@gmail.com>
+# Copyright (c) 2017 Hugo <hugovk@users.noreply.github.com>
+# Copyright (c) 2017 Łukasz Sznuk <ls@rdprojekt.pl>
+# Copyright (c) 2017 Alex Hearn <alex.d.hearn@gmail.com>
+# Copyright (c) 2017 Antonio Ossa <aaossa@uc.cl>
+# Copyright (c) 2018 Konstantin Manna <Konstantin@Manna.uno>
+# Copyright (c) 2018 Konstantin <Github@pheanex.de>
+# Copyright (c) 2018 Sushobhit <31987769+sushobhit27@users.noreply.github.com>
+# Copyright (c) 2018 Matej Marušák <marusak.matej@gmail.com>
+# Copyright (c) 2018 Ville Skyttä <ville.skytta@upcloud.com>
+# Copyright (c) 2018 Mr. Senko <atodorov@mrsenko.com>
+# Copyright (c) 2019 Ikraduya Edian <ikraduya@gmail.com>
# Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
# For details: https://github.com/PyCQA/pylint/blob/master/COPYING
@@ -282,6 +300,18 @@ class RefactoringChecker(checkers.BaseTokenChecker):
"Emitted when calling the super() builtin with the current class "
"and instance. On Python 3 these arguments are the default and they can be omitted.",
),
+ "R1728": (
+ "Consider using a generator instead '%s(%s)'",
+ "consider-using-generator",
+ "If your container can be large using "
+ "a generator will bring better performance.",
+ ),
+ "R1729": (
+ "Use a generator instead '%s(%s)'",
+ "use-a-generator",
+ "Comprehension inside of 'any' or 'all' is unnecessary. "
+ "A generator would be sufficient and faster.",
+ ),
}
options = (
(
@@ -684,18 +714,49 @@ class RefactoringChecker(checkers.BaseTokenChecker):
message_name = "consider-using-set-comprehension"
self.add_message(message_name, node=node)
+ def _check_consider_using_generator(self, node):
+ # 'any' and 'all' definitely should use generator, while 'list' and 'tuple' need to be considered first
+ # See https://github.com/PyCQA/pylint/pull/3309#discussion_r576683109
+ checked_call = ["any", "all", "list", "tuple"]
+ if (
+ isinstance(node, astroid.Call)
+ and node.func
+ and isinstance(node.func, astroid.Name)
+ and node.func.name in checked_call
+ ):
+ # functions in checked_calls take exactly one argument
+ # check whether the argument is list comprehension
+ if len(node.args) == 1 and isinstance(node.args[0], astroid.ListComp):
+ # remove square brackets '[]'
+ inside_comp = node.args[0].as_string()[1:-1]
+ call_name = node.func.name
+ if call_name in ["any", "all"]:
+ self.add_message(
+ "use-a-generator",
+ node=node,
+ args=(call_name, inside_comp),
+ )
+ else:
+ self.add_message(
+ "consider-using-generator",
+ node=node,
+ args=(call_name, inside_comp),
+ )
+
@utils.check_messages(
"stop-iteration-return",
"consider-using-dict-comprehension",
"consider-using-set-comprehension",
"consider-using-sys-exit",
"super-with-arguments",
+ "consider-using-generator",
)
def visit_call(self, node):
self._check_raising_stopiteration_in_generator_next_call(node)
self._check_consider_using_comprehension_constructor(node)
self._check_quit_exit_call(node)
self._check_super_with_arguments(node)
+ self._check_consider_using_generator(node)
@staticmethod
def _has_exit_in_scope(scope):