7
7
# See https://aboutcode.org for more information about nexB OSS projects.
8
8
#
9
9
10
+ import ast
10
11
import operator
11
12
import os
12
13
import re
@@ -282,7 +283,7 @@ def get_requirements_from_python_manifest(
282
283
"""
283
284
Return a list of parsed requirements from the ``sdist_location`` sdist location
284
285
"""
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
286
287
# And no deps have been yielded by requirements file.
287
288
requirements = list (
288
289
get_reqs_from_requirements_file_in_sdist (
@@ -303,13 +304,43 @@ def get_requirements_from_python_manifest(
303
304
# Do not raise exception here as we may have a setup.py that does not
304
305
# have any dependencies.
305
306
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
+ )
313
344
314
345
315
346
DEFAULT_ENVIRONMENT = utils_pypi .Environment .from_pyver_and_os (
0 commit comments