Source code for projspec.proj.conda_package

from projspec.proj import ParseFailed, ProjectSpec
from projspec.utils import AttrDict, _yaml_no_jinja


[docs] class CondaRecipe(ProjectSpec): """Recipe package for conda-build""" icon = "📦" spec_doc = ( "https://docs.conda.io/projects/conda-build/" "en/stable/resources/define-metadata.html" ) def match(self) -> bool: return not {"meta.yaml", "meta.yml", "conda.yaml"}.isdisjoint( self.proj.basenames ) def parse(self) -> None: from projspec.artifact.installable import CondaPackage from projspec.content.environment import Environment, Precision, Stack # https://github.com/conda/conda-recipe-manager/tree/main/conda_recipe_manager/parser may be a good # renderer of the jinja stuff meta = None for fn in ("meta.yaml", "meta.yml", "conda.yaml"): if fn in self.proj.basenames: try: with self.proj.fs.open(self.proj.basenames[fn], "rb") as f: meta0 = _yaml_no_jinja(f) # TODO: multiple output recipe if "package" in meta0: meta = meta0 break if "outputs" in meta0 and any( "name" in _ for _ in meta0["outputs"] ): meta = meta0 break except (OSError, ValueError, UnicodeDecodeError): pass if meta is None: raise ParseFailed art = CondaPackage( proj=self.proj, cmd=["conda-build", f"{self.proj.url}/*.conda"] ) self._artifacts = AttrDict(conda_package=art) # TODO: read envs from "outputs" like for Rattler, below? # or use ``conda render`` to "lock" a templated recipe self._contents = AttrDict( environment=AttrDict( { k: Environment( proj=self.proj, packages=v, stack=Stack.CONDA, precision=Precision.SPEC, ) for k, v in meta.get("requirements", {}).items() } ) )
[docs] class RattlerRecipe(CondaRecipe): """Recipe project for rattler-build""" icon = "📭" spec_doc = "https://rattler.build/latest/reference/recipe_file/" # conda recipes are also valid for rattler if they don't have complex jinja. def match(self) -> bool: return "recipe.yaml" in self.proj.basenames def parse(self) -> None: # TODO: variants.yaml, conda_build_config.yaml or variant_config.yaml? from projspec.artifact.installable import CondaPackage from projspec.content.environment import Environment, Precision, Stack if "recipe.yaml" in self.proj.basenames: with self.proj.fs.open(self.proj.basenames["recipe.yaml"], "rb") as f: meta = _yaml_no_jinja(f) elif "meta.yaml" in self.proj.basenames: with self.proj.fs.open(self.proj.basenames["meta.yaml"], "rb") as f: meta = _yaml_no_jinja(f) else: raise ParseFailed cmd = [ "rattler-build", "build", "-r", self.proj.url, "--output-dir", f"{self.proj.url}/output", ] name = next( filter( bool, (meta.get(_, {}).get("name") for _ in ("context", "recipe", "package")), ) ) path = f"{self.proj.url}/output/{name}" if self.proj.is_local() else None art = CondaPackage( proj=self.proj, cmd=cmd, fn=path, name=name, ) self._artifacts = AttrDict(conda_package=art) try: req = next( filter( bool, (_.get("requirements") for _ in [meta] + meta.get("outputs", [])), ) ) self._contents = AttrDict( environment=AttrDict( { k: Environment( proj=self.proj, packages=v, stack=Stack.CONDA, precision=Precision.SPEC, ) for k, v in req.items() } ) ) except StopIteration: pass