Open voidus opened 6 years ago
The following script might be a starting point, just pipe the output to safety
. Be careful with the input tho as this use ast.parse()
and could happily execute malicious code in the setup.py.
#!/usr/bin/env python3
"""
Returns a safety-readable list of requirements from a setup.py python script
Code heavily inspired by https://stackoverflow.com/a/24237067
Usage:
$ ./parse_setup.py /path/to/setup.py
"""
import ast
import sys
import textwrap
def parse_setup(setup_filename):
"""Parse setup.py and return args and keywords args to its setup
function call
"""
mock_setup = textwrap.dedent('''\
def setup(*args, **kwargs):
__setup_calls__.append((args, kwargs))
''')
parsed_mock_setup = ast.parse(mock_setup, filename=setup_filename)
with open(setup_filename, 'rt') as setup_file:
parsed = ast.parse(setup_file.read())
for index, node in enumerate(parsed.body[:]):
if (
not isinstance(node, ast.Expr) or
not isinstance(node.value, ast.Call) or
node.value.func.id != 'setup'
):
continue
parsed.body[index:index] = parsed_mock_setup.body
break
fixed = ast.fix_missing_locations(parsed)
codeobj = compile(fixed, setup_filename, 'exec')
local_vars = {}
global_vars = {'__setup_calls__': []}
exec(codeobj, global_vars, local_vars)
return global_vars['__setup_calls__'][0]
if __name__ == '__main__':
filename = sys.argv[1]
_, kwargs = parse_setup(filename)
requires = kwargs['install_requires']
print('\n'.join(requires))
Apparently #218 might solve your issue here. Well, at least to integrate safety with your setup.py. Now, to literally scan a setup.py file "from outside" as a static analyzer, then we might need dparse support and a better use of dparse by Safety.
It would be nice if it was possible to pass setup.py files to
safety check --file