Warning

This document is for an old release of Galaxy. You can alternatively view this page in the latest release if it exists or view the top of the latest release's documentation.

Source code for galaxy.tool_util.deps.conda_compat

"""Compat. layer with conda_build/verify if Galaxy/galaxy-lib not installed through conda.

In general there are utilities available for Conda building and parsing that are high-quality
and should be utilized when available but that are only available in conda channels and not in
PyPI. This module serves as a PyPI capable interface to these utilities.
"""
import os
from collections.abc import Hashable

import yaml

try:
    from conda_build.metadata import MetaData
except ImportError:
    MetaData = None

try:
    from anaconda_verify.recipe import (
        parse,
        render_jinja2,
    )
except ImportError:
    render_jinja2 = None
    parse = None


class _Memoized:
    def __init__(self, func):
        self.func = func
        self.cache = {}

    def __call__(self, *args):
        if not isinstance(args, Hashable):
            # uncacheable. a list, for instance.
            # better to not cache than blow up.
            return self.func(*args)
        if args in self.cache:
            return self.cache[args]
        else:
            value = self.func(*args)
            self.cache[args] = value
            return value


def _parse(data, cfg):
    """Parse metadata YAML."""
    assert cfg is None, "Conda utilities for evaluating cfg are not available."
    return dict(yamlize(data))


def _render_jinja2(recipe_dir):
    """Evaluate Conda recipe as a jinja template."""
    try:
        import jinja2
    except ImportError:
        raise Exception("Failed to import jinja2 for evaluating Conda recipe templates.")

    loaders = [jinja2.FileSystemLoader(recipe_dir)]
    env = jinja2.Environment(loader=jinja2.ChoiceLoader(loaders))
    template = env.get_or_select_template("meta.yaml")
    return template.render(environment=env)


@_Memoized
def yamlize(data):
    res = yaml.safe_load(data)
    # ensure the result is a dict
    if res is None:
        res = {}
    return res


if render_jinja2 is None:
    render_jinja2 = _render_jinja2

if parse is None:
    parse = _parse


[docs]def raw_metadata(recipe_dir): """Evaluate Conda template if needed and return raw metadata for supplied recipe directory.""" meta_path = os.path.join(recipe_dir, "meta.yaml") with open(meta_path, "rb") as fi: data = fi.read() if b"{{" in data: data = render_jinja2(recipe_dir) meta = parse(data, None) return meta
class _MetaData: def __init__(self, input_dir): self.meta = raw_metadata(input_dir) def get_value(self, field, default=None): """Get nested field value or supplied default is not present.""" section, key = field.split("/") submeta = self.meta.get(section) if submeta is None: submeta = {} res = submeta.get(key) if res is None: res = default return res if MetaData is None: MetaData = _MetaData __all__ = ( "MetaData", "raw_metadata", )