Source code for conda_recipe_manager.parser.build_context
"""
:Description: Provides an object that can be configured to perform complex selector queries.
"""
from enum import StrEnum
from functools import cache
from typing import Final, cast
from conda_recipe_manager.parser.exceptions import BuildContextVersionException
from conda_recipe_manager.parser.platform_types import (
ALL_ARCHITECTURES,
ALL_OPERATING_SYSTEMS,
ALL_PLATFORM_ALIASES,
Platform,
get_platforms_by_alias,
get_platforms_by_arch,
get_platforms_by_os,
)
from conda_recipe_manager.types import Primitives
[docs]
class BuildContextKey(StrEnum):
"""
Enumeration of the keys that contain int-convertible version information in the build context.
"""
PYTHON = "python"
NUMPY = "numpy"
[docs]
class BuildContext:
"""
Class that is used to represent the build environment context for selector and Jinja expression evaluation.
"""
@staticmethod
@cache # type: ignore[misc]
def _get_platform_context(platform: Platform) -> dict[str, Primitives]:
"""
Constructs the context for the build platform.
:returns: The constructed context.
"""
context: Final[dict[str, Primitives]] = {}
context["build_platform"] = platform.value
context["target_platform"] = platform.value
for alias in ALL_PLATFORM_ALIASES:
context[alias.value] = platform in get_platforms_by_alias(alias)
for arch in ALL_ARCHITECTURES:
context[arch.value] = platform in get_platforms_by_arch(arch)
for os in ALL_OPERATING_SYSTEMS:
context[os.value] = platform in get_platforms_by_os(os)
return context
def _check_and_convert_to_int(self, key: BuildContextKey) -> int:
"""
Checks if the value for the given key is a string and converts it to an integer.
:param key: The key to check and convert.
:raises BuildContextVersionException: If the value is not a string or is not a valid version.
:returns: The converted integer.
"""
val: Final[Primitives] = self._build_env_vars.get(key)
if not isinstance(val, str):
raise BuildContextVersionException(key, val)
version_int: Final[str] = val.replace(".", "")
if not version_int.isdigit():
raise BuildContextVersionException(key, val)
return int(version_int)
def _get_py_np_context(self) -> dict[str, Primitives]:
"""
Constructs the context for the Python and NumPy versions.
:raises BuildContextVersionException: If the Python or NumPy version is not a valid version.
:returns: The constructed Python and NumPy context.
"""
context: Final[dict[str, Primitives]] = {}
if self._build_env_vars.get("python"):
python_version_int: Final[int] = self._check_and_convert_to_int(BuildContextKey.PYTHON)
context["py"] = python_version_int
context["py3k"] = cast(str, self._build_env_vars["python"]).startswith("3.")
context["py2k"] = cast(str, self._build_env_vars["python"]).startswith("2.")
context["py27"] = context["py"] == 27
context["py34"] = context["py"] == 34
context["py35"] = context["py"] == 35
context["py36"] = context["py"] == 36
if self._build_env_vars.get("numpy"):
numpy_version_int: Final[int] = self._check_and_convert_to_int(BuildContextKey.NUMPY)
context["np"] = numpy_version_int
return context
def _construct_build_context(self) -> dict[str, Primitives]:
"""
Constructs the context for the build.
:returns: The constructed build context.
"""
return {
**self._build_env_vars,
**self._get_py_np_context(),
**BuildContext._get_platform_context(self._platform),
}
def _construct_selector_context(self) -> dict[str, Primitives]:
"""
Constructs the selector context. Selectors use type coercion to convert strings
to their appropriate types.
:returns: The constructed selector context.
"""
selector_context: Final[dict[str, Primitives]] = {}
for key, value in self._context.items():
# Mirror conda-build's behavior of coercing strings to their appropriate types.
# See https://github.com/conda/conda-build/issues/5852
if isinstance(value, str):
try:
value = int(value)
except ValueError:
lower_val = cast(str, value).lower()
if lower_val in {"true", "false"}:
value = lower_val == "true"
selector_context[key] = value
return selector_context
def __init__( # pylint: disable=dangerous-default-value
self, platform: Platform, build_env_vars: dict[str, Primitives] = {}
) -> None:
"""
Constructs a build context given the platform and build environment variables.
:param platform: Platform to evaluate the context for.
:param build_env_vars: Build environment variables to evaluate the context for.
"""
self._platform: Final[Platform] = platform
self._build_env_vars: Final[dict[str, Primitives]] = build_env_vars
self._context: Final[dict[str, Primitives]] = self._construct_build_context()
self._selector_context: Final[dict[str, Primitives]] = self._construct_selector_context()
[docs]
def get_context(self) -> dict[str, Primitives]:
"""
Returns the build context.
:returns: The build context.
"""
return self._context
[docs]
def get_selector_context(self) -> dict[str, Primitives]:
"""
Returns the selector context.
:returns: The selector context.
"""
return self._selector_context
[docs]
def get_platform(self) -> Platform:
"""
Returns the build platform.
:returns: The build platform.
"""
return self._platform