def test(recipedir_or_package_or_metadata, move_broken=True, config=None, **kwargs): import os from conda_build.build import test from conda_build.render import render_recipe config = get_or_merge_config(config, **kwargs) if hasattr(recipedir_or_package_or_metadata, 'config'): metadata = recipedir_or_package_or_metadata recipe_config = metadata.config elif os.path.isdir(recipedir_or_package_or_metadata): # This will create a new local build folder if and only if config doesn't already have one. # What this means is that if we're running a test immediately after build, we use the one # that the build already provided config.compute_build_id(recipedir_or_package_or_metadata) metadata, _, _ = render_recipe(recipedir_or_package_or_metadata, config=config) recipe_config = config else: # fall back to old way (use recipe, rather than package) metadata, _, _ = render_recipe(recipedir_or_package_or_metadata, no_download_source=False, config=config, **kwargs) recipe_config = config with recipe_config: # This will create a new local build folder if and only if config doesn't already have one. # What this means is that if we're running a test immediately after build, we use the one # that the build already provided config.compute_build_id(metadata.name()) test_result = test(metadata, config=recipe_config, move_broken=move_broken) return test_result
def render(recipe_path, config=None, variants=None, permit_unsatisfiable_variants=True, finalize=True, **kwargs): """Given path to a recipe, return the MetaData object(s) representing that recipe, with jinja2 templates evaluated. Returns a list of (metadata, needs_download, needs_reparse in env) tuples""" from conda_build.render import render_recipe, finalize_metadata from conda_build.exceptions import DependencyNeedsBuildingError from conda_build.conda_interface import NoPackagesFoundError from collections import OrderedDict config = get_or_merge_config(config, **kwargs) metadata_tuples = render_recipe(recipe_path, no_download_source=config.no_download_source, config=config, variants=variants, permit_unsatisfiable_variants=permit_unsatisfiable_variants) output_metas = OrderedDict() for meta, download, render_in_env in metadata_tuples: for od, om in meta.get_output_metadata_set( permit_unsatisfiable_variants=permit_unsatisfiable_variants): # only show conda packages right now if 'type' not in od or od['type'] == 'conda': assert hasattr(om.config, 'variants') if finalize and not om.final: try: om = finalize_metadata(om, permit_unsatisfiable_variants=permit_unsatisfiable_variants) except (DependencyNeedsBuildingError, NoPackagesFoundError): if not permit_unsatisfiable_variants: raise output_metas[om.dist()] = ((om, download, render_in_env)) return list(output_metas.values())
def main(): p = get_render_parser() p.add_argument( '-f', '--file', action="store", help="write YAML to file, given as argument here.\ Overwrites existing files." ) # we do this one separately because we only allow one entry to conda render p.add_argument( 'recipe', action="store", metavar='RECIPE_PATH', choices=RecipeCompleter(), help="Path to recipe directory.", ) args = p.parse_args() set_language_env_vars(args, p) metadata = render_recipe(find_recipe(args.recipe), no_download_source=args.no_source) if args.output: print(bldpkg_path(metadata)) else: output = yaml.dump(MetaYaml(metadata.meta), Dumper=IndentDumper, default_flow_style=False, indent=4) if args.file: with open(args.file, "w") as f: f.write(output) else: print(output)
def check(recipe_path, no_download_source=False, config=None, **kwargs): from conda_build.render import render_recipe config = get_or_merge_config(config, **kwargs) metadata, _, _ = render_recipe(recipe_path, no_download_source=no_download_source, config=config) return metadata.check_fields()
def render(recipe_path, config=None, variants=None, permit_unsatisfiable_variants=True, **kwargs): """Given path to a recipe, return the MetaData object(s) representing that recipe, with jinja2 templates evaluated. Returns a list of (metadata, needs_download, needs_reparse in env) tuples""" from conda_build.render import render_recipe from collections import OrderedDict config = get_or_merge_config(config, **kwargs) metadata_tuples, index = render_recipe( recipe_path, no_download_source=config.no_download_source, config=config, variants=variants, permit_unsatisfiable_variants=permit_unsatisfiable_variants) output_metas = OrderedDict() for meta, download, render_in_env in metadata_tuples: for od, om in meta.get_output_metadata_set( permit_unsatisfiable_variants=permit_unsatisfiable_variants): # only show conda packages right now if 'type' not in od or od['type'] == 'conda': output_metas[om.dist()] = ((om, download, render_in_env)) return list(output_metas.values())
def render(recipe_path, config=None, variants=None, permit_unsatisfiable_variants=True, **kwargs): """Given path to a recipe, return the MetaData object(s) representing that recipe, with jinja2 templates evaluated. Returns a list of (metadata, needs_download, needs_reparse in env) tuples""" from conda_build.render import render_recipe, finalize_metadata from conda_build.exceptions import DependencyNeedsBuildingError config = get_or_merge_config(config, **kwargs) metadata_tuples, index = render_recipe( recipe_path, no_download_source=config.no_download_source, config=config, variants=variants, permit_unsatisfiable_variants=permit_unsatisfiable_variants) metadata = [] for (_m, download, reparse) in metadata_tuples: for (output_dict, m) in _m.get_output_metadata_set(): if output_dict.get('type') != 'wheel': try: m = finalize_metadata(m, index) except DependencyNeedsBuildingError: log = _get_logger(__name__) log.warn( "Could not finalize metadata due to missing dependencies. " "If building, these should get built in order and it's OK to " "ignore this message..") metadata.append((m, download, reparse)) return metadata
def main(): p = get_render_parser() p.add_argument( '-f', '--file', action="store", help="write YAML to file, given as argument here.\ Overwrites existing files." ) # we do this one separately because we only allow one entry to conda render p.add_argument( 'recipe', action="store", metavar='RECIPE_PATH', choices=RecipeCompleter(), help="Path to recipe directory.", ) # this is here because we have a different default than build p.add_argument( '--verbose', action='store_true', help='Enable verbose output from download tools and progress updates', ) args = p.parse_args() set_language_env_vars(args, p) metadata, _, _ = render_recipe(find_recipe(args.recipe), no_download_source=args.no_source, verbose=args.verbose) if args.output: print(bldpkg_path(metadata)) else: print(output_yaml(metadata, args.file))
def render(recipe_path, config=None, variants=None, permit_unsatisfiable_variants=True, finalize=True, bypass_env_check=False, **kwargs): """Given path to a recipe, return the MetaData object(s) representing that recipe, with jinja2 templates evaluated. Returns a list of (metadata, needs_download, needs_reparse in env) tuples""" from conda_build.render import render_recipe, finalize_metadata from conda_build.exceptions import DependencyNeedsBuildingError from conda_build.conda_interface import NoPackagesFoundError from collections import OrderedDict config = get_or_merge_config(config, **kwargs) metadata_tuples = render_recipe( recipe_path, bypass_env_check=bypass_env_check, no_download_source=config.no_download_source, config=config, variants=variants, permit_unsatisfiable_variants=permit_unsatisfiable_variants) output_metas = OrderedDict() for meta, download, render_in_env in metadata_tuples: if not meta.skip() or not config.trim_skip: for od, om in meta.get_output_metadata_set( permit_unsatisfiable_variants=permit_unsatisfiable_variants, permit_undefined_jinja=not finalize, bypass_env_check=bypass_env_check): if not om.skip() or not config.trim_skip: if 'type' not in od or od['type'] == 'conda': if finalize and not om.final: try: om = finalize_metadata( om, permit_unsatisfiable_variants= permit_unsatisfiable_variants) except (DependencyNeedsBuildingError, NoPackagesFoundError): if not permit_unsatisfiable_variants: raise # remove outputs section from output objects for simplicity if not om.path and om.meta.get('outputs'): om.parent_outputs = om.meta['outputs'] del om.meta['outputs'] output_metas[om.dist(), om.config.variant.get('target_platform'), tuple((var, om.config.variant[var]) for var in om.get_used_vars())] = \ ((om, download, render_in_env)) else: output_metas["{}: {}".format(om.type, om.name()), om.config.variant.get('target_platform'), tuple((var, om.config.variant[var]) for var in om.get_used_vars())] = \ ((om, download, render_in_env)) return list(output_metas.values())
def test(recipedir_or_package_or_metadata, move_broken=True, config=None, **kwargs): import os from conda_build.conda_interface import url_path from conda_build.build import test from conda_build.render import render_recipe from conda_build.utils import get_recipe_abspath, rm_rf from conda_build import source config = get_or_merge_config(config, **kwargs) # we want to know if we're dealing with package input. If so, we can move the input on success. is_package = False if hasattr(recipedir_or_package_or_metadata, 'config'): metadata = recipedir_or_package_or_metadata recipe_config = metadata.config else: recipe_dir, need_cleanup = get_recipe_abspath(recipedir_or_package_or_metadata) config.need_cleanup = need_cleanup # This will create a new local build folder if and only if config doesn't already have one. # What this means is that if we're running a test immediately after build, we use the one # that the build already provided metadata, _, _ = render_recipe(recipe_dir, config=config) recipe_config = config # this recipe came from an extracted tarball. if need_cleanup: # ensure that the local location of the package is indexed, so that conda can find the # local package local_location = os.path.dirname(recipedir_or_package_or_metadata) # strip off extra subdir folders for platform in ('win', 'linux', 'osx'): if os.path.basename(local_location).startswith(platform + "-"): local_location = os.path.dirname(local_location) update_index(local_location, config=config) local_url = url_path(local_location) # channel_urls is an iterable, but we don't know if it's a tuple or list. Don't know # how to add elements. recipe_config.channel_urls = list(recipe_config.channel_urls) recipe_config.channel_urls.insert(0, local_url) is_package = True if metadata.meta.get('test') and metadata.meta['test'].get('source_files'): source.provide(metadata.path, metadata.get_section('source'), config=config) rm_rf(recipe_dir) with recipe_config: # This will create a new local build folder if and only if config doesn't already have one. # What this means is that if we're running a test immediately after build, we use the one # that the build already provided recipe_config.compute_build_id(metadata.name()) test_result = test(metadata, config=recipe_config, move_broken=move_broken) if (test_result and is_package and hasattr(recipe_config, 'output_folder') and recipe_config.output_folder): os.rename(recipedir_or_package_or_metadata, os.path.join(recipe_config.output_folder, os.path.basename(recipedir_or_package_or_metadata))) return test_result
def get_output_file_path(recipe_path_or_metadata, no_download_source=False, config=None, **kwargs): from conda_build.render import render_recipe, bldpkg_path config = get_or_merge_config(config, **kwargs) if hasattr(recipe_path_or_metadata, 'config'): metadata = recipe_path_or_metadata else: metadata, _, _ = render_recipe(recipe_path_or_metadata, no_download_source=no_download_source, config=config) return bldpkg_path(metadata)
def execute(args): p, args = parse_args(args) config = Config() set_language_env_vars(args, p, config) with LoggingContext(logging.CRITICAL + 1): metadata, _, _ = render_recipe(args.recipe, no_download_source=args.no_source, config=config) if args.output: print(bldpkg_path(metadata)) else: print(output_yaml(metadata, args.file))
def execute(args): p, args = parse_args(args) config = Config() set_language_env_vars(args, p, config) metadata, _, _ = render_recipe(args.recipe, no_download_source=args.no_source, config=config) if args.output: logging.basicConfig(level=logging.ERROR) silence_loggers(show_warnings_and_errors=False) print(bldpkg_path(metadata)) else: logging.basicConfig(level=logging.INFO) print(output_yaml(metadata, args.file))
def render(recipe_path, config=None, variants=None, permit_unsatisfiable_variants=True, finalize=True, bypass_env_check=False, **kwargs): """Given path to a recipe, return the MetaData object(s) representing that recipe, with jinja2 templates evaluated. Returns a list of (metadata, needs_download, needs_reparse in env) tuples""" from conda_build.render import render_recipe, finalize_metadata from conda_build.exceptions import DependencyNeedsBuildingError from conda_build.conda_interface import NoPackagesFoundError from collections import OrderedDict config = get_or_merge_config(config, **kwargs) metadata_tuples = render_recipe(recipe_path, bypass_env_check=bypass_env_check, no_download_source=config.no_download_source, config=config, variants=variants, permit_unsatisfiable_variants=permit_unsatisfiable_variants) output_metas = OrderedDict() for meta, download, render_in_env in metadata_tuples: if not meta.skip() or not config.trim_skip: for od, om in meta.get_output_metadata_set( permit_unsatisfiable_variants=permit_unsatisfiable_variants, permit_undefined_jinja=not finalize, bypass_env_check=bypass_env_check): if not om.skip() or not config.trim_skip: if 'type' not in od or od['type'] == 'conda': if finalize and not om.final: try: om = finalize_metadata(om, permit_unsatisfiable_variants=permit_unsatisfiable_variants) except (DependencyNeedsBuildingError, NoPackagesFoundError): if not permit_unsatisfiable_variants: raise # remove outputs section from output objects for simplicity if not om.path and om.meta.get('outputs'): om.parent_outputs = om.meta['outputs'] del om.meta['outputs'] output_metas[om.dist(), om.config.variant.get('target_platform'), tuple((var, om.config.variant[var]) for var in om.get_used_vars())] = \ ((om, download, render_in_env)) else: output_metas["{}: {}".format(om.type, om.name()), om.config.variant.get('target_platform'), tuple((var, om.config.variant[var]) for var in om.get_used_vars())] = \ ((om, download, render_in_env)) return list(output_metas.values())
def execute(args): p, args = parse_args(args) config = Config() set_language_env_vars(args, p, config) metadata, _, _ = render_recipe(args.recipe, no_download_source=args.no_source, config=config) if args.output: logging.basicConfig(level=logging.ERROR) silence_loggers(show_warnings_and_errors=False) print(bldpkg_path(metadata, config=config)) else: logging.basicConfig(level=logging.INFO) print(output_yaml(metadata, args.file))
def render(recipe_path, config=None, variants=None, permit_unsatisfiable_variants=True, **kwargs): """Given path to a recipe, return the MetaData object(s) representing that recipe, with jinja2 templates evaluated. Returns a list of (metadata, needs_download, needs_reparse in env) tuples""" from conda_build.render import render_recipe from collections import OrderedDict config = get_or_merge_config(config, **kwargs) metadata_tuples, index = render_recipe(recipe_path, no_download_source=config.no_download_source, config=config, variants=variants, permit_unsatisfiable_variants=permit_unsatisfiable_variants) output_metas = OrderedDict() for meta, download, render_in_env in metadata_tuples: for od, om in meta.get_output_metadata_set( permit_unsatisfiable_variants=permit_unsatisfiable_variants): # only show conda packages right now if 'type' not in od or od['type'] == 'conda': output_metas[om.dist()] = ((om, download, render_in_env)) return list(output_metas.values())
def build_tree(recipe_list, config, build_only=False, post=False, notest=False, need_source_download=True, need_reparse_in_env=False): to_build_recursive = [] recipe_list = deque(recipe_list) already_built = set() while recipe_list: # This loop recursively builds dependencies if recipes exist if build_only: post = False notest = True config.anaconda_upload = False elif post: post = True notest = True config.anaconda_upload = False else: post = None recipe = recipe_list.popleft() if hasattr(recipe, 'config'): metadata = recipe recipe_config = metadata.config # this code is duplicated below because we need to be sure that the build id is set # before downloading happens - or else we lose where downloads are if recipe_config.set_build_id: recipe_config.compute_build_id(metadata.name(), reset=True) recipe_parent_dir = "" to_build_recursive.append(metadata.name()) else: recipe_parent_dir = os.path.dirname(recipe) recipe = recipe.rstrip("/").rstrip("\\") recipe_config = config to_build_recursive.append(os.path.basename(recipe)) # before downloading happens - or else we lose where downloads are if recipe_config.set_build_id: recipe_config.compute_build_id(os.path.basename(recipe), reset=True) metadata, need_source_download, need_reparse_in_env = render_recipe(recipe, config=recipe_config) try: with recipe_config: ok_to_test = build(metadata, post=post, need_source_download=need_source_download, need_reparse_in_env=need_reparse_in_env, config=recipe_config) if not notest and ok_to_test: test(metadata, config=recipe_config) except (NoPackagesFound, Unsatisfiable) as e: error_str = str(e) # Typically if a conflict is with one of these # packages, the other package needs to be rebuilt # (e.g., a conflict with 'python 3.5*' and 'x' means # 'x' isn't build for Python 3.5 and needs to be # rebuilt). skip_names = ['python', 'r'] add_recipes = [] # add the failed one back in at the beginning - but its deps may come before it recipe_list.extendleft([recipe]) for line in error_str.splitlines(): if not line.startswith(' - '): continue pkg = line.lstrip(' - ').split(' -> ')[-1] pkg = pkg.strip().split(' ')[0] if pkg in skip_names: continue if pkg in to_build_recursive: raise RuntimeError("Can't build {0} due to unsatisfiable dependencies:\n" .format(recipe) + error_str) recipe_glob = glob(os.path.join(recipe_parent_dir, pkg)) if recipe_glob: for recipe_dir in recipe_glob: print(error_str) print(("Missing dependency {0}, but found" + " recipe directory, so building " + "{0} first").format(pkg)) add_recipes.append(recipe_dir) else: raise RuntimeError("Can't build {0} due to unsatisfiable dependencies:\n" .format(recipe) + error_str) recipe_list.extendleft(add_recipes) # outputs message, or does upload, depending on value of args.anaconda_upload if post in [True, None]: output_file = bldpkg_path(metadata, config=recipe_config) handle_anaconda_upload(output_file, config=recipe_config) already_built.add(output_file)
def build_tree(recipe_list, config, build_only=False, post=False, notest=False, need_source_download=True, need_reparse_in_env=False): to_build_recursive = [] recipe_list = deque(recipe_list) already_built = set() while recipe_list: # This loop recursively builds dependencies if recipes exist if build_only: post = False notest = True config.anaconda_upload = False elif post: post = True notest = True config.anaconda_upload = False else: post = None recipe = recipe_list.popleft() if hasattr(recipe, 'config'): metadata = recipe recipe_config = metadata.config # this code is duplicated below because we need to be sure that the build id is set # before downloading happens - or else we lose where downloads are if recipe_config.set_build_id: recipe_config.compute_build_id(metadata.name(), reset=True) recipe_parent_dir = "" to_build_recursive.append(metadata.name()) else: recipe_parent_dir = os.path.dirname(recipe) recipe = recipe.rstrip("/").rstrip("\\") recipe_config = config to_build_recursive.append(os.path.basename(recipe)) # before downloading happens - or else we lose where downloads are if recipe_config.set_build_id: recipe_config.compute_build_id(os.path.basename(recipe), reset=True) metadata, need_source_download, need_reparse_in_env = render_recipe( recipe, config=recipe_config) try: with recipe_config: ok_to_test = build(metadata, post=post, need_source_download=need_source_download, need_reparse_in_env=need_reparse_in_env, config=recipe_config) if not notest and ok_to_test: test(metadata, config=recipe_config) except (NoPackagesFound, Unsatisfiable) as e: error_str = str(e) # Typically if a conflict is with one of these # packages, the other package needs to be rebuilt # (e.g., a conflict with 'python 3.5*' and 'x' means # 'x' isn't build for Python 3.5 and needs to be # rebuilt). skip_names = ['python', 'r'] add_recipes = [] # add the failed one back in at the beginning - but its deps may come before it recipe_list.extendleft([recipe]) for line in error_str.splitlines(): if not line.startswith(' - '): continue pkg = line.lstrip(' - ').split(' -> ')[-1] pkg = pkg.strip().split(' ')[0] if pkg in skip_names: continue if pkg in to_build_recursive: raise RuntimeError( "Can't build {0} due to unsatisfiable dependencies:\n". format(recipe) + error_str) recipe_glob = glob(os.path.join(recipe_parent_dir, pkg)) if recipe_glob: for recipe_dir in recipe_glob: print(error_str) print(("Missing dependency {0}, but found" + " recipe directory, so building " + "{0} first").format(pkg)) add_recipes.append(recipe_dir) else: raise RuntimeError( "Can't build {0} due to unsatisfiable dependencies:\n". format(recipe) + error_str) recipe_list.extendleft(add_recipes) # outputs message, or does upload, depending on value of args.anaconda_upload if post in [True, None]: output_file = bldpkg_path(metadata, config=recipe_config) handle_anaconda_upload(output_file, config=recipe_config) already_built.add(output_file)
def render(recipe_path, config=None, **kwargs): from conda_build.render import render_recipe config = get_or_merge_config(config, **kwargs) return render_recipe(recipe_path, no_download_source=config.no_download_source, config=config)
def build_tree(recipe_list, config, build_only=False, post=False, notest=False, need_source_download=True, need_reparse_in_env=False): to_build_recursive = [] recipe_list = deque(recipe_list) if on_win: trash_dir = os.path.join(os.path.dirname(sys.executable), 'pkgs', '.trash') if os.path.isdir(trash_dir): # We don't really care if this does a complete job. # Cleaning up some files is better than none. subprocess.call('del /s /q "{0}\\*.*" >nul 2>&1'.format(trash_dir), shell=True) # delete_trash(None) already_built = set() extra_help = "" while recipe_list: # This loop recursively builds dependencies if recipes exist if build_only: post = False notest = True config.anaconda_upload = False elif post: post = True notest = True config.anaconda_upload = False else: post = None recipe = recipe_list.popleft() if hasattr(recipe, 'config'): metadata = recipe recipe_config = metadata.config # this code is duplicated below because we need to be sure that the build id is set # before downloading happens - or else we lose where downloads are if recipe_config.set_build_id: recipe_config.compute_build_id(metadata.name(), reset=True) recipe_parent_dir = "" to_build_recursive.append(metadata.name()) else: recipe_parent_dir = os.path.dirname(recipe) recipe = recipe.rstrip("/").rstrip("\\") recipe_config = config to_build_recursive.append(os.path.basename(recipe)) # before downloading happens - or else we lose where downloads are if recipe_config.set_build_id: recipe_config.compute_build_id(os.path.basename(recipe), reset=True) metadata, need_source_download, need_reparse_in_env = render_recipe(recipe, config=recipe_config) if not getattr(config, "noverify", False): verifier = Verify() ignore_scripts = context.ignore_recipe_verify_scripts if \ context.ignore_recipe_verify_scripts else None run_scripts = context.run_recipe_verify_scripts if \ context.run_recipe_verify_scripts else None verifier.verify_recipe(ignore_scripts=ignore_scripts, run_scripts=run_scripts, rendered_meta=metadata.meta, recipe_dir=metadata.path) try: with recipe_config: ok_to_test = build(metadata, post=post, need_source_download=need_source_download, need_reparse_in_env=need_reparse_in_env, config=recipe_config) if not notest and ok_to_test: test(metadata, config=recipe_config) except (NoPackagesFound, NoPackagesFoundError, Unsatisfiable, CondaValueError) as e: error_str = str(e) skip_names = ['python', 'r'] add_recipes = [] # add the failed one back in at the beginning - but its deps may come before it recipe_list.extendleft([recipe]) for line in error_str.splitlines(): if not line.startswith(' - '): continue pkg = line.lstrip(' - ').split(' -> ')[-1] pkg = pkg.strip().split(' ')[0] if pkg in to_build_recursive: raise RuntimeError("Can't build {0} due to unsatisfiable dependencies:\n" .format(recipe) + error_str + "\n" + extra_help) if pkg in skip_names: to_build_recursive.append(pkg) extra_help = """Typically if a conflict is with the Python or R packages, the other package needs to be rebuilt (e.g., a conflict with 'python 3.5*' and 'x' means 'x' isn't build for Python 3.5 and needs to be rebuilt.""" recipe_glob = glob(os.path.join(recipe_parent_dir, pkg)) if recipe_glob: for recipe_dir in recipe_glob: print(error_str) print(("Missing dependency {0}, but found" + " recipe directory, so building " + "{0} first").format(pkg)) add_recipes.append(recipe_dir) else: raise RuntimeError("Can't build {0} due to unsatisfiable dependencies:\n" .format(recipe) + error_str + "\n\n" + extra_help) recipe_list.extendleft(add_recipes) # outputs message, or does upload, depending on value of args.anaconda_upload if post in [True, None]: output_file = bldpkg_path(metadata, config=recipe_config) handle_anaconda_upload(output_file, config=recipe_config) already_built.add(output_file)