From 13accb55ece3fe55a71bc904726f5aae4dcbcfb6 Mon Sep 17 00:00:00 2001 From: Mark Byrne Date: Fri, 3 May 2024 22:36:58 +0200 Subject: [PATCH 1/8] Fix a false positive for ``consider-using-dict-items`` when iterating ``os.environ`` using the ``os.environ.keys()`` operation and then deleting an item using the key as a lookup. Closes #9554 --- doc/whatsnew/fragments/9554.false_positive | 3 ++ .../refactoring/recommendation_checker.py | 4 +++ .../c/consider/consider_using_dict_items.py | 9 ++++++ .../c/consider/consider_using_dict_items.txt | 29 ++++++++++--------- 4 files changed, 31 insertions(+), 14 deletions(-) create mode 100644 doc/whatsnew/fragments/9554.false_positive diff --git a/doc/whatsnew/fragments/9554.false_positive b/doc/whatsnew/fragments/9554.false_positive new file mode 100644 index 0000000000..4f6382c18c --- /dev/null +++ b/doc/whatsnew/fragments/9554.false_positive @@ -0,0 +1,3 @@ +Fix a false positive for ``consider-using-dict-items`` when iterating ``os.environ`` using the ``os.environ.keys()`` operation and then deleting an item using the key as a lookup. + +Closes #9554 diff --git a/pylint/checkers/refactoring/recommendation_checker.py b/pylint/checkers/refactoring/recommendation_checker.py index 617406613f..a1e4108be3 100644 --- a/pylint/checkers/refactoring/recommendation_checker.py +++ b/pylint/checkers/refactoring/recommendation_checker.py @@ -308,6 +308,10 @@ def _check_consider_using_dict_items(self, node: nodes.For) -> None: # Ignore this subscript if it is the target of an assignment # Early termination as dict index lookup is necessary return + if isinstance(subscript.parent, nodes.Delete): + # Ignore this subscript if the index is used to delete a + # dictionary item. + return self.add_message("consider-using-dict-items", node=node) return diff --git a/tests/functional/c/consider/consider_using_dict_items.py b/tests/functional/c/consider/consider_using_dict_items.py index 7fd74814fc..41ccd09a10 100644 --- a/tests/functional/c/consider/consider_using_dict_items.py +++ b/tests/functional/c/consider/consider_using_dict_items.py @@ -1,5 +1,6 @@ """Emit a message for iteration through dict keys and subscripting dict with key.""" # pylint: disable=line-too-long,missing-docstring,unsubscriptable-object,too-few-public-methods,redefined-outer-name,use-dict-literal,modified-iterating-dict +# pylint: disable=wrong-import-position def bad(): a_dict = {1: 1, 2: 2, 3: 3} @@ -103,3 +104,11 @@ class Foo: for k in d: # [consider-using-dict-items] if '1' in d[k]: # index lookup necessary here, do not emit error print('found 1') + + +# False positive in issue #9554 +# https://github.com/pylint-dev/pylint/issues/9554 +import os +for var in os.environ.keys(): # [consider-iterating-dictionary] + if var.startswith('foo_'): + del os.environ[var] # index lookup necessary here, do not emit error diff --git a/tests/functional/c/consider/consider_using_dict_items.txt b/tests/functional/c/consider/consider_using_dict_items.txt index 280ffecf37..e0f8171103 100644 --- a/tests/functional/c/consider/consider_using_dict_items.txt +++ b/tests/functional/c/consider/consider_using_dict_items.txt @@ -1,16 +1,17 @@ -consider-using-dict-items:6:4:7:24:bad:Consider iterating with .items():UNDEFINED -consider-using-dict-items:9:4:10:30:bad:Consider iterating with .items():UNDEFINED -consider-using-dict-items:21:4:22:35:another_bad:Consider iterating with .items():UNDEFINED -consider-using-dict-items:40:0:42:18::Consider iterating with .items():UNDEFINED -consider-using-dict-items:44:0:45:20::Consider iterating with .items():UNDEFINED -consider-iterating-dictionary:47:10:47:23::Consider iterating the dictionary directly instead of calling .keys():INFERENCE -consider-using-dict-items:47:0:48:20::Consider iterating with .items():UNDEFINED -consider-using-dict-items:54:0:55:24::Consider iterating with .items():UNDEFINED -consider-using-dict-items:67:0:None:None::Consider iterating with .items():UNDEFINED +consider-using-dict-items:7:4:8:24:bad:Consider iterating with .items():UNDEFINED +consider-using-dict-items:10:4:11:30:bad:Consider iterating with .items():UNDEFINED +consider-using-dict-items:22:4:23:35:another_bad:Consider iterating with .items():UNDEFINED +consider-using-dict-items:41:0:43:18::Consider iterating with .items():UNDEFINED +consider-using-dict-items:45:0:46:20::Consider iterating with .items():UNDEFINED +consider-iterating-dictionary:48:10:48:23::Consider iterating the dictionary directly instead of calling .keys():INFERENCE +consider-using-dict-items:48:0:49:20::Consider iterating with .items():UNDEFINED +consider-using-dict-items:55:0:56:24::Consider iterating with .items():UNDEFINED consider-using-dict-items:68:0:None:None::Consider iterating with .items():UNDEFINED -consider-using-dict-items:71:0:None:None::Consider iterating with .items():UNDEFINED +consider-using-dict-items:69:0:None:None::Consider iterating with .items():UNDEFINED consider-using-dict-items:72:0:None:None::Consider iterating with .items():UNDEFINED -consider-using-dict-items:75:0:None:None::Consider iterating with .items():UNDEFINED -consider-iterating-dictionary:86:25:86:42::Consider iterating the dictionary directly instead of calling .keys():INFERENCE -consider-using-dict-items:86:0:None:None::Consider iterating with .items():UNDEFINED -consider-using-dict-items:103:0:105:24::Consider iterating with .items():UNDEFINED +consider-using-dict-items:73:0:None:None::Consider iterating with .items():UNDEFINED +consider-using-dict-items:76:0:None:None::Consider iterating with .items():UNDEFINED +consider-iterating-dictionary:87:25:87:42::Consider iterating the dictionary directly instead of calling .keys():INFERENCE +consider-using-dict-items:87:0:None:None::Consider iterating with .items():UNDEFINED +consider-using-dict-items:104:0:106:24::Consider iterating with .items():UNDEFINED +consider-iterating-dictionary:112:11:112:28::Consider iterating the dictionary directly instead of calling .keys():INFERENCE From bf17fd740525e8bdf308250bddec0076dfd43f6a Mon Sep 17 00:00:00 2001 From: Mark Byrne <31762852+mbyrnepr2@users.noreply.github.com> Date: Sat, 4 May 2024 15:58:04 +0200 Subject: [PATCH 2/8] Update doc/whatsnew/fragments/9554.false_positive Co-authored-by: Pierre Sassoulas --- doc/whatsnew/fragments/9554.false_positive | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/whatsnew/fragments/9554.false_positive b/doc/whatsnew/fragments/9554.false_positive index 4f6382c18c..c8c8d71ac8 100644 --- a/doc/whatsnew/fragments/9554.false_positive +++ b/doc/whatsnew/fragments/9554.false_positive @@ -1,3 +1,3 @@ -Fix a false positive for ``consider-using-dict-items`` when iterating ``os.environ`` using the ``os.environ.keys()`` operation and then deleting an item using the key as a lookup. +Fix a false positive for ``consider-using-dict-items`` when iterating using ``keys()`` and then deleting an item using the key as a lookup. Closes #9554 From 9cc8a2a40d568d5239c0f65c17b0aee636026d8b Mon Sep 17 00:00:00 2001 From: Mark Byrne <31762852+mbyrnepr2@users.noreply.github.com> Date: Sat, 4 May 2024 15:58:30 +0200 Subject: [PATCH 3/8] Update tests/functional/c/consider/consider_using_dict_items.py Co-authored-by: Pierre Sassoulas --- tests/functional/c/consider/consider_using_dict_items.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/functional/c/consider/consider_using_dict_items.py b/tests/functional/c/consider/consider_using_dict_items.py index 41ccd09a10..00fc87577a 100644 --- a/tests/functional/c/consider/consider_using_dict_items.py +++ b/tests/functional/c/consider/consider_using_dict_items.py @@ -108,7 +108,6 @@ class Foo: # False positive in issue #9554 # https://github.com/pylint-dev/pylint/issues/9554 -import os for var in os.environ.keys(): # [consider-iterating-dictionary] if var.startswith('foo_'): del os.environ[var] # index lookup necessary here, do not emit error From b3d15fd68be4ed46a3019958dd4c318879e051b4 Mon Sep 17 00:00:00 2001 From: Mark Byrne <31762852+mbyrnepr2@users.noreply.github.com> Date: Sat, 4 May 2024 15:58:45 +0200 Subject: [PATCH 4/8] Update tests/functional/c/consider/consider_using_dict_items.py Co-authored-by: Pierre Sassoulas --- tests/functional/c/consider/consider_using_dict_items.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/functional/c/consider/consider_using_dict_items.py b/tests/functional/c/consider/consider_using_dict_items.py index 00fc87577a..0e7a7e4504 100644 --- a/tests/functional/c/consider/consider_using_dict_items.py +++ b/tests/functional/c/consider/consider_using_dict_items.py @@ -2,6 +2,9 @@ # pylint: disable=line-too-long,missing-docstring,unsubscriptable-object,too-few-public-methods,redefined-outer-name,use-dict-literal,modified-iterating-dict # pylint: disable=wrong-import-position +import os + + def bad(): a_dict = {1: 1, 2: 2, 3: 3} for k in a_dict: # [consider-using-dict-items] From 530d1e84d7ea532a373374f4757133ca6dfe63c7 Mon Sep 17 00:00:00 2001 From: Mark Byrne Date: Sat, 4 May 2024 16:48:28 +0200 Subject: [PATCH 5/8] Regenerate the functional test output after change to the test module. --- .../c/consider/consider_using_dict_items.txt | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/tests/functional/c/consider/consider_using_dict_items.txt b/tests/functional/c/consider/consider_using_dict_items.txt index e0f8171103..da8637cc19 100644 --- a/tests/functional/c/consider/consider_using_dict_items.txt +++ b/tests/functional/c/consider/consider_using_dict_items.txt @@ -1,17 +1,17 @@ -consider-using-dict-items:7:4:8:24:bad:Consider iterating with .items():UNDEFINED -consider-using-dict-items:10:4:11:30:bad:Consider iterating with .items():UNDEFINED -consider-using-dict-items:22:4:23:35:another_bad:Consider iterating with .items():UNDEFINED -consider-using-dict-items:41:0:43:18::Consider iterating with .items():UNDEFINED -consider-using-dict-items:45:0:46:20::Consider iterating with .items():UNDEFINED -consider-iterating-dictionary:48:10:48:23::Consider iterating the dictionary directly instead of calling .keys():INFERENCE +consider-using-dict-items:10:4:11:24:bad:Consider iterating with .items():UNDEFINED +consider-using-dict-items:13:4:14:30:bad:Consider iterating with .items():UNDEFINED +consider-using-dict-items:25:4:26:35:another_bad:Consider iterating with .items():UNDEFINED +consider-using-dict-items:44:0:46:18::Consider iterating with .items():UNDEFINED consider-using-dict-items:48:0:49:20::Consider iterating with .items():UNDEFINED -consider-using-dict-items:55:0:56:24::Consider iterating with .items():UNDEFINED -consider-using-dict-items:68:0:None:None::Consider iterating with .items():UNDEFINED -consider-using-dict-items:69:0:None:None::Consider iterating with .items():UNDEFINED +consider-iterating-dictionary:51:10:51:23::Consider iterating the dictionary directly instead of calling .keys():INFERENCE +consider-using-dict-items:51:0:52:20::Consider iterating with .items():UNDEFINED +consider-using-dict-items:58:0:59:24::Consider iterating with .items():UNDEFINED +consider-using-dict-items:71:0:None:None::Consider iterating with .items():UNDEFINED consider-using-dict-items:72:0:None:None::Consider iterating with .items():UNDEFINED -consider-using-dict-items:73:0:None:None::Consider iterating with .items():UNDEFINED +consider-using-dict-items:75:0:None:None::Consider iterating with .items():UNDEFINED consider-using-dict-items:76:0:None:None::Consider iterating with .items():UNDEFINED -consider-iterating-dictionary:87:25:87:42::Consider iterating the dictionary directly instead of calling .keys():INFERENCE -consider-using-dict-items:87:0:None:None::Consider iterating with .items():UNDEFINED -consider-using-dict-items:104:0:106:24::Consider iterating with .items():UNDEFINED -consider-iterating-dictionary:112:11:112:28::Consider iterating the dictionary directly instead of calling .keys():INFERENCE +consider-using-dict-items:79:0:None:None::Consider iterating with .items():UNDEFINED +consider-iterating-dictionary:90:25:90:42::Consider iterating the dictionary directly instead of calling .keys():INFERENCE +consider-using-dict-items:90:0:None:None::Consider iterating with .items():UNDEFINED +consider-using-dict-items:107:0:109:24::Consider iterating with .items():UNDEFINED +consider-iterating-dictionary:114:11:114:28::Consider iterating the dictionary directly instead of calling .keys():INFERENCE From 0bd8a1a48888f593991e013a4fbaa96ad70eeeb5 Mon Sep 17 00:00:00 2001 From: Mark Byrne Date: Sat, 4 May 2024 16:53:47 +0200 Subject: [PATCH 6/8] Remove the unnecessary disable. --- .../c/consider/consider_using_dict_items.py | 1 - .../c/consider/consider_using_dict_items.txt | 30 +++++++++---------- 2 files changed, 15 insertions(+), 16 deletions(-) diff --git a/tests/functional/c/consider/consider_using_dict_items.py b/tests/functional/c/consider/consider_using_dict_items.py index 0e7a7e4504..a4337cb9d4 100644 --- a/tests/functional/c/consider/consider_using_dict_items.py +++ b/tests/functional/c/consider/consider_using_dict_items.py @@ -1,6 +1,5 @@ """Emit a message for iteration through dict keys and subscripting dict with key.""" # pylint: disable=line-too-long,missing-docstring,unsubscriptable-object,too-few-public-methods,redefined-outer-name,use-dict-literal,modified-iterating-dict -# pylint: disable=wrong-import-position import os diff --git a/tests/functional/c/consider/consider_using_dict_items.txt b/tests/functional/c/consider/consider_using_dict_items.txt index da8637cc19..9e14751420 100644 --- a/tests/functional/c/consider/consider_using_dict_items.txt +++ b/tests/functional/c/consider/consider_using_dict_items.txt @@ -1,17 +1,17 @@ -consider-using-dict-items:10:4:11:24:bad:Consider iterating with .items():UNDEFINED -consider-using-dict-items:13:4:14:30:bad:Consider iterating with .items():UNDEFINED -consider-using-dict-items:25:4:26:35:another_bad:Consider iterating with .items():UNDEFINED -consider-using-dict-items:44:0:46:18::Consider iterating with .items():UNDEFINED -consider-using-dict-items:48:0:49:20::Consider iterating with .items():UNDEFINED -consider-iterating-dictionary:51:10:51:23::Consider iterating the dictionary directly instead of calling .keys():INFERENCE -consider-using-dict-items:51:0:52:20::Consider iterating with .items():UNDEFINED -consider-using-dict-items:58:0:59:24::Consider iterating with .items():UNDEFINED +consider-using-dict-items:9:4:10:24:bad:Consider iterating with .items():UNDEFINED +consider-using-dict-items:12:4:13:30:bad:Consider iterating with .items():UNDEFINED +consider-using-dict-items:24:4:25:35:another_bad:Consider iterating with .items():UNDEFINED +consider-using-dict-items:43:0:45:18::Consider iterating with .items():UNDEFINED +consider-using-dict-items:47:0:48:20::Consider iterating with .items():UNDEFINED +consider-iterating-dictionary:50:10:50:23::Consider iterating the dictionary directly instead of calling .keys():INFERENCE +consider-using-dict-items:50:0:51:20::Consider iterating with .items():UNDEFINED +consider-using-dict-items:57:0:58:24::Consider iterating with .items():UNDEFINED +consider-using-dict-items:70:0:None:None::Consider iterating with .items():UNDEFINED consider-using-dict-items:71:0:None:None::Consider iterating with .items():UNDEFINED -consider-using-dict-items:72:0:None:None::Consider iterating with .items():UNDEFINED +consider-using-dict-items:74:0:None:None::Consider iterating with .items():UNDEFINED consider-using-dict-items:75:0:None:None::Consider iterating with .items():UNDEFINED -consider-using-dict-items:76:0:None:None::Consider iterating with .items():UNDEFINED -consider-using-dict-items:79:0:None:None::Consider iterating with .items():UNDEFINED -consider-iterating-dictionary:90:25:90:42::Consider iterating the dictionary directly instead of calling .keys():INFERENCE -consider-using-dict-items:90:0:None:None::Consider iterating with .items():UNDEFINED -consider-using-dict-items:107:0:109:24::Consider iterating with .items():UNDEFINED -consider-iterating-dictionary:114:11:114:28::Consider iterating the dictionary directly instead of calling .keys():INFERENCE +consider-using-dict-items:78:0:None:None::Consider iterating with .items():UNDEFINED +consider-iterating-dictionary:89:25:89:42::Consider iterating the dictionary directly instead of calling .keys():INFERENCE +consider-using-dict-items:89:0:None:None::Consider iterating with .items():UNDEFINED +consider-using-dict-items:106:0:108:24::Consider iterating with .items():UNDEFINED +consider-iterating-dictionary:113:11:113:28::Consider iterating the dictionary directly instead of calling .keys():INFERENCE From 7b5ddeaf2b3a8a84569bd7166ddf7c977b624cd1 Mon Sep 17 00:00:00 2001 From: Mark Byrne Date: Sat, 4 May 2024 16:54:40 +0200 Subject: [PATCH 7/8] Run black. --- .../c/consider/consider_using_dict_items.py | 28 ++++++++++++------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/tests/functional/c/consider/consider_using_dict_items.py b/tests/functional/c/consider/consider_using_dict_items.py index a4337cb9d4..be8ba152a4 100644 --- a/tests/functional/c/consider/consider_using_dict_items.py +++ b/tests/functional/c/consider/consider_using_dict_items.py @@ -1,4 +1,5 @@ """Emit a message for iteration through dict keys and subscripting dict with key.""" + # pylint: disable=line-too-long,missing-docstring,unsubscriptable-object,too-few-public-methods,redefined-outer-name,use-dict-literal,modified-iterating-dict import os @@ -18,12 +19,15 @@ def good(): for k in a_dict: print(k) + out_of_scope_dict = dict() + def another_bad(): for k in out_of_scope_dict: # [consider-using-dict-items] print(out_of_scope_dict[k]) + def another_good(): for k in out_of_scope_dict: k = 1 @@ -50,9 +54,11 @@ def another_good(): for k4 in b_dict.keys(): # [consider-iterating-dictionary,consider-using-dict-items] val = b_dict[k4] + class Foo: c_dict = {} + # Should emit warning when iterating over a dict attribute of a class for k5 in Foo.c_dict: # [consider-using-dict-items] val = Foo.c_dict[k5] @@ -86,30 +92,32 @@ class Foo: val = any(True for k8 in Foo.c_dict if c_dict[k8]) # Should emit warning, using .keys() of Foo.c_dict -val = any(True for k8 in Foo.c_dict.keys() if Foo.c_dict[k8]) # [consider-iterating-dictionary,consider-using-dict-items] +val = any( + True for k8 in Foo.c_dict.keys() if Foo.c_dict[k8] +) # [consider-iterating-dictionary,consider-using-dict-items] # Test false positive described in #4630 # (https://github.com/pylint-dev/pylint/issues/4630) -d = {'key': 'value'} +d = {"key": "value"} for k in d: # this is fine, with the reassignment of d[k], d[k] is necessary - d[k] += '123' - if '1' in d[k]: # index lookup necessary here, do not emit error - print('found 1') + d[k] += "123" + if "1" in d[k]: # index lookup necessary here, do not emit error + print("found 1") for k in d: # if this gets rewritten to d.items(), we are back to the above problem d[k] = d[k] + 1 - if '1' in d[k]: # index lookup necessary here, do not emit error - print('found 1') + if "1" in d[k]: # index lookup necessary here, do not emit error + print("found 1") for k in d: # [consider-using-dict-items] - if '1' in d[k]: # index lookup necessary here, do not emit error - print('found 1') + if "1" in d[k]: # index lookup necessary here, do not emit error + print("found 1") # False positive in issue #9554 # https://github.com/pylint-dev/pylint/issues/9554 for var in os.environ.keys(): # [consider-iterating-dictionary] - if var.startswith('foo_'): + if var.startswith("foo_"): del os.environ[var] # index lookup necessary here, do not emit error From 1f2a0dab1f2d65bdbbc3fca695f2cc3d75c04ff9 Mon Sep 17 00:00:00 2001 From: Mark Byrne Date: Sat, 4 May 2024 17:50:01 +0200 Subject: [PATCH 8/8] Regenerate functional test output again (after running black). --- .../c/consider/consider_using_dict_items.py | 4 +-- .../c/consider/consider_using_dict_items.txt | 34 +++++++++---------- 2 files changed, 18 insertions(+), 20 deletions(-) diff --git a/tests/functional/c/consider/consider_using_dict_items.py b/tests/functional/c/consider/consider_using_dict_items.py index be8ba152a4..16f73d1dcd 100644 --- a/tests/functional/c/consider/consider_using_dict_items.py +++ b/tests/functional/c/consider/consider_using_dict_items.py @@ -92,9 +92,7 @@ class Foo: val = any(True for k8 in Foo.c_dict if c_dict[k8]) # Should emit warning, using .keys() of Foo.c_dict -val = any( - True for k8 in Foo.c_dict.keys() if Foo.c_dict[k8] -) # [consider-iterating-dictionary,consider-using-dict-items] +val = any(True for k8 in Foo.c_dict.keys() if Foo.c_dict[k8]) # [consider-iterating-dictionary,consider-using-dict-items] # Test false positive described in #4630 # (https://github.com/pylint-dev/pylint/issues/4630) diff --git a/tests/functional/c/consider/consider_using_dict_items.txt b/tests/functional/c/consider/consider_using_dict_items.txt index 9e14751420..63f684cc6a 100644 --- a/tests/functional/c/consider/consider_using_dict_items.txt +++ b/tests/functional/c/consider/consider_using_dict_items.txt @@ -1,17 +1,17 @@ -consider-using-dict-items:9:4:10:24:bad:Consider iterating with .items():UNDEFINED -consider-using-dict-items:12:4:13:30:bad:Consider iterating with .items():UNDEFINED -consider-using-dict-items:24:4:25:35:another_bad:Consider iterating with .items():UNDEFINED -consider-using-dict-items:43:0:45:18::Consider iterating with .items():UNDEFINED -consider-using-dict-items:47:0:48:20::Consider iterating with .items():UNDEFINED -consider-iterating-dictionary:50:10:50:23::Consider iterating the dictionary directly instead of calling .keys():INFERENCE -consider-using-dict-items:50:0:51:20::Consider iterating with .items():UNDEFINED -consider-using-dict-items:57:0:58:24::Consider iterating with .items():UNDEFINED -consider-using-dict-items:70:0:None:None::Consider iterating with .items():UNDEFINED -consider-using-dict-items:71:0:None:None::Consider iterating with .items():UNDEFINED -consider-using-dict-items:74:0:None:None::Consider iterating with .items():UNDEFINED -consider-using-dict-items:75:0:None:None::Consider iterating with .items():UNDEFINED -consider-using-dict-items:78:0:None:None::Consider iterating with .items():UNDEFINED -consider-iterating-dictionary:89:25:89:42::Consider iterating the dictionary directly instead of calling .keys():INFERENCE -consider-using-dict-items:89:0:None:None::Consider iterating with .items():UNDEFINED -consider-using-dict-items:106:0:108:24::Consider iterating with .items():UNDEFINED -consider-iterating-dictionary:113:11:113:28::Consider iterating the dictionary directly instead of calling .keys():INFERENCE +consider-using-dict-items:10:4:11:24:bad:Consider iterating with .items():UNDEFINED +consider-using-dict-items:13:4:14:30:bad:Consider iterating with .items():UNDEFINED +consider-using-dict-items:27:4:28:35:another_bad:Consider iterating with .items():UNDEFINED +consider-using-dict-items:47:0:49:18::Consider iterating with .items():UNDEFINED +consider-using-dict-items:51:0:52:20::Consider iterating with .items():UNDEFINED +consider-iterating-dictionary:54:10:54:23::Consider iterating the dictionary directly instead of calling .keys():INFERENCE +consider-using-dict-items:54:0:55:20::Consider iterating with .items():UNDEFINED +consider-using-dict-items:63:0:64:24::Consider iterating with .items():UNDEFINED +consider-using-dict-items:76:0:None:None::Consider iterating with .items():UNDEFINED +consider-using-dict-items:77:0:None:None::Consider iterating with .items():UNDEFINED +consider-using-dict-items:80:0:None:None::Consider iterating with .items():UNDEFINED +consider-using-dict-items:81:0:None:None::Consider iterating with .items():UNDEFINED +consider-using-dict-items:84:0:None:None::Consider iterating with .items():UNDEFINED +consider-iterating-dictionary:95:25:95:42::Consider iterating the dictionary directly instead of calling .keys():INFERENCE +consider-using-dict-items:95:0:None:None::Consider iterating with .items():UNDEFINED +consider-using-dict-items:112:0:114:24::Consider iterating with .items():UNDEFINED +consider-iterating-dictionary:119:11:119:28::Consider iterating the dictionary directly instead of calling .keys():INFERENCE