def argument_preprocessor(args): """Run verb and plugin preprocessors on arguments. The preprocessors take in raw arguments and return potentially trimmed arguments and extra options to be added to the argparse NameSpace object. This can fail if the positional path argument does not contain a valid path or if the build type of the package at that path does not have a corresponding build type plugin. :param list args: list of arguments as str's :returns: tuple of left over arguments and dictionary of extra options :raises: SystemError if underlying assumptions are not met """ extras = {} # Extract make arguments args, make_flags = extract_argument_group(args, '--make-flags') # Detected build type if possible parser = argparse.ArgumentParser() add_path_argument(parser) opts, _ = parser.parse_known_args(args) try: path = validate_package_manifest_path(opts.path) except (MissingPluginError, ValueError) as exc: sys.exit("{0}".format(exc)) build_type = get_build_type(path) build_type_impl = get_class_for_build_type(build_type)() # Let detected build type plugin do argument preprocessing args, extras = build_type_impl.argument_preprocessor(args) args = combine_make_flags(make_flags, args, extras) return args, extras
def run(opts, context): # Load up build type plugin class build_type = get_build_type(opts.path) build_type_impl = get_class_for_build_type(build_type)() pkg_name = context.package_manifest.name if not opts.skip_build: ignore_file = os.path.join(context.build_space, 'AMENT_IGNORE') if not os.path.exists(ignore_file) and not context.dry_run: os.makedirs(context.build_space, exist_ok=True) with open(ignore_file, 'w'): pass # Run the build command print("+++ Building '{0}'".format(pkg_name)) on_build_ret = build_type_impl.on_build(context) handle_build_action(on_build_ret, context) expand_prefix_level_setup_files(context) if not opts.skip_install: # Run the install command print("+++ Installing '{0}'".format(pkg_name)) on_install_ret = build_type_impl.on_install(context) handle_build_action(on_install_ret, context) deploy_prefix_level_setup_files(context)
def prepare_arguments(parser, args): """ Add parameters to argparse for the build_pkg verb and its plugins. After adding the generic verb arguments, this function tries to determine the build type of the target package. This is done by gracefully trying to get the positional ``path`` argument from the arguments, falling back to the default ``os.curdir``. Then it searches for a package manifest in that path. If it finds the package manifest it then determines the build type of the package, e.g. ``ament_cmake``. It then tries to load a build type plugin for that build type. If the loading is successful it will allow the plugin to add additional arguments to the parser in a new :py:class:`argparse.ArgumentGroup` for that build type. :param parser: ArgumentParser object to which arguments are added :type parser: :py:class:`argparse.ArgumentParser` :param list args: list of arguments as str's :returns: modified version of the original parser given :rtype: :py:class:`argparse.ArgumentParser` """ # Add verb arguments add_path_argument(parser) add_arguments(parser) # Detected build type if possible try: # Remove -h and --help to prevent printing help messages filt_args = list(filter(lambda x: x not in ['-h', '--help'], args)) # Remove first position argument, because that will be the verb for i, arg in enumerate(filt_args): if not arg.startswith('-'): del filt_args[i] break # Parse the arguments to find the user's provided path (or the default) opts, _ = parser.parse_known_args(filt_args) # Check to ensure the path has a package validate_package_path(opts.path) # Get the build_type from the package manifest build_type = get_build_type(opts.path) # Find an entry point which supports this build type build_type_impl = get_class_for_build_type(build_type)() # Let the detected build type plugin add arguments group = parser.add_argument_group( '{0} (detected) options'.format(build_type_impl.build_type)) call_prepare_arguments( build_type_impl.prepare_arguments, group, args, ) # Catch value and system errors which will raise later # This is done to preserve -h and --help's ability to function except (MissingPluginError, ValueError) as exc: # If system exit AND -h or --help are used, show the error if '-h' in args or '--help' in args: print('Error: Could not detect package build type:', exc) return parser
def prepare_arguments(parser, args): """ Add parameters to argparse for the build_pkg verb and its plugins. After adding the generic verb arguments, this function tries to determine the build type of the target package. This is done by gracefully trying to get the positional ``path`` argument from the arguments, falling back to the default ``os.curdir``. Then it searches for a package manifest in that path. If it finds the package manifest it then determines the build type of the package, e.g. ``ament_cmake``. It then tries to load a build type plugin for that build type. If the loading is successful it will allow the plugin to add additional arguments to the parser in a new :py:class:`argparse.ArgumentGroup` for that build type. :param parser: ArgumentParser object to which arguments are added :type parser: :py:class:`argparse.ArgumentParser` :param list args: list of arguments as str's :returns: modified version of the original parser given :rtype: :py:class:`argparse.ArgumentParser` """ # Add verb arguments add_path_argument(parser) add_arguments(parser) # Detected build type if possible try: # Remove -h and --help to prevent printing help messages filt_args = list(filter(lambda x: x not in ['-h', '--help'], args)) # Remove first position argument, because that will be the verb for i, arg in enumerate(filt_args): if not arg.startswith('-'): del filt_args[i] break # Parse the arguments to find the user's provided path (or the default) opts, _ = parser.parse_known_args(filt_args) # Check to ensure the path has a package validate_package_path(opts.path) # Get the build_type from the package manifest build_type = get_build_type(opts.path) # Find an entry point which supports this build type build_type_impl = get_class_for_build_type(build_type)() # Let the detected build type plugin add arguments group = parser.add_argument_group('{0} (detected) options'.format( build_type_impl.build_type)) call_prepare_arguments( build_type_impl.prepare_arguments, group, args, ) # Catch value and system errors which will raise later # This is done to preserve -h and --help's ability to function except (MissingPluginError, ValueError) as exc: # If system exit AND -h or --help are used, show the error if '-h' in args or '--help' in args: print('Error: Could not detect package build type:', exc) return parser
def run(opts, context): # Load up build type plugin class build_type = get_build_type(opts.path) build_type_impl = get_class_for_build_type(build_type)() pkg_name = context.package_manifest.name # Run the uninstall command print("+++ Uninstalling '{0}'".format(pkg_name)) on_uninstall_ret = build_type_impl.on_uninstall(context) handle_build_action(on_uninstall_ret, context)
def main(opts): opts.build_tests = True context = build_pkg_get_context(opts) context.retest_until_pass = (opts.retest_until_pass > 0) rc = build_pkg_run(opts, context) if rc: return rc # Load up build type plugin class build_type = get_build_type(opts.path) build_type_impl = get_class_for_build_type(build_type)() # Run the test command pkg_name = context.package_manifest.name print("+++ Testing '{0}'".format(pkg_name)) context.test_iteration = 0 while True: try: on_test_ret = build_type_impl.on_test(context) except (AttributeError, NotImplementedError): print("on_test() is not implemented for build type '%s'" % build_type, file=sys.stderr) return try: handle_build_action(on_test_ret, context) except SystemExit as e: # check if tests should be rerun if opts.retest_until_pass > context.test_iteration: context.test_iteration += 1 print( "+++ Testing '%s' again (retry #%d of %d)" % (pkg_name, context.test_iteration, opts.retest_until_pass)) continue # Automated systems can use --ignore-return-codes to allow them to react to # a failure to *run* a test but not a failure generated by a test that ran as # intended. Otherwise, we'll combine the two cases to help users to notice # when anything went wrong during a test run. if opts.ignore_return_codes: return else: return e.code # check if tests should be rerun if opts.retest_until_fail > context.test_iteration: context.test_iteration += 1 print("+++ Testing '%s' again (retry #%d of %d)" % (pkg_name, context.test_iteration, opts.retest_until_fail)) continue break
def main(opts): opts.build_tests = True context = build_pkg_get_context(opts) context.retest_until_pass = (opts.retest_until_pass > 0) rc = build_pkg_run(opts, context) if rc: return rc # Load up build type plugin class build_type = get_build_type(opts.path) build_type_impl = get_class_for_build_type(build_type)() # Run the test command pkg_name = context.package_manifest.name print("+++ Testing '{0}'".format(pkg_name)) context.test_iteration = 0 while True: try: on_test_ret = build_type_impl.on_test(context) except (AttributeError, NotImplementedError): print("on_test() is not implemented for build type '%s'" % build_type, file=sys.stderr) return try: handle_build_action(on_test_ret, context) except SystemExit as e: # check if tests should be rerun if opts.retest_until_pass > context.test_iteration: context.test_iteration += 1 print("+++ Testing '%s' again (retry #%d of %d)" % (pkg_name, context.test_iteration, opts.retest_until_pass)) continue # Automated systems can use --ignore-return-codes to allow them to react to # a failure to *run* a test but not a failure generated by a test that ran as # intended. Otherwise, we'll combine the two cases to help users to notice # when anything went wrong during a test run. if opts.ignore_return_codes: return else: return e.code # check if tests should be rerun if opts.retest_until_fail > context.test_iteration: context.test_iteration += 1 print("+++ Testing '%s' again (retry #%d of %d)" % (pkg_name, context.test_iteration, opts.retest_until_fail)) continue break
def main(opts): opts.build_tests = True context = build_pkg_get_context(opts) context.retest_until_pass = (opts.retest_until_pass > 0) rc = build_pkg_run(opts, context) if rc: return rc # Load up build type plugin class build_type = get_build_type(opts.path) build_type_impl = get_class_for_build_type(build_type)() # Run the test command pkg_name = context.package_manifest.name print("+++ Testing '{0}'".format(pkg_name)) context.test_iteration = 0 while True: try: on_test_ret = build_type_impl.on_test(context) except (AttributeError, NotImplementedError): print("on_test() is not implemented for build type '%s'" % build_type, file=sys.stderr) return try: handle_build_action(on_test_ret, context) except SystemExit: # check if tests should be rerun if opts.retest_until_pass > context.test_iteration: context.test_iteration += 1 print( "+++ Testing '%s' again (retry #%d of %d)" % (pkg_name, context.test_iteration, opts.retest_until_pass)) continue # there is no way to distinguish why the test returned non zero # the test invocation itself could have failed: # return e.code # but it could have also run successful and only failed some tests: return # check if tests should be rerun if opts.retest_until_fail > context.test_iteration: context.test_iteration += 1 print("+++ Testing '%s' again (retry #%d of %d)" % (pkg_name, context.test_iteration, opts.retest_until_fail)) continue break
def create_context(opts): # Setup build_pkg common context context = Context() context.source_space = os.path.abspath(os.path.normpath(opts.path)) context.package_manifest = _get_cached_package_manifest(opts.path) pkg_name = context.package_manifest.name context.build_space = os.path.join(opts.build_space, pkg_name) context.install_space = opts.install_space context.install = True context.build_dependencies = opts.build_dependencies \ if 'build_dependencies' in opts else [] context.exec_dependency_paths_in_workspace = opts.exec_dependency_paths_in_workspace \ if 'exec_dependency_paths_in_workspace' in opts else [] context.symlink_install = opts.symlink_install context.make_flags = opts.make_flags context.dry_run = False context.build_tests = opts.build_tests context.python_interpreter = opts.python_interpreter print('') print("Process package '{0}' with context:".format(pkg_name)) print('-' * 80) keys = [ 'source_space', 'build_space', 'install_space', 'make_flags', 'build_tests', ] max_key_len = str(max(len(k) for k in keys)) for key in keys: value = context[key] if isinstance(value, list): value = ', '.join(value) if value else 'None' print(('{0:>' + max_key_len + '} => {1}').format(key, value)) print('-' * 80) # Load up build type plugin class build_type = get_build_type(opts.path) build_type_impl = get_class_for_build_type(build_type)() # Allow the build type plugin to process options into a context extender ce = build_type_impl.extend_context(opts) # Extend the context with the context extender ce.apply_to_context(context) return context
def run(opts, context): # Load up build type plugin class build_type = get_build_type(opts.path) build_type_impl = get_class_for_build_type(build_type)() pkg_name = context.package_manifest.name if not opts.skip_build: # Run the build command print("+++ Building '{0}'".format(pkg_name)) on_build_ret = build_type_impl.on_build(context) handle_build_action(on_build_ret, context) expand_prefix_level_setup_files(context) if not opts.skip_install: # Run the install command print("+++ Installing '{0}'".format(pkg_name)) on_install_ret = build_type_impl.on_install(context) handle_build_action(on_install_ret, context) deploy_prefix_level_setup_files(context)
def main(opts): opts.build_tests = True context = build_pkg_get_context(opts) rc = build_pkg_run(opts, context) if rc: return rc # Load up build type plugin class build_type = get_build_type(opts.path) build_type_impl = get_class_for_build_type(build_type)() # Run the test command pkg_name = context.package_manifest.name print("+++ Testing '{0}'".format(pkg_name)) try: on_test_ret = build_type_impl.on_test(context) except (AttributeError, NotImplementedError): print("on_test() is not implemented for build type '%s'" % build_type, file=sys.stderr) return try: handle_build_action(on_test_ret, context) except SystemExit: return 1