recipe

Editable Recipe (meta.yaml)

The meta.yaml format used by conda to describe how a package is built has diverged from standard YAML format significantly. This module implements a class Recipe that in contrast to the Meta object resulting from parsing by conda_build offers functions to edit the meta.yaml.

Functions

load_parallel_iter(recipe_folder, packages)

Classes

Recipe(recipe_dir, recipe_folder)

Represents a recipe (meta.yaml) in editable form

Exceptions

CondaRenderFailure(item[, message, line, column])

Raised when conda_build.api.render fails

DuplicateKey(item[, message, line, column])

Raised for recipes with duplicate keys in the meta.yaml.

EmptyRecipe(item[, message, line, column])

Raised if the recipe file is empty

HasSelector(item[, message, line, column])

Raised when recplacements fail due to # [cond] line selectors FIXME: This should no longer be an error

MissingBuild(item[, message, line, column])

Raised if the recipe is missing the build section

MissingKey(item[, message, line, column])

Raised if a recipe is missing package/version or package/name

MissingMetaYaml(item[, message, line, column])

Raised when FileNotFoundError is encountered

RecipeError(item[, message, line, column])

RenderFailure(item[, message, line, column])

Raised on Jinja rendering problems

Documentation

exception bioconda_utils.recipe.RecipeError(item, message=None, line=None, column=None)[source]
exception bioconda_utils.recipe.DuplicateKey(item, message=None, line=None, column=None)[source]

Raised for recipes with duplicate keys in the meta.yaml. YAML does not allow those, but the PyYAML parser silently overwrites previous keys.

For duplicate keys that are a result of # [osx] style line selectors, Recipe attempts to resolve them as a list of dictionaries instead.

exception bioconda_utils.recipe.MissingKey(item, message=None, line=None, column=None)[source]

Raised if a recipe is missing package/version or package/name

exception bioconda_utils.recipe.EmptyRecipe(item, message=None, line=None, column=None)[source]

Raised if the recipe file is empty

exception bioconda_utils.recipe.MissingBuild(item, message=None, line=None, column=None)[source]

Raised if the recipe is missing the build section

exception bioconda_utils.recipe.HasSelector(item, message=None, line=None, column=None)[source]

Raised when recplacements fail due to # [cond] line selectors FIXME: This should no longer be an error

exception bioconda_utils.recipe.MissingMetaYaml(item, message=None, line=None, column=None)[source]

Raised when FileNotFoundError is encountered

self.item is NOT a Recipe but a str here

exception bioconda_utils.recipe.CondaRenderFailure(item, message=None, line=None, column=None)[source]

Raised when conda_build.api.render fails

exception bioconda_utils.recipe.RenderFailure(item, message=None, line=None, column=None)[source]

Raised on Jinja rendering problems

May have self.line

class bioconda_utils.recipe.Recipe(recipe_dir, recipe_folder)[source]

Represents a recipe (meta.yaml) in editable form

Using conda-build to render recipe is slow and a one-way process. We need to be able to load and save recipes, which is handled by the representation in this class.

Recipes undergo two manipulation rounds before parsed as YAML:
  1. Selecting lines using # [expression]

  2. Rendering as Jinja2 template

(1) is currently unhandled, leading to recipes with repeated mapping keys (commonly two url keys). Those recipes are ignored for the time being.

Parameters:
  • recipe_folder – base recipes folder

  • recipe_dir – path to specific recipe

JINJA_VARS = {'cdt': <function Recipe.<lambda>>, 'compiler': <function Recipe.<lambda>>, 'cran_mirror': 'https://cloud.r-project.org', 'pin_compatible': <function Recipe.<lambda>>}

Variables to pass to Jinja when rendering recipe

basedir

path to folder containing recipes

reldir

relative path to recipe dir from folder containing recipes

meta: Dict[str, Any]

Parsed recipe YAML

meta_yaml: List[str]

Lines of the raw recipe file

orig: Recipe

Original recipe before modifications (updated by load_from_string)

on_branch: bool

Whether the recipe was loaded from a branch (update in progress)

data: Dict[str, Any]

For passing data around

property path

Full path to meta.yaml

property relpath

Relative path to meta.yaml (from basedir)

property dir

Path to recipe folder

load_from_string(data)[source]

Load and render recipe contents from disk

Return type:

Recipe

classmethod from_file(recipe_dir, recipe_fname, return_exceptions=False)[source]

Create new Recipe object from file

Parameters:
  • recipe_dir – Path to recipes folder

  • recipe_fname – Relative path to recipe (folder or meta.yaml)

Return type:

Recipe

set_original()[source]

Store the current state of the recipe as “original” version

Return type:

None

dump()[source]

Dump recipe content

get_template()[source]

Create a Jinja2 template from the current raw recipe

get_simple_modules()[source]

Yield simple replacement values from template

E.g. those set with {% set version='1.2.3' %}`

Returns:

1.2.3)

Return type:

a dictionary of replacements (e.g. version

render()[source]

Convert recipe text into data structure

  • create jinja template from recipe content

  • render template

  • parse yaml

  • normalize

Return type:

None

property maintainers

List of recipe maintainers

property name: str

The name of the toplevel package built by this recipe

Return type:

str

property version: str

The version of the package build by this recipe

Return type:

str

property build_number: int

The current build number

Return type:

int

get_raw_range(path)[source]

Locate the position of a node in the YAML within the raw text

See also get_raw() if you want to get the content of the unparsed meta.yaml at a specific key.

Parameters:

path – The “path” to the node. Use numbers for lists (‘source/1/url’)

Returns:

a tuple of first_row, first_column, last_row, last_column

get_raw(path)[source]

Extracts the unparsed text for a node in the meta.yaml

This may contain separators and other characters from the yaml!

Parameters:

path – Slash-separated path to the node. Numbers can be used to access indices in lists. A number ‘0’ is ignored if the node is a dict (so ‘source/0/url’ will work even if there is only one url).

Returns:

Extracted raw text

get(path, default=<class 'KeyError'>)[source]

Get a value or section from the recipe

>>> recipe.get('requirements/build')
['setuptools]
>>> recipe.get('source/0/url')
'https://somewhere'

The path is a / separated list of dictionary keys to be walked in the recipe meta data. Numeric sections in the path access list elements. Using 0 in the path will get the first element in a list or the contents directly if there is no list. I.e., source/0/url will always get the first url, whether or not the source section is a list.

Parameters:
  • path (str) – Path through YAML

  • default (Any) – If not KeyError, this value will be returned if the path does not exist in the recipe

Raises:

KeyError if no default given and the path does not exist.

Return type:

Any

set(path, value)[source]

Set a value or section in the recipe

See get for a description of how path works.

property package_names: List[str]

List of the packages built by this recipe (including outputs)

Return type:

List[str]

replace(before, after, within=('package', 'source'), with_fuzz=False)[source]

Runs string replace on parts of recipe text.

  • Lines considered are those containing Jinja set statements ({% set var="val" %}) and those defining the top level Mapping entries given by within (default:package and source).

  • Cowardly refuses to modify lines with # [expression] selectors.

Return type:

int

reset_buildnumber(n=0)[source]

Resets the build number

If the build number is missing, it is added after build.

conda_render(bypass_env_check=True, finalize=True, permit_unsatisfiable_variants=False, **kwargs)[source]

Handles calling conda_build.api.render

conda_build.api.render is fragile, loud and slow. Avoid using this whenever you can.

This function will create a temporary directory, write out the current meta.yaml contents, redirect stdout and stderr to silence needless prints, ultimately call the render function, catching various exceptions and rewriting them into CondaRenderFailure, then cache the result.

Since the MetaData objects returned expect the on-disk meta.yaml to persist (it can get reloaded later on), clients of this function must make sure to call `conda_release` once you are done with those objects.

Parameters:
  • bypass_env_check – Avoids calling solver to fill in values for pin_compatible and resolved_packages in Jinja2 expansion. Changed default: conda-build.api.render defaults to False, we set this to True as it is very slow.

  • finalize – Has render() run finalize_metadata, which fills in versions for host/run dependencies.

  • permit_unsatisfiable_variants – Avoids raising UnsatisfiableError or DependencyNeedsBuildingError when determining package dependencies. Changed default: Set to True upstream, we set this to False to be informed about dependency problems.

  • kwargs – passed on to conda_build.api.render

Raises:

CondaRenderfailure – Some of the exceptions raised are rewritten to simplify handling. The list will grow, but is likely incomplete.

Return type:

List[Tuple[MetaData, bool, bool]]

Returns:

List of 3-tuples each comprising the rendered MetaData and the flags needs_download and needs_render_in_env.

FIXME:

Need to use kwargs to invalidate cache.

conda_release()[source]

Releases resources acquired in conda_render