Skip to content

Commit 685c80c

Browse files
committed
Add support for annotated assignments to static attribute lookup.
When walking the ast of a module, look for AnnAssign nodes in addition to Assign to support assignments with type annotations, for example. Since we have to read different attributes, split the generators into a for loop. Existing ast.Assign nodes follow the same processing as before.
1 parent be63232 commit 685c80c

2 files changed

Lines changed: 25 additions & 16 deletions

File tree

setuptools/config/expand.py

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -69,24 +69,21 @@ def __init__(self, name: str, spec: ModuleSpec):
6969
def __getattr__(self, attr):
7070
"""Attempt to load an attribute "statically", via :func:`ast.literal_eval`."""
7171
try:
72-
assignment_expressions = (
73-
statement
74-
for statement in self.module.body
75-
if isinstance(statement, ast.Assign)
76-
)
77-
expressions_with_target = (
78-
(statement, target)
79-
for statement in assignment_expressions
80-
for target in statement.targets
81-
)
82-
matching_values = (
83-
statement.value
84-
for statement, target in expressions_with_target
85-
if isinstance(target, ast.Name) and target.id == attr
86-
)
87-
return next(ast.literal_eval(value) for value in matching_values)
72+
for statement in self.module.body:
73+
if isinstance(statement, ast.Assign):
74+
targets = statement.targets
75+
value = statement.value
76+
elif isinstance(statement, ast.AnnAssign):
77+
targets = [statement.target]
78+
value = statement.value
79+
else:
80+
continue
81+
for target in targets:
82+
if isinstance(target, ast.Name) and target.id == attr:
83+
return ast.literal_eval(value)
8884
except Exception as e:
8985
raise AttributeError(f"{self.name} has no attribute {attr}") from e
86+
raise AttributeError(f"{self.name} has no attribute {attr}")
9087

9188

9289
def glob_relative(

setuptools/tests/config/test_expand.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,18 @@ def test_read_attr(self, tmp_path, monkeypatch):
8585
values = expand.read_attr('lib.mod.VALUES', {'lib': 'pkg/sub'}, tmp_path)
8686
assert values['c'] == (0, 1, 1)
8787

88+
def test_read_annotated_attr(self, tmp_path):
89+
files = {
90+
"pkg/__init__.py": "",
91+
"pkg/sub/__init__.py": (
92+
"VERSION: str = '0.1.1'\n"
93+
"raise SystemExit(1)\n"
94+
),
95+
}
96+
write_files(files, tmp_path)
97+
# Make sure this attribute can be read statically
98+
assert expand.read_attr('pkg.sub.VERSION', root_dir=tmp_path) == '0.1.1'
99+
88100
def test_import_order(self, tmp_path):
89101
"""
90102
Sometimes the import machinery will import the parent package of a nested

0 commit comments

Comments
 (0)