Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: type loader.py #14

Merged
merged 5 commits into from
Jul 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pixi.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ ignore = [
]
exclude = [
"src/rattler_build_conda_compat/lint.py",
"src/rattler_build_conda_compat/loader.py",
"src/rattler_build_conda_compat/render.py",
"src/rattler_build_conda_compat/utils.py",
]
Expand Down
56 changes: 30 additions & 26 deletions src/rattler_build_conda_compat/loader.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,31 @@
from __future__ import annotations

from contextlib import contextmanager
from typing import TYPE_CHECKING, Any, Iterator, Self

import yaml
from typing import Any, Dict, Union

from rattler_build_conda_compat.conditional_list import visit_conditional_list

if TYPE_CHECKING:
from os import PathLike


class RecipeLoader(yaml.BaseLoader):
@classmethod
@contextmanager
def with_namespace(cls, namespace):
def with_namespace(cls: Self, namespace: dict[str, Any] | None) -> Iterator[None]:
try:
cls._namespace = namespace
yield
finally:
del cls._namespace

def construct_sequence(self, node: Any, deep: bool = False) -> Any:
def construct_sequence( # noqa: C901
self: Self,
node: yaml.Node,
deep: bool = False, # noqa: FBT002, FBT001
) -> list[yaml.Node]:
"""deep is True when creating an object/mapping recursively,
in that case want the underlying elements available during construction
"""
Expand All @@ -31,9 +43,8 @@ def construct_sequence(self, node: Any, deep: bool = False) -> Any:
then_node_key, then_node_value = child_node.value[idx + 1]

if then_node_key.value != "then":
raise ValueError(
"cannot have if without then, please reformat your variant file"
)
msg = "cannot have if without then, please reformat your variant file"
raise ValueError(msg)

try:
_, else_node_value = child_node.value[idx + 2]
Expand All @@ -42,7 +53,7 @@ def construct_sequence(self, node: Any, deep: bool = False) -> Any:

to_be_eval = f"{value_node.value}"

evaled = eval(to_be_eval, self._namespace)
evaled = eval(to_be_eval, self._namespace) # noqa: S307
if evaled:
the_evaluated_one = then_node_value
elif else_node_value:
Expand All @@ -56,7 +67,7 @@ def construct_sequence(self, node: Any, deep: bool = False) -> Any:
node.value.remove(child_node)

if not isinstance(node, yaml.SequenceNode):
raise Exception(
raise TypeError(
None,
None,
f"expected a sequence node, but found {node.id!s}",
Expand All @@ -66,11 +77,11 @@ def construct_sequence(self, node: Any, deep: bool = False) -> Any:
return [self.construct_object(child, deep=deep) for child in node.value]


def load_yaml(content: Union[str, bytes]):
return yaml.load(content, Loader=yaml.BaseLoader)
def load_yaml(content: str | bytes) -> Any: # noqa: ANN401
return yaml.load(content, Loader=yaml.BaseLoader) # noqa: S506


def remove_empty_keys(variant_dict):
def remove_empty_keys(variant_dict: dict[str, Any]) -> dict[str, Any]:
filtered_dict = {}
for key, value in variant_dict.items():
if isinstance(value, list) and len(value) == 0:
Expand All @@ -80,14 +91,15 @@ def remove_empty_keys(variant_dict):
return filtered_dict


def parse_recipe_config_file(path, namespace):
with open(path) as f:
with RecipeLoader.with_namespace(namespace):
content = yaml.load(f, Loader=RecipeLoader)
def parse_recipe_config_file(
path: PathLike[str], namespace: dict[str, Any] | None
) -> dict[str, Any]:
with open(path) as f, RecipeLoader.with_namespace(namespace):
content = yaml.load(f, Loader=RecipeLoader) # noqa: S506
return remove_empty_keys(content)


def load_all_requirements(content) -> Dict[str, Any]:
def load_all_requirements(content: dict[str, Any]) -> dict[str, Any]:
requirements_section = dict(content.get("requirements", {}))
if not requirements_section:
return {}
Expand All @@ -96,15 +108,7 @@ def load_all_requirements(content) -> Dict[str, Any]:
section_reqs = requirements_section[section]
if not section_reqs:
continue
expanded_reqs = []
for req in section_reqs:
if isinstance(req, dict):
then_reqs = req.get("then", [])
else_reqs = req.get("else", [])
expanded_reqs.extend(then_reqs)
expanded_reqs.extend(else_reqs)
else:
expanded_reqs.append(req)
requirements_section[section] = expanded_reqs

requirements_section[section] = list(visit_conditional_list(section_reqs))

return requirements_section