summaryrefslogtreecommitdiff
path: root/tests/functional/u/unnecessary/unnecessary_dict_index_lookup.py
blob: 7ae5488ce799dc0a05ff8769ce1c2c84b7cded9f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
# pylint: disable=missing-docstring, too-few-public-methods, expression-not-assigned, line-too-long

a_dict = {}
b_dict = {}

for k, v in a_dict.items():
    print(a_dict[k])  # [unnecessary-dict-index-lookup]
    print(b_dict[k])  # Should not emit warning, accessing other dictionary
    a_dict[k] = 123  # Should not emit warning, key access necessary
    a_dict[k] += 123  # Should not emit warning, key access necessary
    print(a_dict[k])  # Should not emit warning, v != a_dict[k]

for k, v in b_dict.items():
    print(k)
    k = "another key"
    print(b_dict[k])  # This is fine, key reassigned


# Tests on comprehensions
A = {v: 1 for k, v in a_dict.items() if a_dict[k]}  # [unnecessary-dict-index-lookup]
B = {v: 1 for k, v in a_dict.items() if k}  # This is fine, no indexing
C = {a_dict[k]: 1 for k, v in a_dict.items() if k}  # [unnecessary-dict-index-lookup]
# +1: [unnecessary-dict-index-lookup, unnecessary-dict-index-lookup]
D = {a_dict[k]: 1 for k, v in a_dict.items() if a_dict[k]}

E = [v for k, v in a_dict.items() if a_dict[k]]  # [unnecessary-dict-index-lookup]
F = [v for k, v in a_dict.items() if k]  # This is fine, no indexing
G = [a_dict[k] for k, v in a_dict.items() if k]  # [unnecessary-dict-index-lookup]
# +1: [unnecessary-dict-index-lookup, unnecessary-dict-index-lookup]
H = [a_dict[k] for k, v in a_dict.items() if a_dict[k]]


# Tests on dict attribute of a class
class Foo:
    c_dict = {}


for k, v in Foo.c_dict.items():
    print(b_dict[k])  # Should not emit warning, accessing other dictionary
    print(Foo.c_dict[k])  # [unnecessary-dict-index-lookup]
    unnecessary = 0  # pylint: disable=invalid-name
    unnecessary += Foo.c_dict[k]  # [unnecessary-dict-index-lookup]
    Foo.c_dict[k] += v  # key access necessary

# Tests on comprehensions
S = {v: 1 for k, v in Foo.c_dict.items() if Foo.c_dict[k]}  # [unnecessary-dict-index-lookup]
J = {v: 1 for k, v in Foo.c_dict.items() if k}  # This is fine, no indexing
K = {Foo.c_dict[k]: 1 for k, v in Foo.c_dict.items() if k}  # [unnecessary-dict-index-lookup]
# +1: [unnecessary-dict-index-lookup, unnecessary-dict-index-lookup]
L = {Foo.c_dict[k]: 1 for k, v in Foo.c_dict.items() if Foo.c_dict[k]}

M = [v for k, v in Foo.c_dict.items() if Foo.c_dict[k]]  # [unnecessary-dict-index-lookup]
N = [v for k, v in Foo.c_dict.items() if k]  # This is fine, no indexing
T = [Foo.c_dict[k] for k, v in Foo.c_dict.items() if k]  # [unnecessary-dict-index-lookup]
# +1: [unnecessary-dict-index-lookup, unnecessary-dict-index-lookup]
P = [Foo.c_dict[k] for k, v in Foo.c_dict.items() if Foo.c_dict[k]]

# Test assigning d.items() to a single variable
d = {1: "a", 2: "b"}
for item in d.items():
    print(item[0])
    print(d[item[0]])  # [unnecessary-dict-index-lookup]

Q = [item[0] for item in d.items()]
R = [d[item[0]] for item in d.items()]  # [unnecessary-dict-index-lookup]

# Reassigning single var
for item in d.items():
    print(item[0])
    print(d[item[0]])  # [unnecessary-dict-index-lookup]
    item = (2, "b")
    print(d[item[0]])  # This is fine, no warning thrown as key has been reassigned


# Test false positive described in #4630
# (https://github.com/PyCQA/pylint/issues/4630)

d = {'key': 'value'}

for k, _ in d.items():
    d[k] += 'VALUE'
    if 'V' in d[k]:  # This is fine, if d[k] is replaced with _, the semantics change
        print('found V')


for k, _ in d.items():
    if 'V' in d[k]:  # [unnecessary-dict-index-lookup]
        d[k] = "value"
        print(d[k])  # This is fine

# Test false positive described in #4716
# Should not be emitted for del
# (https://github.com/PyCQA/pylint/issues/4716)
d = {}
for key, val in d.items():
    del d[key]
    break

for item in d.items():
    del d[item[0]]
    break

outer_dict = {"inner_dict": {}}
for key, val in outer_dict.items():
    for key_two, val_two in val.items():
        del outer_dict[key][key_two]  # [unnecessary-dict-index-lookup]
        break

# Test partial unpacking of items
# https://github.com/PyCQA/pylint/issues/5504

d = {}
for key, in d.items():
    print(d[key])

# Test subscripting an attribute
# https://github.com/PyCQA/pylint/issues/6557
f = Foo()
for input_output in d.items():
    f.input_output = input_output  # pylint: disable=attribute-defined-outside-init
    print(d[f.input_output[0]])