@@ -102,6 +102,66 @@ def _parse_eval_file(test: str, content: str) -> tuple[list[error], Namespace |
102102 return expected , options
103103
104104
105+ @pytest .mark .parametrize (
106+ "source, expected" ,
107+ [
108+ ("for i in xs:\n for i in ys:\n print(i)\n print(i)" , ["i" ]),
109+ (
110+ "for i in xs:\n for j in ys:\n for i in zs:\n print(i)" ,
111+ ["i" ],
112+ ),
113+ ("for i, j in xs:\n for j, i in ys:\n print(i, j)" , ["j" , "i" ]),
114+ ("for i in xs:\n for first, (*i,) in ys:\n print(i)" , ["i" ]),
115+ (
116+ "for i in xs:\n if flag:\n for i in ys:\n print(i)" ,
117+ ["i" ],
118+ ),
119+ (
120+ "async def f():\n async for i in xs:\n "
121+ " for i in ys:\n print(i)" ,
122+ ["i" ],
123+ ),
124+ (
125+ "async def f():\n for i in xs:\n "
126+ " async for i in ys:\n print(i)" ,
127+ ["i" ],
128+ ),
129+ (
130+ "for i in xs:\n for i in ys:\n for i in zs:\n print(i)" ,
131+ ["i" , "i" ],
132+ ),
133+ ("for i in xs:\n for j in ys:\n print(i, j)" , []),
134+ ("for i in xs:\n print(i)\n for i in ys:\n print(i)" , []),
135+ ("for _ in xs:\n for _ in ys:\n pass" , []),
136+ ("for _unused in xs:\n for _unused in ys:\n pass" , []),
137+ ("for obj in xs:\n for obj.attr in ys:\n pass" , []),
138+ ("for i in xs:\n for values[i] in ys:\n pass" , []),
139+ ("for i in xs:\n for values[[i for i in zs][0]] in ys:\n pass" , []),
140+ ("for values[[i for i in zs][0]] in xs:\n for i in ys:\n pass" , []),
141+ ("for obj.attr in xs:\n for obj in ys:\n pass" , []),
142+ ("for i in xs:\n values = [i for i in ys]" , []),
143+ ("for i in xs:\n def f():\n for i in ys:\n print(i)" , []),
144+ (
145+ "for i in xs:\n async def f():\n "
146+ " async for i in ys:\n print(i)" ,
147+ [],
148+ ),
149+ ("for i in xs:\n class C:\n for i in ys:\n print(i)" , []),
150+ ("for i in xs:\n print(i)\n else:\n for i in ys:\n print(i)" , []),
151+ (
152+ "for i in xs:\n for j in ys:\n pass\n "
153+ " else:\n for i in zs:\n print(i)" ,
154+ ["i" ],
155+ ),
156+ ],
157+ )
158+ def test_nested_loop_bindings (source , expected ):
159+ visitor = BugBearVisitor (filename = "example.py" , lines = source .splitlines ())
160+ visitor .visit (ast .parse (source ))
161+ errors = [error for error in visitor .errors if error .message .startswith ("B045" )]
162+ assert [error .vars [0 ] for error in errors ] == expected
163+
164+
105165class BugbearTestCase (unittest .TestCase ):
106166 maxDiff = None
107167
0 commit comments