|
9 | 9 | from dataclasses import replace
|
10 | 10 | from pathlib import Path
|
11 | 11 | from tempfile import NamedTemporaryFile
|
12 |
| -from typing import Callable, Iterable, Iterator, NamedTuple, Optional, Tuple |
| 12 | +from typing import Callable, Iterable, Iterator, NamedTuple, Optional, Tuple, Union |
13 | 13 |
|
14 | 14 | from pip_requirements_parser import RequirementsFile # type: ignore[import]
|
15 | 15 | from pkg_resources import Requirement
|
@@ -79,24 +79,32 @@ def parse_setup_py(path: Path) -> Iterator[DeclaredDependency]: # noqa: C901
|
79 | 79 | # resolve any variable references in the arguments to the setup() call.
|
80 | 80 | tracked_vars = VariableTracker(source)
|
81 | 81 |
|
82 |
| - def _extract_deps_from_setup_call( # noqa: C901 |
| 82 | + def _extract_deps_from_value( |
| 83 | + value: Union[str, Iterable[str]], |
| 84 | + node: ast.AST, |
| 85 | + ) -> Iterator[DeclaredDependency]: |
| 86 | + if isinstance(value, str): # expected list, but got string |
| 87 | + value = [value] # parse as if a single-element list is given |
| 88 | + try: |
| 89 | + for item in value: |
| 90 | + yield parse_one_req(item, source) |
| 91 | + except ValueError as e: # parse_one_req() failed |
| 92 | + raise DependencyParsingError(node) from e |
| 93 | + |
| 94 | + def _extract_deps_from_setup_call( |
83 | 95 | node: ast.Call,
|
84 | 96 | ) -> Iterator[DeclaredDependency]:
|
85 | 97 | for keyword in node.keywords:
|
86 | 98 | try:
|
87 | 99 | if keyword.arg == "install_requires":
|
88 | 100 | value = tracked_vars.resolve(keyword.value)
|
89 |
| - if not isinstance(value, list): |
90 |
| - raise DependencyParsingError(keyword.value) |
91 |
| - for item in value: |
92 |
| - yield parse_one_req(item, source) |
| 101 | + yield from _extract_deps_from_value(value, keyword.value) |
93 | 102 | elif keyword.arg == "extras_require":
|
94 | 103 | value = tracked_vars.resolve(keyword.value)
|
95 | 104 | if not isinstance(value, dict):
|
96 | 105 | raise DependencyParsingError(keyword.value)
|
97 | 106 | for items in value.values():
|
98 |
| - for item in items: |
99 |
| - yield parse_one_req(item, source) |
| 107 | + yield from _extract_deps_from_value(items, keyword.value) |
100 | 108 | except (DependencyParsingError, CannotResolve) as exc:
|
101 | 109 | if sys.version_info >= (3, 9):
|
102 | 110 | unparsed_content = ast.unparse(exc.node)
|
|
0 commit comments