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.CondaRenderFailure(item, message=None, line=None, column=None)[source]

Bases: bioconda_utils.recipe.RecipeError

Raised when conda_build.api.render fails

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

Bases: bioconda_utils.recipe.RecipeError

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.EmptyRecipe(item, message=None, line=None, column=None)[source]

Bases: bioconda_utils.recipe.RecipeError

Raised if the recipe file is empty

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

Bases: bioconda_utils.recipe.RecipeError

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

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

Bases: bioconda_utils.recipe.RecipeError

Raised if the recipe is missing the build section

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

Bases: bioconda_utils.recipe.RecipeError

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

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

Bases: bioconda_utils.recipe.RecipeError

Raised when FileNotFoundError is encountered

self.item is NOT a Recipe but a str here

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

Bases: object

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 = None

path to folder containing recipes

property build_number

The current build number

Return type

int

conda_release()[source]

Releases resources acquired in conda_render

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.

data = None

For passing data around

property dir

Path to recipe folder

dump()[source]

Dump recipe content

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

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

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_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_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

get_template()[source]

Create a Jinja2 template from the current raw recipe

load_from_string(data)[source]

Load and render recipe contents from disk

Return type

Recipe

property maintainers

List of recipe maintainers

meta = None

Parsed recipe YAML

meta_yaml = None

Lines of the raw recipe file

property name

The name of the toplevel package built by this recipe

Return type

str

on_branch = None

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

orig = None

Original recipe before modifications (updated by load_from_string)

property package_names

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

Return type

List[str]

property path

Full path to meta.yaml

reldir = None

relative path to recipe dir from folder containing recipes

property relpath

Relative path to meta.yaml (from basedir)

render()[source]

Convert recipe text into data structure

  • create jinja template from recipe content

  • render template

  • parse yaml

  • normalize

Return type

None

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.

set(path, value)[source]

Set a value or section in the recipe

See get for a description of how path works.

set_original()[source]

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

Return type

None

property version

The version of the package build by this recipe

Return type

str

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

Bases: bioconda_utils.aiopipe.EndProcessingItem

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

Bases: bioconda_utils.recipe.RecipeError

Raised on Jinja rendering problems

May have self.line