Skip to content

Commit aa64f26

Browse files
committed
Obtain install_requires via AST.
Signed-off-by: Bennati, Stefano <[email protected]>
1 parent 4e0cae5 commit aa64f26

File tree

1 file changed

+39
-8
lines changed

1 file changed

+39
-8
lines changed

src/python_inspector/resolution.py

Lines changed: 39 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
# See https://aboutcode.org for more information about nexB OSS projects.
88
#
99

10+
import ast
1011
import operator
1112
import os
1213
import re
@@ -282,7 +283,7 @@ def get_requirements_from_python_manifest(
282283
"""
283284
Return a list of parsed requirements from the ``sdist_location`` sdist location
284285
"""
285-
# Look in requirements file if and only if thy are refered in setup.py or setup.cfg
286+
# Look in requirements file if and only if they are refered in setup.py or setup.cfg
286287
# And no deps have been yielded by requirements file.
287288
requirements = list(
288289
get_reqs_from_requirements_file_in_sdist(
@@ -303,13 +304,43 @@ def get_requirements_from_python_manifest(
303304
# Do not raise exception here as we may have a setup.py that does not
304305
# have any dependencies.
305306
with (open(setup_py_location)) as sf:
306-
match = re.search(r"install_requires[\s]*=[\s]*\[([^\]]*)\]", sf.read())
307-
if match is not None:
308-
install_requires = re.sub(r"\s", "", match.group(1))
309-
if install_requires != "":
310-
raise Exception(
311-
f"Unable to collect setup.py dependencies securely: {setup_py_location}"
312-
)
307+
file_contents = sf.read()
308+
node = ast.parse(file_contents)
309+
setup_fct = [
310+
elem
311+
for elem in ast.walk(node)
312+
if (
313+
isinstance(elem, ast.Expr)
314+
and isinstance(elem.value, ast.Call)
315+
and isinstance(elem.value.func, ast.Name)
316+
and elem.value.func.id == "setup"
317+
)
318+
]
319+
if len(setup_fct) == 0:
320+
raise Exception(
321+
f"Unable to collect setup.py dependencies securely: {setup_py_location}"
322+
)
323+
if len(setup_fct) > 1:
324+
print(
325+
f"Warning: identified multiple definitions of 'setup()' in {setup_py_location}, defaulting to the first occurrence"
326+
)
327+
setup_fct = setup_fct[0]
328+
install_requires = [
329+
k.value for k in setup_fct.value.keywords if k.arg == "install_requires"
330+
]
331+
if len(install_requires) == 0:
332+
raise Exception(
333+
f"Unable to collect setup.py dependencies securely: {setup_py_location}"
334+
)
335+
if len(install_requires) > 1:
336+
print(
337+
f"Warning: identified multiple definitions of 'install_requires' in {setup_py_location}, defaulting to the first occurrence"
338+
)
339+
install_requires = install_requires[0].elts
340+
if len(install_requires) != 0:
341+
raise Exception(
342+
f"Unable to collect setup.py dependencies securely: {setup_py_location}"
343+
)
313344

314345

315346
DEFAULT_ENVIRONMENT = utils_pypi.Environment.from_pyver_and_os(

0 commit comments

Comments
 (0)