Skip to content

Commit 27e29f7

Browse files
committed
Don't track names, just line numbers
1 parent ae9d62c commit 27e29f7

File tree

2 files changed

+45
-22
lines changed

2 files changed

+45
-22
lines changed

dowsing/setuptools/setup_py_parsing.py

Lines changed: 25 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ def visit_Call(self, node: cst.Call) -> Optional[bool]:
189189
PRETEND_ARGV = ["setup.py", "bdist_wheel"]
190190

191191
def evaluate_in_scope(
192-
self, item: cst.CSTNode, scope: Any, target_name: str = "", target_line: int = 0
192+
self, item: cst.CSTNode, scope: Any, target_line: int = 0
193193
) -> Any:
194194
qnames = self.get_metadata(QualifiedNameProvider, item)
195195

@@ -211,20 +211,26 @@ def evaluate_in_scope(
211211
reverse=True,
212212
)
213213
# Walk assignments from bottom to top, evaluating them recursively.
214-
# When recursing, only look at assignments above the "target line".
215214
for lineno, node in assignment_nodes:
215+
216+
# When recursing, only look at assignments above the "target line".
217+
if target_line and lineno >= target_line:
218+
continue
219+
216220
# Assign(
217221
# targets=[AssignTarget(target=Name(value="v"))],
218222
# value=SimpleString(value="'x'"),
219223
# )
224+
#
225+
# AugAssign(
226+
# target=Name(value="v"),
227+
# operator=AddAssign(...),
228+
# value=SimpleString(value="'x'"),
229+
# )
230+
#
220231
# TODO or an import...
221232
# TODO builtins have BuiltinAssignment
222233

223-
# we have recursed, likey due to `x = x + y` assignment or similar
224-
# self-referential evaluation, and can't
225-
if target_name and target_name == name and lineno >= target_line:
226-
continue
227-
228234
try:
229235
if node:
230236
parent = self.get_metadata(ParentNodeProvider, node)
@@ -245,9 +251,9 @@ def evaluate_in_scope(
245251

246252
# This presumes a single assignment
247253
if isinstance(gp, cst.Assign) and len(gp.targets) == 1:
248-
result = self.evaluate_in_scope(gp.value, scope, name, lineno)
254+
result = self.evaluate_in_scope(gp.value, scope, lineno)
249255
elif isinstance(parent, cst.AugAssign):
250-
result = self.evaluate_in_scope(parent, scope, name, lineno)
256+
result = self.evaluate_in_scope(parent, scope, lineno)
251257
else:
252258
# too complicated?
253259
continue
@@ -265,7 +271,6 @@ def evaluate_in_scope(
265271
self.evaluate_in_scope(
266272
el.value,
267273
self.get_metadata(ScopeProvider, el),
268-
target_name,
269274
target_line,
270275
)
271276
)
@@ -284,12 +289,10 @@ def evaluate_in_scope(
284289
for arg in item.args:
285290
if isinstance(arg.keyword, cst.Name):
286291
args[names.index(arg.keyword.value)] = self.evaluate_in_scope(
287-
arg.value, scope, target_name, target_line
292+
arg.value, scope, target_line
288293
)
289294
else:
290-
args[i] = self.evaluate_in_scope(
291-
arg.value, scope, target_name, target_line
292-
)
295+
args[i] = self.evaluate_in_scope(arg.value, scope, target_line)
293296
i += 1
294297

295298
# TODO clear ones that are still default
@@ -303,7 +306,7 @@ def evaluate_in_scope(
303306
for arg in item.args:
304307
if isinstance(arg.keyword, cst.Name):
305308
d[arg.keyword.value] = self.evaluate_in_scope(
306-
arg.value, scope, target_name, target_line
309+
arg.value, scope, target_line
307310
)
308311
# TODO something with **kwargs
309312
return d
@@ -312,19 +315,19 @@ def evaluate_in_scope(
312315
for el2 in item.elements:
313316
if isinstance(el2, cst.DictElement):
314317
d[self.evaluate_in_scope(el2.key, scope)] = self.evaluate_in_scope(
315-
el2.value, scope, target_name, target_line
318+
el2.value, scope, target_line
316319
)
317320
return d
318321
elif isinstance(item, cst.Subscript):
319-
lhs = self.evaluate_in_scope(item.value, scope, target_name, target_line)
322+
lhs = self.evaluate_in_scope(item.value, scope, target_line)
320323
if isinstance(lhs, str):
321324
# A "??" entry, propagate
322325
return "??"
323326

324327
# TODO: Figure out why this is Sequence
325328
if isinstance(item.slice[0].slice, cst.Index):
326329
rhs = self.evaluate_in_scope(
327-
item.slice[0].slice.value, scope, target_name, target_line
330+
item.slice[0].slice.value, scope, target_line
328331
)
329332
try:
330333
if isinstance(lhs, dict):
@@ -338,8 +341,8 @@ def evaluate_in_scope(
338341
# LOG.warning(f"Omit2 {type(item.slice[0].slice)!r}")
339342
return "??"
340343
elif isinstance(item, cst.BinaryOperation):
341-
lhs = self.evaluate_in_scope(item.left, scope, target_name, target_line)
342-
rhs = self.evaluate_in_scope(item.right, scope, target_name, target_line)
344+
lhs = self.evaluate_in_scope(item.left, scope, target_line)
345+
rhs = self.evaluate_in_scope(item.right, scope, target_line)
343346
if lhs == "??" or rhs == "??":
344347
return "??"
345348
if isinstance(item.operator, cst.Add):
@@ -350,8 +353,8 @@ def evaluate_in_scope(
350353
else:
351354
return "??"
352355
elif isinstance(item, cst.AugAssign):
353-
lhs = self.evaluate_in_scope(item.target, scope, target_name, target_line)
354-
rhs = self.evaluate_in_scope(item.value, scope, target_name, target_line)
356+
lhs = self.evaluate_in_scope(item.target, scope, target_line)
357+
rhs = self.evaluate_in_scope(item.value, scope, target_line)
355358
if lhs == "??" or rhs == "??":
356359
return "??"
357360
if isinstance(item.operator, cst.AddAssign):

dowsing/tests/setuptools.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -373,3 +373,23 @@ def test_self_reference_assignments(self) -> None:
373373
self.assertEqual(d.name, "foobar")
374374
self.assertEqual(d.version, "base.suffix")
375375
self.assertListEqual(d.classifiers, ["123", "abc", "xyz"])
376+
377+
def test_circular_references(self) -> None:
378+
d = self._read(
379+
"""\
380+
from setuptools import setup
381+
382+
name = "foo"
383+
384+
foo = bar
385+
bar = version
386+
version = foo
387+
388+
setup(
389+
name=name,
390+
version=version,
391+
)
392+
"""
393+
)
394+
self.assertEqual(d.name, "foo")
395+
self.assertEqual(d.version, "??")

0 commit comments

Comments
 (0)