diff options
author | Claudiu Popa <pcmanticore@gmail.com> | 2018-10-11 08:15:20 +0200 |
---|---|---|
committer | Claudiu Popa <pcmanticore@gmail.com> | 2018-10-11 08:15:20 +0200 |
commit | 0a39200932a9143082255e600ff5a7e764520ce8 (patch) | |
tree | f8624379e8e815c8c5bc7f7e53347301628ecc6c | |
parent | fcc01516ae176ad3fdedc4497328105f3314e376 (diff) | |
download | pylint-git-0a39200932a9143082255e600ff5a7e764520ce8.tar.gz |
Consider ``range()`` objects for ``undefined-loop-variable`` leaking from iteration.
Close #2533
-rw-r--r-- | ChangeLog | 4 | ||||
-rw-r--r-- | pylint/checkers/format.py | 6 | ||||
-rw-r--r-- | pylint/checkers/variables.py | 11 | ||||
-rw-r--r-- | pylint/test/functional/cellvar_escaping_loop.py | 14 | ||||
-rw-r--r-- | pylint/test/functional/cellvar_escaping_loop.txt | 13 | ||||
-rw-r--r-- | pylint/test/functional/undefined_loop_variable.py | 16 | ||||
-rw-r--r-- | pylint/test/functional/undefined_loop_variable.txt | 3 |
7 files changed, 45 insertions, 22 deletions
@@ -7,6 +7,10 @@ What's New in Pylint 2.2? Release date: TBA + * Consider ``range()`` objects for ``undefined-loop-variable`` leaking from iteration. + + Close #2533 + * ``deprecated-method`` can use the attribute name for identifying a deprecated method Previously we were using the fully qualified name, which we still do, but the fully diff --git a/pylint/checkers/format.py b/pylint/checkers/format.py index b5f35cd00..38b6649c5 100644 --- a/pylint/checkers/format.py +++ b/pylint/checkers/format.py @@ -1333,3 +1333,9 @@ class FormatChecker(BaseTokenChecker): def register(linter): """required method to auto register this checker """ linter.register_checker(FormatChecker(linter)) + + +def funkier(): + for val in range(3): + pass + print(val) diff --git a/pylint/checkers/variables.py b/pylint/checkers/variables.py index 78d78a913..784568ddd 100644 --- a/pylint/checkers/variables.py +++ b/pylint/checkers/variables.py @@ -64,6 +64,7 @@ PY3K = sys.version_info >= (3, 0) # for `abc` METACLASS_NAME_TRANSFORMS = {"_py_abc": "abc"} TYPING_TYPE_CHECKS_GUARDS = frozenset({"typing.TYPE_CHECKING", "TYPE_CHECKING"}) +BUILTIN_RANGE = "builtins.range" def _is_from_future_import(stmt, name): @@ -1145,7 +1146,7 @@ class VariablesChecker(BaseChecker): ): return - # For functions we can do more by inferring the length of the iterred object + # For functions we can do more by inferring the length of the itered object if not isinstance(assign, astroid.For): self.add_message("undefined-loop-variable", args=name, node=node) return @@ -1155,6 +1156,14 @@ class VariablesChecker(BaseChecker): except astroid.InferenceError: self.add_message("undefined-loop-variable", args=name, node=node) else: + if ( + isinstance(inferred, astroid.Instance) + and inferred.qname() == BUILTIN_RANGE + ): + # Consider range() objects safe, even if they might not yield any results. + return + + # Consider sequences. sequences = ( astroid.List, astroid.Tuple, diff --git a/pylint/test/functional/cellvar_escaping_loop.py b/pylint/test/functional/cellvar_escaping_loop.py index 29107b575..23c6b4b2e 100644 --- a/pylint/test/functional/cellvar_escaping_loop.py +++ b/pylint/test/functional/cellvar_escaping_loop.py @@ -35,16 +35,6 @@ def good_case5(): def good_case6(): - """Accept use of the variable after the loop. - - There's already a warning about possibly undefined loop variables, and - the value will not change any more.""" - for i in range(10): - print(i) - return lambda: i # [undefined-loop-variable] - - -def good_case7(): """Accept use of the variable inside return.""" for i in range(10): if i == 8: @@ -52,13 +42,13 @@ def good_case7(): return lambda: -1 -def good_case8(): +def good_case7(): """Lambda defined and called in loop.""" for i in range(10): print((lambda x: i + x)(1)) -def good_case9(): +def good_case8(): """Another eager binding of the cell variable.""" funs = [] for i in range(10): diff --git a/pylint/test/functional/cellvar_escaping_loop.txt b/pylint/test/functional/cellvar_escaping_loop.txt index bdd7fe9c6..2ac0b58ef 100644 --- a/pylint/test/functional/cellvar_escaping_loop.txt +++ b/pylint/test/functional/cellvar_escaping_loop.txt @@ -1,7 +1,6 @@ -undefined-loop-variable:44:good_case6.<lambda>:Using possibly undefined loop variable 'i' -cell-var-from-loop:77:bad_case.<lambda>:Cell variable i defined in loop -cell-var-from-loop:82:bad_case2.<lambda>:Cell variable i defined in loop -cell-var-from-loop:90:bad_case3.<lambda>:Cell variable j defined in loop -cell-var-from-loop:100:bad_case4.nested:Cell variable i defined in loop -cell-var-from-loop:121:bad_case5.<lambda>:Cell variable i defined in loop -cell-var-from-loop:129:bad_case6.<lambda>:Cell variable i defined in loop +cell-var-from-loop:67:bad_case.<lambda>:Cell variable i defined in loop +cell-var-from-loop:72:bad_case2.<lambda>:Cell variable i defined in loop +cell-var-from-loop:80:bad_case3.<lambda>:Cell variable j defined in loop +cell-var-from-loop:90:bad_case4.nested:Cell variable i defined in loop +cell-var-from-loop:111:bad_case5.<lambda>:Cell variable i defined in loop +cell-var-from-loop:119:bad_case6.<lambda>:Cell variable i defined in loop diff --git a/pylint/test/functional/undefined_loop_variable.py b/pylint/test/functional/undefined_loop_variable.py index 3840003b5..a984898f8 100644 --- a/pylint/test/functional/undefined_loop_variable.py +++ b/pylint/test/functional/undefined_loop_variable.py @@ -1,4 +1,4 @@ -# pylint: disable=missing-docstring +# pylint: disable=missing-docstring,redefined-builtin def do_stuff(some_random_list): for var in some_random_list: @@ -59,3 +59,17 @@ def do_stuff_with_a_tuple(): for var in (1, 2, 3): pass return var + + +def do_stuff_with_a_range(): + for var in range(1, 2): + pass + return var + + +def do_stuff_with_redefined_range(): + def range(key): + yield from [1, key] + for var in range(3): + pass + return var # [undefined-loop-variable] diff --git a/pylint/test/functional/undefined_loop_variable.txt b/pylint/test/functional/undefined_loop_variable.txt index 33022d454..64cf6388b 100644 --- a/pylint/test/functional/undefined_loop_variable.txt +++ b/pylint/test/functional/undefined_loop_variable.txt @@ -1,2 +1,3 @@ undefined-loop-variable:6:do_stuff:Using possibly undefined loop variable 'var' -undefined-loop-variable:25::Using possibly undefined loop variable 'var1'
\ No newline at end of file +undefined-loop-variable:25::Using possibly undefined loop variable 'var1' +undefined-loop-variable:75:do_stuff_with_redefined_range:Using possibly undefined loop variable 'var' |