Skip to content

recipe

Describes the Recipe class and validates recipes using pydantic

dump_model(recipe_file, recipe, readonly=False, force=False)

Dumps recipe to yaml file.

Source code in hpcman/hpcman/software/recipe.py
@log_call()
def dump_model(recipe_file: Path, recipe: BaseModel, readonly: bool = False, force: bool = False) -> None:
    """Dumps recipe to yaml file."""
    writer = YAML(typ="rt", pure=True)
    if force and recipe_file.exists() and not os.access(recipe_file, os.W_OK):
        recipe_file.chmod(stat.S_IWUSR)
    try:
        to_yaml_file(recipe_file, recipe, custom_yaml_writer=writer)
    except PermissionError:
        rprint(f"You do not have permission to over-write {recipe_file.as_posix()}.")
        rprint("Use the '--force' option and try again. Also, check your '$USER'")
        return None
    if readonly:
        recipe_file.chmod(mode=0o444)

export_and_dump(recipe_dir, recipe)

Makes directory and dumps recipe there

Source code in hpcman/hpcman/software/recipe.py
@log_call()
def export_and_dump(recipe_dir: Path, recipe: BaseRecipe) -> Path:
    """Makes directory and dumps recipe there"""
    new_recipe = Path(recipe_dir / recipe.recipe_name)
    new_recipe.mkdir(mode=0o775, exist_ok=True)
    dump_model(Path(new_recipe / RECIPE_FN), recipe)
    return new_recipe

export_model_schema(method)

Exports schema from pydantic model

Source code in hpcman/hpcman/software/recipe.py
def export_model_schema(method: InstallMethod) -> None:
    """Exports schema from pydantic model"""
    if method is InstallMethod.CONDA:
        recipe = CondaRecipe
    elif method is InstallMethod.PIXI:
        recipe = PixiRecipe
    elif method is InstallMethod.PIPX:
        recipe = PipxRecipe
    else:
        rprint(f"Method '{method.value}' hasn't been implemented yet.")
        exit()
    print_json(json.dumps(recipe.model_json_schema()))

get_finished_recipe(**kwargs)

Generate proper Recipe Class

Source code in hpcman/hpcman/software/recipe.py
@log_call()
def get_finished_recipe(**kwargs) -> BaseRecipe:
    """Generate proper Recipe Class"""
    method = kwargs.get("method")
    if method == InstallMethod.CONDA:
        return CondaRecipe(**kwargs)
    elif method == InstallMethod.COMPILE:
        return BaseRecipe(**kwargs)
    elif method == InstallMethod.PIPX:
        if "pkgs" in kwargs:
            if len(pkgs := kwargs.pop("pkgs", [])) == 1:
                kwargs["pkg"] = pkgs[0]
            else:
                rprint("[red]Pipx recipe only supports one package[/red]")
                rprint("Either update your recipe with one pkg and/or specify additional pkgs with --libs.")
                exit(1)
        return PipxRecipe(**kwargs)
    elif method == InstallMethod.PIXI:
        if "pkgs" in kwargs:
            if len(pkgs := kwargs.pop("pkgs", [])) == 1:
                kwargs["pkg"] = pkgs[0]
            else:
                rprint("[red]Pixi recipe only supports one package[/red]")
                rprint("Either update your recipe with one pkg or use the conda install method.")
                exit(1)
        return PixiRecipe(**kwargs)
    else:
        rprint(f"[red]Unknown method {method}[/red]")
        return BaseRecipe(**kwargs)

get_recipe_list(recipe_dir)

Get list of recipe names.

Source code in hpcman/hpcman/software/recipe.py
def get_recipe_list(recipe_dir: Path) -> List[str]:
    """Get list of recipe names."""
    recipes = [x.name for x in recipe_dir.iterdir() if x.is_dir() and Path(x / RECIPE_FN).exists()]

    return recipes

handle_recipe_errors(e)

Handles recipe errors and prints messages

Source code in hpcman/hpcman/software/recipe.py
def handle_recipe_errors(e: ValidationError) -> None:
    """Handles recipe errors and prints messages"""
    rprint(f"Detected {e.error_count()} validation error(s):")
    for error in e.errors():
        if (
            any(option in error["loc"] for option in ("recipe_name", "name"))
            and error["type"] == "string_pattern_mismatch"
        ):
            error["msg"] = "'recipe_name' and 'name' must not contain spaces. Check settings and try again."
        rprint(f" => Fields: {error['loc']}")
        rprint(f" => {error['msg']} -> type={error['type']}, input_value={error['input']}\n")

    rprint("Please provide these values in the hpcrecipe.yaml file or as command-line options and try again.")
    exit(1)

update_recipe(recipe, **kwargs)

Update recipe with new info

Source code in hpcman/hpcman/software/recipe.py
@log_call()
def update_recipe(recipe: BaseRecipe, **kwargs) -> BaseRecipe:
    """Update recipe with new info"""
    for k, v in kwargs.items():
        if hasattr(recipe, k):
            setattr(recipe, k, v)
        else:
            logger.warning(f"Attempting to set option '{k}' which is not present for method '{recipe.method}'.")
    return recipe