Skip to content

Commit

Permalink
Add conda_build.yaml
Browse files Browse the repository at this point in the history
  • Loading branch information
kenodegard committed Apr 15, 2024
1 parent ea171c0 commit 322de87
Show file tree
Hide file tree
Showing 13 changed files with 168 additions and 152 deletions.
14 changes: 8 additions & 6 deletions conda_build/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,15 @@
from pathlib import Path

import conda_package_handling.api
import yaml
from bs4 import UnicodeDammit
from conda import __version__ as conda_version
from conda.base.context import context, reset_context
from conda.core.prefix_data import PrefixData
from conda.exceptions import CondaError, NoPackagesFoundError, UnsatisfiableError
from conda.models.channel import Channel

from conda_build import yaml

from . import __version__ as conda_build_version
from . import environ, noarch_python, source, tarcheck, utils
from .conda_interface import (
Expand Down Expand Up @@ -882,7 +883,7 @@ def copy_recipe(m):

# dump the full variant in use for this package to the recipe folder
with open(os.path.join(recipe_dir, "conda_build_config.yaml"), "w") as f:
yaml.dump(m.config.variant, f)
yaml.safe_dump(m.config.variant, f)


def copy_readme(m):
Expand Down Expand Up @@ -918,11 +919,12 @@ def jsonify_info_yamls(m):
except:
pass
with open(file) as i, open(dst, "w") as o:
import yaml

yaml = yaml.full_load(i)
json.dump(
yaml, o, sort_keys=True, indent=2, separators=(",", ": ")
yaml.safe_load(i),
o,
sort_keys=True,
indent=2,
separators=(",", ": "),
)
res.append(
join(os.path.basename(m.config.info_dir), ijd, bn + ".json")
Expand Down
3 changes: 3 additions & 0 deletions conda_build/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
# SPDX-License-Identifier: BSD-3-Clause
import textwrap

from .deprecations import deprecated

SEPARATOR = "-" * 70

indent = lambda s: textwrap.fill(textwrap.dedent(s))
Expand Down Expand Up @@ -42,6 +44,7 @@ def indented_exception(self):
return f"Error Message:\n--> {indent(orig)}\n\n"


@deprecated("24.5", "24.7", addendum="Unused.")
class UnableToParseMissingJinja2(UnableToParse):
def error_body(self):
return "\n".join(
Expand Down
61 changes: 12 additions & 49 deletions conda_build/metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,10 @@
from conda.gateways.disk.read import compute_sum
from frozendict import deepfreeze

from . import exceptions, utils, variants
from . import exceptions, utils, variants, yaml
from .conda_interface import MatchSpec
from .config import Config, get_or_merge_config
from .deprecations import deprecated
from .features import feature_list
from .license_family import ensure_valid_license_family
from .utils import (
Expand All @@ -34,50 +35,19 @@
insert_variant_versions,
on_win,
)
from .yaml import _StringifyNumbersLoader

if TYPE_CHECKING:
from typing import Literal

try:
import yaml
except ImportError:
sys.exit(
"Error: could not import yaml (required to read meta.yaml "
"files of conda recipes)"
)

try:
Loader = yaml.CLoader
except AttributeError:
Loader = yaml.Loader


class StringifyNumbersLoader(Loader):
@classmethod
def remove_implicit_resolver(cls, tag):
if "yaml_implicit_resolvers" not in cls.__dict__:
cls.yaml_implicit_resolvers = {
k: v[:] for k, v in cls.yaml_implicit_resolvers.items()
}
for ch in tuple(cls.yaml_implicit_resolvers):
resolvers = [(t, r) for t, r in cls.yaml_implicit_resolvers[ch] if t != tag]
if resolvers:
cls.yaml_implicit_resolvers[ch] = resolvers
else:
del cls.yaml_implicit_resolvers[ch]

@classmethod
def remove_constructor(cls, tag):
if "yaml_constructors" not in cls.__dict__:
cls.yaml_constructors = cls.yaml_constructors.copy()
if tag in cls.yaml_constructors:
del cls.yaml_constructors[tag]

deprecated.constant(
"24.5",
"24.7",
"StringifyNumbersLoader",
_StringifyNumbersLoader,
addendum="Use `conda_build.yaml._StringifyNumbersLoader` instead.",
)

StringifyNumbersLoader.remove_implicit_resolver("tag:yaml.org,2002:float")
StringifyNumbersLoader.remove_implicit_resolver("tag:yaml.org,2002:int")
StringifyNumbersLoader.remove_constructor("tag:yaml.org,2002:float")
StringifyNumbersLoader.remove_constructor("tag:yaml.org,2002:int")

# arches that don't follow exact names in the subdir need to be mapped here
ARCH_MAP = {"32": "x86", "64": "x86_64"}
Expand Down Expand Up @@ -305,15 +275,8 @@ def select_lines(data, namespace, variants_in_place):

def yamlize(data):
try:
return yaml.load(data, Loader=StringifyNumbersLoader)
except yaml.error.YAMLError as e:
if "{{" in data:
try:
import jinja2

jinja2 # Avoid pyflakes failure: 'jinja2' imported but unused
except ImportError:
raise exceptions.UnableToParseMissingJinja2(original=e)
return yaml.safe_load(data, stringify_numbers=True)
except yaml.YAMLError as e:
print("Problematic recipe:", file=sys.stderr)
print(data, file=sys.stderr)
raise exceptions.UnableToParse(original=e)
Expand Down
66 changes: 28 additions & 38 deletions conda_build/render.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
from __future__ import annotations

import json
import os
import random
import re
import string
Expand All @@ -15,7 +14,6 @@
from contextlib import contextmanager
from functools import lru_cache
from os.path import (
dirname,
isabs,
isdir,
isfile,
Expand All @@ -25,13 +23,14 @@
from pathlib import Path
from typing import TYPE_CHECKING

import yaml
import yaml as pyyaml
from conda.base.context import context
from conda.core.package_cache_data import ProgressiveFetchExtract
from conda.exceptions import UnsatisfiableError

from . import environ, exceptions, source, utils
from . import environ, exceptions, source, utils, yaml
from .conda_interface import PackageRecord, TemporaryDirectory, specs_from_url
from .deprecations import deprecated
from .exceptions import DependencyNeedsBuildingError
from .index import get_build_index
from .metadata import MetaData, combine_top_level_metadata_with_output
Expand All @@ -47,20 +46,17 @@
)

if TYPE_CHECKING:
import os
from typing import Iterator

from .config import Config


@deprecated("24.5", "24.7")
def odict_representer(dumper, data):
return dumper.represent_dict(data.items())


yaml.add_representer(set, yaml.representer.SafeRepresenter.represent_list)
yaml.add_representer(tuple, yaml.representer.SafeRepresenter.represent_list)
yaml.add_representer(OrderedDict, odict_representer)


def bldpkg_path(m):
"""
Returns path to built package's tarball given its ``Metadata``.
Expand Down Expand Up @@ -1026,57 +1022,51 @@ def render_recipe(

# Next bit of stuff is to support YAML output in the order we expect.
# http://stackoverflow.com/a/17310199/1170370
@deprecated("24.5", "24.7")
class _MetaYaml(dict):
fields = FIELDS

def to_omap(self):
return [(field, self[field]) for field in _MetaYaml.fields if field in self]


@deprecated("24.5", "24.7")
def _represent_omap(dumper, data):
return dumper.represent_mapping("tag:yaml.org,2002:map", data.to_omap())


@deprecated("24.5", "24.7")
def _unicode_representer(dumper, uni):
node = yaml.ScalarNode(tag="tag:yaml.org,2002:str", value=uni)
node = pyyaml.ScalarNode(tag="tag:yaml.org,2002:str", value=uni)
return node


class _IndentDumper(yaml.Dumper):
@deprecated("24.5", "24.7")
class _IndentDumper(pyyaml.Dumper):
def increase_indent(self, flow=False, indentless=False):
return super().increase_indent(flow, False)

def ignore_aliases(self, data):
return True


yaml.add_representer(_MetaYaml, _represent_omap)
yaml.add_representer(str, _unicode_representer)
unicode = None # silence pyflakes about unicode not existing in py3
def output_yaml(
metadata: MetaData,
filename: str | os.PathLike | Path | None = None,
suppress_outputs: bool = False,
) -> str:
meta = metadata.meta
# create a manually ordered copy of the meta dict
meta = {field: meta[field] for field in FIELDS if field in meta}
if suppress_outputs and metadata.is_output and "outputs" in meta:
del meta["outputs"]

output = yaml.safe_dump(meta)

def output_yaml(metadata, filename=None, suppress_outputs=False):
local_metadata = metadata.copy()
if (
suppress_outputs
and local_metadata.is_output
and "outputs" in local_metadata.meta
):
del local_metadata.meta["outputs"]
output = yaml.dump(
_MetaYaml(local_metadata.meta),
Dumper=_IndentDumper,
default_flow_style=False,
indent=2,
)
if filename:
if any(sep in filename for sep in ("\\", "/")):
try:
os.makedirs(dirname(filename))
except OSError:
pass
with open(filename, "w") as f:
f.write(output)
return "Wrote yaml to %s" % filename
else:
if not filename:
return output

filename = Path(filename)
filename.parent.mkdir(parents=True, exist_ok=True)
filename.write_text(output)
return "Wrote yaml to %s" % filename
12 changes: 2 additions & 10 deletions conda_build/skeletons/cran.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,18 +29,10 @@
realpath,
relpath,
)
from typing import TYPE_CHECKING

import requests
import yaml

# try to import C dumper
try:
from yaml import CSafeDumper as SafeDumper
except ImportError:
from yaml import SafeDumper

from typing import TYPE_CHECKING

from conda.common.io import dashlist

from .. import source
Expand Down Expand Up @@ -564,7 +556,7 @@ def yaml_quote_string(string):
Note that this function is NOT general.
"""
return (
yaml.dump(string, indent=True, Dumper=SafeDumper)
yaml.safe_dump(string, indent=True)
.replace("\n...\n", "")
.replace("\n", "\n ")
.rstrip("\n ")
Expand Down
4 changes: 2 additions & 2 deletions conda_build/variants.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@
from functools import lru_cache
from itertools import product

import yaml
from conda.base.context import context

from . import yaml
from .conda_interface import cc_conda_build
from .utils import ensure_list, get_logger, islist, on_win, trim_empty_keys
from .version import _parse as parse_version
Expand Down Expand Up @@ -136,7 +136,7 @@ def parse_config_file(path, config):
with open(path) as f:
contents = f.read()
contents = select_lines(contents, get_selectors(config), variants_in_place=False)
content = yaml.load(contents, Loader=yaml.loader.BaseLoader) or {}
content = yaml.safe_load(contents) or {}
trim_empty_keys(content)
return content

Expand Down
Loading

0 comments on commit 322de87

Please sign in to comment.