-
-
Notifications
You must be signed in to change notification settings - Fork 19
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support reading annotated variables. #102
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
Support reading annotated variables (e.g. `__requires__: list[str] = ["jaraco.functools"]`). |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,5 @@ | ||
import abc | ||
import ast | ||
import contextlib | ||
import itertools | ||
import json | ||
import pathlib | ||
|
@@ -151,24 +150,28 @@ def read_python(self): | |
>>> DepsReader(r"__requires__='foo\nbar\n#baz'").read() | ||
['foo', 'bar'] | ||
""" | ||
raw_reqs = suppress(ValueError)(self._read)('__requires__') or [] | ||
raw_reqs = self._read('__requires__', default=()) | ||
reqs_items = jaraco.text.yield_lines(raw_reqs) | ||
deps = Dependencies.load(reqs_items) | ||
with contextlib.suppress(Exception): | ||
deps.index_url = self._read('__index_url__') | ||
deps.index_url = self._read('__index_url__') | ||
return deps | ||
|
||
def _read(self, var_name): | ||
def _read(self, var_name, default=None): | ||
mod = ast.parse(self.script) | ||
(node,) = ( | ||
node | ||
for node in mod.body | ||
if isinstance(node, ast.Assign) | ||
and len(node.targets) == 1 | ||
and isinstance(node.targets[0], ast.Name) | ||
and node.targets[0].id == var_name | ||
) | ||
return ast.literal_eval(node.value) | ||
code = None | ||
for node in mod.body: | ||
if isinstance(node, ast.Assign) and len(node.targets) == 1: | ||
(target,) = node.targets | ||
elif isinstance(node, ast.AnnAssign): | ||
target = node.target | ||
else: | ||
continue | ||
if isinstance(target, ast.Name) and target.id == var_name: | ||
if code: | ||
code = None | ||
break | ||
Comment on lines
+170
to
+172
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It took me a while to figure out that this block here is for the duplication detection. It's nested several levels deep and alters other state variables, entangling it with the other concerns in this method. Much better would be to have a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I see. But why would it be a different outcome? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm suggesting the same outcome, just a different approach. |
||
code = node.value | ||
return ast.literal_eval(code) if code else default | ||
Comment on lines
+161
to
+174
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This rewrite of the function changes the mccabe cyclomatic complexity from 1 to 6, indicating that the new code is substantially more complex. This change introduces two new state variables ( |
||
|
||
|
||
class SourceDepsReader(DepsReader): | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, interesting - TIL an
AnnAssign
can never be part of a multi-target assignment: