From c0ea1876bcaba99ddc728b5c7ad63cf11e1e1106 Mon Sep 17 00:00:00 2001 From: Andre Anjos <andre.dos.anjos@gmail.com> Date: Wed, 4 Aug 2021 16:35:22 +0200 Subject: [PATCH] [build] Simplify recipe parsing and environment creation significantly and fixes multiple environment creation issues; Closes #70 --- bob/devtools/build.py | 68 +++++++++++++++++++++++----------- bob/devtools/ci.py | 23 ------------ bob/devtools/scripts/ci.py | 2 +- bob/devtools/scripts/create.py | 11 +----- 4 files changed, 50 insertions(+), 54 deletions(-) diff --git a/bob/devtools/build.py b/bob/devtools/build.py index 1ccd8774..52fd2d79 100644 --- a/bob/devtools/build.py +++ b/bob/devtools/build.py @@ -227,8 +227,7 @@ def get_parsed_recipe(metadata): """Renders the recipe and returns the interpreted YAML file.""" with root_logger_protection(): - output = conda_build.api.output_yaml(metadata[0][0]) - return yaml.load(output, Loader=yaml.FullLoader) + return metadata[0][0].get_rendered_recipe_text() def exists_on_channel(channel_url, basename): @@ -289,29 +288,56 @@ def remove_pins(deps): return [ll.split()[0] for ll in deps] +def uniq(seq, idfun=None): + """Very fast, order preserving uniq function.""" + + # order preserving + if idfun is None: + + def idfun(x): + return x + + seen = {} + result = [] + for item in seq: + marker = idfun(item) + # in old Python versions: + # if seen.has_key(marker) + # but in new ones: + if marker in seen: + continue + seen[marker] = 1 + result.append(item) + return result + + def parse_dependencies(recipe_dir, config): metadata = get_rendered_metadata(recipe_dir, config) recipe = get_parsed_recipe(metadata) - build_requirements = remove_pins(recipe["requirements"].get("build", [])) - # causes conflicts on macOS - if "llvm-tools" in build_requirements: - build_requirements.remove("llvm-tools") - if "libgfortran4" in build_requirements: - build_requirements.remove("libgfortran4") - return ( - build_requirements - + remove_pins(recipe["requirements"].get("host", [])) - + recipe["requirements"].get("run", []) - + recipe.get("test", {}).get("requires", []) - + ["pip"] # required for installing further packages - + ["bob.buildout"] # required for basic bootstrap of most recipes - + ["ipython"] # for ipdb - # Also add anaconda compilers to make sure source installed packages are - # compiled properly - + ["clangxx_osx-64" if platform.system() == "Darwin" else "gxx_linux-64"] - ) - # by last, packages required for local dev + requirements = [] + for section in ("build", "host"): + requirements += remove_pins(recipe.get("requirements", {}).get(section, [])) + # we don't remove pins for the rest of the recipe + requirements += recipe.get("requirements", {}).get("run", []) + requirements += recipe.get("test", {}).get("requires", []) + + # also add anaconda compilers to make sure source installed packages are + # compiled properly + if platform.system() == "Darwin": + requirements += ["clangxx_osx-64"] + else: + requirements += ["gxx_linux-64"] + + # further requirements + requirements += [ + "pip", # required for installing further packages + "bob.buildout", # required for basic bootstrap of most recipes + "ipython", # for ipdb + ] + + # remove duplicates without affecting the order + return uniq(requirements) def get_env_directory(conda, name): diff --git a/bob/devtools/ci.py b/bob/devtools/ci.py index 186d7675..0206740f 100644 --- a/bob/devtools/ci.py +++ b/bob/devtools/ci.py @@ -135,29 +135,6 @@ def read_packages(filename): return packages -def uniq(seq, idfun=None): - """Very fast, order preserving uniq function.""" - - # order preserving - if idfun is None: - - def idfun(x): - return x - - seen = {} - result = [] - for item in seq: - marker = idfun(item) - # in old Python versions: - # if seen.has_key(marker) - # but in new ones: - if marker in seen: - continue - seen[marker] = 1 - result.append(item) - return result - - def select_build_file(basename, paths, branch): """Selects the file to use for a build. diff --git a/bob/devtools/scripts/ci.py b/bob/devtools/scripts/ci.py index 9a768696..57e45b96 100644 --- a/bob/devtools/scripts/ci.py +++ b/bob/devtools/scripts/ci.py @@ -13,13 +13,13 @@ from click_plugins import with_plugins from ..build import comment_cleanup from ..build import load_order_file +from ..build import uniq from ..ci import cleanup from ..ci import is_private from ..ci import read_packages from ..ci import select_conda_build_config from ..ci import select_conda_recipe_append from ..ci import select_user_condarc -from ..ci import uniq from ..constants import BASE_CONDARC from ..constants import SERVER from ..deploy import deploy_conda_package diff --git a/bob/devtools/scripts/create.py b/bob/devtools/scripts/create.py index 426c1bf0..9d0c4450 100644 --- a/bob/devtools/scripts/create.py +++ b/bob/devtools/scripts/create.py @@ -12,6 +12,7 @@ from ..bootstrap import set_environment from ..build import conda_create from ..build import make_conda_config from ..build import parse_dependencies +from ..build import uniq from ..config import read_config from ..constants import BASE_CONDARC from ..constants import CONDA_BUILD_CONFIG @@ -25,14 +26,6 @@ from . import bdt logger = get_logger(__name__) -def _uniq(seq): - """Fast order preserving uniq() function for Python lists""" - - seen = set() - seen_add = seen.add - return [x for x in seq if not (x in seen or seen_add(x))] - - @click.command( epilog=""" Examples: @@ -279,7 +272,7 @@ def create( pip_extras_config = [] if "create" in config: pip_extras_config = config["create"].get("pip_extras", "").split() - pip_extras = _uniq(pip_extras_config + list(pip_extras)) + pip_extras = uniq(pip_extras_config + list(pip_extras)) if pip_extras: logger.info("Pip-installing: %s", pip_extras) -- GitLab