diff options
Diffstat (limited to 'build/print_python_deps.py')
-rwxr-xr-x | build/print_python_deps.py | 113 |
1 files changed, 113 insertions, 0 deletions
diff --git a/build/print_python_deps.py b/build/print_python_deps.py new file mode 100755 index 0000000000..2459a28e6b --- /dev/null +++ b/build/print_python_deps.py @@ -0,0 +1,113 @@ +#!/usr/bin/env vpython +# Copyright 2016 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +"""Prints all non-system dependencies for the given module. + +The primary use-case for this script is to genererate the list of python modules +required for .isolate files. +""" + +import argparse +import imp +import os +import pipes +import sys + +# Don't use any helper modules, or else they will end up in the results. + + +_SRC_ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), os.pardir)) + + +def _ComputePythonDependencies(): + """Gets the paths of imported non-system python modules. + + A path is assumed to be a "system" import if it is outside of chromium's + src/. The paths will be relative to the current directory. + """ + module_paths = (m.__file__ for m in sys.modules.values() + if m and hasattr(m, '__file__')) + + src_paths = set() + for path in module_paths: + if path == __file__: + continue + path = os.path.abspath(path) + if not path.startswith(_SRC_ROOT): + continue + + if (path.endswith('.pyc') + or (path.endswith('c') and not os.path.splitext(path)[1])): + path = path[:-1] + src_paths.add(path) + + return src_paths + + +def _NormalizeCommandLine(options): + """Returns a string that when run from SRC_ROOT replicates the command.""" + args = ['build/print_python_deps.py'] + root = os.path.relpath(options.root, _SRC_ROOT) + if root != '.': + args.extend(('--root', root)) + if options.output: + args.extend(('--output', os.path.relpath(options.output, _SRC_ROOT))) + for whitelist in sorted(options.whitelists): + args.extend(('--whitelist', os.path.relpath(whitelist, _SRC_ROOT))) + args.append(os.path.relpath(options.module, _SRC_ROOT)) + return ' '.join(pipes.quote(x) for x in args) + + +def _FindPythonInDirectory(directory): + """Returns an iterable of all non-test python files in the given directory.""" + files = [] + for root, _dirnames, filenames in os.walk(directory): + for filename in filenames: + if filename.endswith('.py') and not filename.endswith('_test.py'): + yield os.path.join(root, filename) + + +def main(): + parser = argparse.ArgumentParser( + description='Prints all non-system dependencies for the given module.') + parser.add_argument('module', + help='The python module to analyze.') + parser.add_argument('--root', default='.', + help='Directory to make paths relative to.') + parser.add_argument('--output', + help='Write output to a file rather than stdout.') + parser.add_argument('--no-header', action='store_true', + help='Do not write the "# Generated by" header.') + parser.add_argument('--gn-paths', action='store_true', + help='Write paths as //foo/bar/baz.py') + parser.add_argument('--whitelist', default=[], action='append', + dest='whitelists', + help='Recursively include all non-test python files ' + 'within this directory. May be specified multiple times.') + options = parser.parse_args() + # Replace the path entry for print_python_deps.py with the one for the given + # module. + sys.path[0] = os.path.dirname(options.module) + imp.load_source('NAME', options.module) + + paths_set = _ComputePythonDependencies() + for path in options.whitelists: + paths_set.update(os.path.abspath(p) for p in _FindPythonInDirectory(path)) + + paths = [os.path.relpath(p, options.root) for p in paths_set] + + normalized_cmdline = _NormalizeCommandLine(options) + out = open(options.output, 'w') if options.output else sys.stdout + with out: + if not options.no_header: + out.write('# Generated by running:\n') + out.write('# %s\n' % normalized_cmdline) + prefix = '//' if options.gn_paths else '' + for path in sorted(paths): + out.write(prefix + path + '\n') + + +if __name__ == '__main__': + sys.exit(main()) |