77# See https://aboutcode.org for more information about nexB OSS projects.
88#
99
10+ import ast
1011import operator
1112import os
1213import 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
315346DEFAULT_ENVIRONMENT = utils_pypi .Environment .from_pyver_and_os (
0 commit comments