def _add_build_command_dependencies(variant_build_commands, build_commands, start_index=0): """ Create a dependency tree for a list of build commands. Each build_command will contain a `build_command_dependencies` key which contains a list of integers. Each integer in the list represents the index of the dependencies build_commands within the list. The start_index indicates the value that the dependency indices should start counting from. """ # Create a packages dictionary that uses all of a recipe's packages as key, with # the recipes index as values. packages = dict() index = 0 #save indices of build commands which are already present in build_commands duplicates = [] for var_index, build_command in enumerate(variant_build_commands): if build_command in build_commands: alt_index = build_commands.index(build_command) duplicates.append(var_index) for package in build_command.packages: packages.update({ package : [alt_index] + packages.get(package, []) }) else: for package in build_command.packages: packages.update({ package : [start_index + index] + packages.get(package, []) }) index +=1 # remove build commands that are already added to build_commands variant_build_commands = [i for j, i in enumerate(variant_build_commands) if j not in duplicates] # Add a list of indices for dependency to a BuildCommand's `build_command_dependencies` value # Note: This will filter out all dependencies that aren't in the recipes list. for index, build_command in enumerate(variant_build_commands): deps = [] dependencies = set() dependencies.update({utils.remove_version(dep) for dep in build_command.run_dependencies}) dependencies.update({utils.remove_version(dep) for dep in build_command.build_dependencies}) dependencies.update({utils.remove_version(dep) for dep in build_command.host_dependencies}) dependencies.update({utils.remove_version(dep) for dep in build_command.test_dependencies}) for dep in dependencies: if dep in packages: deps += filter(lambda x: x != start_index + index, packages[dep]) build_command.build_command_dependencies = deps return variant_build_commands
def validate_build_tree(build_commands, external_deps): ''' Check a build tree for dependency compatability. ''' packages = [ package for recipe in build_commands for package in recipe.packages ] channels = { channel for recipe in build_commands for channel in recipe.channels } deps = { dep for recipe in build_commands for dep in recipe.run_dependencies } deps.update(external_deps) pkg_args = " ".join([ "\"{}\"".format(utils.generalize_version(dep)) for dep in deps if not utils.remove_version(dep) in packages ]) channel_args = " ".join( {"-c \"{}\"".format(channel) for channel in channels}) cli = "conda create --dry-run -n test_conda_dependencies {} {}".format( channel_args, pkg_args) ret_code, std_out, std_err = utils.run_command_capture(cli) if not ret_code: raise OpenCEError(Error.VALIDATE_BUILD_TREE, cli, std_out, std_err)
def main(arg_strings=None): parser = make_parser() args = parser.parse_args(arg_strings) for variant in VARIANTS: for env_file in args.env_files: print(str(env_file) + " : " + str(variant)) retval,recipes = build_env.create_all_recipes([env_file], variant, repository_folder=args.repository_folder, conda_build_config=args.conda_build_config) packages = [package for recipe in recipes for package in recipe["packages"]] channels = {channel for recipe in recipes for channel in recipe["channels"]} deps = {dep for recipe in recipes for dep in recipe.get("run_dependencies")} cli = "conda create --dry-run -n test_conda_dependencies" cli += " " cli += " ".join({"-c \"" + channel + "\"" for channel in channels}) cli += " " cli += " ".join(["\"" + generalize_dependency_version(dep) + "\"" for dep in deps if not utils.remove_version(dep) in packages]) retval = run_and_log(cli) if retval != 0: print("An error was encountered!") return 1 print(args.conda_build_config + " Successfully validated!") return 0
def _create_dep_tree(recipes): """ Create a dependency tree for a list of recipes. Each recipe will contain a 'dependencies` key which contains a list of integers. Each integer in the list represents the index of the dependencies recipe within the recipe list. """ # Create a packages dictionary that uses all of a recipe's packages as key, with # the recipes index as values. packages = dict() for index, recipe in enumerate(recipes): for package in recipe.get('packages', []): packages.update({package: [index] + packages.get(package, [])}) # Create a new list of dictionary items that each contain: # A list of indices for each dependency. # A boolean indicating whether the recipe has been seen during a traversal # Note: This will filter out all dependencies that aren't in the recipes list. outputs = [] for index, recipe in enumerate(recipes): deps = [] dependencies = set() dependencies.update({ utils.remove_version(dep) for dep in recipe.get("run_dependencies") }) dependencies.update({ utils.remove_version(dep) for dep in recipe.get("build_dependencies") }) dependencies.update({ utils.remove_version(dep) for dep in recipe.get("host_dependencies") }) dependencies.update({ utils.remove_version(dep) for dep in recipe.get("test_dependencies") }) for dep in dependencies: if dep in packages: deps += filter(lambda x: x != index, packages[dep]) output = {'dep_indices': deps, 'seen': False} outputs.append(output) return outputs
def _add_build_command_dependencies(build_commands, start_index=0): """ Create a dependency tree for a list of build commands. Each build_command will contain a `build_command_dependencies` key which contains a list of integers. Each integer in the list represents the index of the dependencies build_commands within the list. The start_index indicates the value that the dependency indices should start counting from. """ # Create a packages dictionary that uses all of a recipe's packages as key, with # the recipes index as values. packages = dict() for index, build_command in enumerate(build_commands): for package in build_command.packages: packages.update( {package: [start_index + index] + packages.get(package, [])}) # Add a list of indices for dependency to a BuildCommand's `build_command_dependencies` value # Note: This will filter out all dependencies that aren't in the recipes list. for index, build_command in enumerate(build_commands): deps = [] dependencies = set() dependencies.update({ utils.remove_version(dep) for dep in build_command.run_dependencies }) dependencies.update({ utils.remove_version(dep) for dep in build_command.build_dependencies }) dependencies.update({ utils.remove_version(dep) for dep in build_command.host_dependencies }) dependencies.update({ utils.remove_version(dep) for dep in build_command.test_dependencies }) for dep in dependencies: if dep in packages: deps += filter(lambda x: x != start_index + index, packages[dep]) build_command.build_command_dependencies = deps
def validate_config(arg_strings=None): ''' Entry function. ''' args = make_parser().parse_args(arg_strings) variants = utils.make_variants(args.python_versions, args.build_types, args.mpi_types) for variant in variants: print('Validating {} for {}'.format(args.conda_build_config, variant)) for env_file in args.env_config_file: print('Validating {} for {} : {}'.format(args.conda_build_config, env_file, variant)) try: recipes = build_tree.BuildTree([env_file], variant['python'], variant['build_type'], variant['mpi_type'], repository_folder=args.repository_folder, conda_build_config=args.conda_build_config) except OpenCEError as err: print(err.msg) print('Error while validating {} for {} : {}'.format(args.conda_build_config, env_file, variant)) return 1 packages = [package for recipe in recipes for package in recipe.packages] channels = {channel for recipe in recipes for channel in recipe.channels} deps = {dep for recipe in recipes for dep in recipe.run_dependencies} deps.update(recipes.get_external_dependencies(variant)) pkg_args = " ".join(["\"{}\"".format(generalize_version(dep)) for dep in deps if not utils.remove_version(dep) in packages]) channel_args = " ".join({"-c \"{}\"".format(channel) for channel in channels}) cli = "conda create --dry-run -n test_conda_dependencies {} {}".format(channel_args, pkg_args) retval = utils.run_and_log(cli) if retval != 0: print('Error while validating {} for {} : {}'.format(args.conda_build_config, env_file, variant)) return 1 print('Successfully validated {} for {} : {}'.format(args.conda_build_config, env_file, variant)) print('Successfully validated {} for {}'.format(args.conda_build_config, variant)) print("{} Successfully validated!".format(args.conda_build_config)) return 0