Skip to content

Add new consider-using-generator checker Issue #3165 #3309

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

Merged
merged 22 commits into from
Feb 20, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
75c1f8a
Add new `consider-using-generator` checker
ikraduya Dec 17, 2019
771aa26
Add `consider-using-generator` unit test
ikraduya Dec 17, 2019
20e47d7
Add `consider-using-generator` in ChangeLog and whatsnew
ikraduya Dec 17, 2019
8df2c20
Change `consider-using-generator` message description
ikraduya Feb 16, 2021
ea6c21c
Add design choices for 'consider-using-generator'
Pierre-Sassoulas Feb 16, 2021
8e8f599
Minor change in message description
ikraduya Feb 16, 2021
a942725
Grammar correction at ChangeLog, 2.5.rst, and refactoring_checker.py
ikraduya Feb 16, 2021
66381f4
Move ChangeLog item from 2.5.0 to 2.7.0
ikraduya Feb 16, 2021
eb16eb2
Merge branch 'master' into Issue3165
Pierre-Sassoulas Feb 16, 2021
5106349
Add new `consider-using-generator` checker
ikraduya Dec 17, 2019
7f7ce47
Add `consider-using-generator` unit test
ikraduya Dec 17, 2019
a33978a
Add `consider-using-generator` in ChangeLog and whatsnew
ikraduya Dec 17, 2019
e4cf934
Change `consider-using-generator` message description
ikraduya Feb 16, 2021
f928049
Add design choices for 'consider-using-generator'
Pierre-Sassoulas Feb 16, 2021
13da8d7
Minor change in message description
ikraduya Feb 16, 2021
9cb01f2
Grammar correction at ChangeLog, 2.5.rst, and refactoring_checker.py
ikraduya Feb 16, 2021
4044347
Move ChangeLog item from 2.5.0 to 2.7.0
ikraduya Feb 16, 2021
60fa295
Add `consider-using-generator` in 2.7.rst
ikraduya Feb 16, 2021
eb3a407
Resolve ChangeLog `consider-using-generator` issue
ikraduya Feb 16, 2021
750417d
Creating additional 'use-a-generator' checker
ikraduya Feb 20, 2021
ab3533f
Merge branch 'master' into Issue3165
Pierre-Sassoulas Feb 20, 2021
522ca9b
Fix pre-commit checks
Pierre-Sassoulas Feb 20, 2021
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
3 changes: 3 additions & 0 deletions CONTRIBUTORS.txt
Original file line number Diff line number Diff line change
Expand Up @@ -446,4 +446,7 @@ contributors:

* David Gilman: contributor

* Ikraduya Edian: contributor
- Added new checks 'consider-using-generator' and 'use-a-generator'.

* Tiago Honorato: contributor
9 changes: 9 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
Expand Up @@ -168,8 +168,17 @@ What's New in Pylint 2.7.0?

Close #3555

* New check: ``consider-using-generator``

This check warns when a comprehension is used inside an `any` or `all` function,
since it is unnecessary and should be replaced by a generator instead.
Using a generator would be less code and way faster.

Close #3165

* Add Github Actions to replace Travis and AppVeyor in the future


What's New in Pylint 2.6.1?
===========================

Expand Down
2 changes: 2 additions & 0 deletions doc/whatsnew/2.7.rst
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ New checkers

* Add `condition-evals-to-constant` check for conditionals using and/or that evaluate to a constant.

* Add `consider-using-generator` check for the use of list comprehension inside ``any`` or ``all`` function.

Other Changes
=============

Expand Down
61 changes: 61 additions & 0 deletions pylint/checkers/refactoring/refactoring_checker.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,22 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2016-2018 Claudiu Popa <[email protected]>
# Copyright (c) 2016-2017 Łukasz Rogalski <[email protected]>
# Copyright (c) 2016 Moises Lopez <[email protected]>
# Copyright (c) 2016 Alexander Todorov <[email protected]>
# Copyright (c) 2017-2018 hippo91 <[email protected]>
# Copyright (c) 2017 Ville Skyttä <[email protected]>
# Copyright (c) 2017-2018 Bryce Guinta <[email protected]>
# Copyright (c) 2017 Hugo <[email protected]>
# Copyright (c) 2017 Łukasz Sznuk <[email protected]>
# Copyright (c) 2017 Alex Hearn <[email protected]>
# Copyright (c) 2017 Antonio Ossa <[email protected]>
# Copyright (c) 2018 Konstantin Manna <[email protected]>
# Copyright (c) 2018 Konstantin <[email protected]>
# Copyright (c) 2018 Sushobhit <[email protected]>
# Copyright (c) 2018 Matej Marušák <[email protected]>
# Copyright (c) 2018 Ville Skyttä <[email protected]>
# Copyright (c) 2018 Mr. Senko <[email protected]>
# Copyright (c) 2019 Ikraduya Edian <[email protected]>

# 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
Expand Down Expand Up @@ -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 = (
(
Expand Down Expand Up @@ -684,18 +714,49 @@ def _check_consider_using_comprehension_constructor(self, node):
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):
Expand Down
11 changes: 11 additions & 0 deletions tests/functional/c/consider_using_generator.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# pylint: disable=missing-docstring, invalid-name
# https://github.com/PyCQA/pylint/issues/3165

list([])
tuple([])

list([0 for y in list(range(10))]) # [consider-using-generator]
tuple([0 for y in list(range(10))]) # [consider-using-generator]

list(0 for y in list(range(10)))
tuple(0 for y in list(range(10)))
2 changes: 2 additions & 0 deletions tests/functional/c/consider_using_generator.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
consider-using-generator:7:0::Consider using a generator instead 'list(0 for y in list(range(10)))'
consider-using-generator:8:0::Consider using a generator instead 'tuple(0 for y in list(range(10)))'
11 changes: 11 additions & 0 deletions tests/functional/u/use_a_generator.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# pylint: disable=missing-docstring, invalid-name
# https://github.com/PyCQA/pylint/issues/3165

any([])
all([])

any([0 for x in list(range(10))]) # [use-a-generator]
all([0 for y in list(range(10))]) # [use-a-generator]

any(0 for x in list(range(10)))
all(0 for y in list(range(10)))
2 changes: 2 additions & 0 deletions tests/functional/u/use_a_generator.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
use-a-generator:7:0::Use a generator instead 'any(0 for x in list(range(10)))'
use-a-generator:8:0::Use a generator instead 'all(0 for y in list(range(10)))'