def main(argv): parser = argparse.ArgumentParser('Generate a file from a Python script', add_help=False) parser.add_argument('--locale', metavar='locale', type=str, help='The locale in use.') parser.add_argument('python_script', metavar='python-script', type=str, help='The Python script to run') parser.add_argument('method_name', metavar='method-name', type=str, help='The method of the script to invoke') parser.add_argument('output_file', metavar='output-file', type=str, help='The file to generate') parser.add_argument('dep_file', metavar='dep-file', type=str, help='File to write any additional make dependencies to') parser.add_argument('dep_target', metavar='dep-target', type=str, help='Make target to use in the dependencies file') parser.add_argument('additional_arguments', metavar='arg', nargs=argparse.REMAINDER, help="Additional arguments to the script's main() method") args = parser.parse_args(argv) kwargs = {} if args.locale: kwargs['locale'] = args.locale script = args.python_script # Permit the script to import modules from the same directory in which it # resides. The justification for doing this is that if we were invoking # the script as: # # python script arg1... # # then importing modules from the script's directory would come for free. # Since we're invoking the script in a roundabout way, we provide this # bit of convenience. sys.path.append(os.path.dirname(script)) with open(script, 'r') as fh: module = imp.load_module('script', fh, script, ('.py', 'r', imp.PY_SOURCE)) method = args.method_name if not hasattr(module, method): print('Error: script "{0}" is missing a {1} method'.format(script, method), file=sys.stderr) return 1 ret = 1 try: with FileAvoidWrite(args.output_file, mode='rb') as output: try: ret = module.__dict__[method](output, *args.additional_arguments, **kwargs) except Exception: # Ensure that we don't overwrite the file if the script failed. output.avoid_writing_to_file() raise # The following values indicate a statement of success: # - a set() (see below) # - 0 # - False # - None # # Everything else is an error (so scripts can conveniently |return # 1| or similar). If a set is returned, the elements of the set # indicate additional dependencies that will be listed in the deps # file. Python module imports are automatically included as # dependencies. if isinstance(ret, set): deps = ret # The script succeeded, so reset |ret| to indicate that. ret = None else: deps = set() # Only write out the dependencies if the script was successful if not ret: # Add dependencies on any python modules that were imported by # the script. deps |= set(iter_modules_in_path(buildconfig.topsrcdir, buildconfig.topobjdir)) # Add dependencies on any buildconfig items that were accessed # by the script. deps |= set(buildconfig.get_dependencies()) mk = Makefile() mk.create_rule([args.dep_target]).add_dependencies(deps) with FileAvoidWrite(args.dep_file) as dep_file: mk.dump(dep_file) else: # Ensure that we don't overwrite the file if the script failed. output.avoid_writing_to_file() except IOError as e: print('Error opening file "{0}"'.format(e.filename), file=sys.stderr) traceback.print_exc() return 1 return ret
def main(argv): parser = argparse.ArgumentParser('Generate a file from a Python script', add_help=False) parser.add_argument('--locale', metavar='locale', type=str, help='The locale in use.') parser.add_argument('python_script', metavar='python-script', type=str, help='The Python script to run') parser.add_argument('method_name', metavar='method-name', type=str, help='The method of the script to invoke') parser.add_argument('output_file', metavar='output-file', type=str, help='The file to generate') parser.add_argument('dep_file', metavar='dep-file', type=str, help='File to write any additional make dependencies to') parser.add_argument('additional_arguments', metavar='arg', nargs=argparse.REMAINDER, help="Additional arguments to the script's main() method") args = parser.parse_args(argv) kwargs = {} if args.locale: kwargs['locale'] = args.locale script = args.python_script # Permit the script to import modules from the same directory in which it # resides. The justification for doing this is that if we were invoking # the script as: # # python script arg1... # # then importing modules from the script's directory would come for free. # Since we're invoking the script in a roundabout way, we provide this # bit of convenience. sys.path.append(os.path.dirname(script)) with open(script, 'r') as fh: module = imp.load_module('script', fh, script, ('.py', 'r', imp.PY_SOURCE)) method = args.method_name if not hasattr(module, method): print('Error: script "{0}" is missing a {1} method'.format(script, method), file=sys.stderr) return 1 ret = 1 try: with FileAvoidWrite(args.output_file, mode='rb') as output: ret = module.__dict__[method](output, *args.additional_arguments, **kwargs) # The following values indicate a statement of success: # - a set() (see below) # - 0 # - False # - None # # Everything else is an error (so scripts can conveniently |return # 1| or similar). If a set is returned, the elements of the set # indicate additional dependencies that will be listed in the deps # file. Python module imports are automatically included as # dependencies. if isinstance(ret, set): deps = ret # The script succeeded, so reset |ret| to indicate that. ret = None else: deps = set() # Only write out the dependencies if the script was successful if not ret: # Add dependencies on any python modules that were imported by # the script. deps |= set(iter_modules_in_path(buildconfig.topsrcdir, buildconfig.topobjdir)) # Add dependencies on any buildconfig items that were accessed # by the script. deps |= set(buildconfig.get_dependencies()) mk = Makefile() mk.create_rule([args.output_file]).add_dependencies(deps) with FileAvoidWrite(args.dep_file) as dep_file: mk.dump(dep_file) # Even when our file's contents haven't changed, we want to update # the file's mtime so make knows this target isn't still older than # whatever prerequisite caused it to be built this time around. try: os.utime(args.output_file, None) except: print('Error processing file "{0}"'.format(args.output_file), file=sys.stderr) traceback.print_exc() except IOError as e: print('Error opening file "{0}"'.format(e.filename), file=sys.stderr) traceback.print_exc() return 1 return ret