Skip to content

Commit

Permalink
Migrates CRM to use yaml.CSafeLoader over yaml.safe_load() (#115)
Browse files Browse the repository at this point in the history
* Migrates CRM to use yaml.CSafeLoader over yaml.safe_load()

* Adds import guard per JC's suggestion

* Fixes mypy issue
  • Loading branch information
schuylermartin45 authored Sep 9, 2024
1 parent f50159c commit dafada1
Showing 1 changed file with 12 additions and 6 deletions.
18 changes: 12 additions & 6 deletions conda_recipe_manager/parser/recipe_reader.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,12 @@
from conda_recipe_manager.parser.types import TAB_AS_SPACES, TAB_SPACE_COUNT, MultilineVariant
from conda_recipe_manager.types import PRIMITIVES_TUPLE, JsonType, Primitives, SentinelType

# Import guard: Fallback to `SafeLoader` if `CSafeLoader` isn't available
try:
from yaml import CSafeLoader as SafeLoader
except ImportError:
from yaml import SafeLoader # type: ignore[assignment]


class RecipeReader(IsModifiable):
"""
Expand Down Expand Up @@ -97,10 +103,10 @@ def _v1_sub_jinja() -> None:
# then we fall back to performing JINJA substitutions.
try:
try:
output = cast(JsonType, yaml.safe_load(s))
output = yaml.load(s, Loader=SafeLoader)
_v1_sub_jinja()
except yaml.scanner.ScannerError:
output = cast(JsonType, yaml.safe_load(quote_special_strings(s)))
output = cast(JsonType, yaml.load(quote_special_strings(s), Loader=SafeLoader))
_v1_sub_jinja()
except Exception: # pylint: disable=broad-exception-caught
# If a construction exception is thrown, attempt to re-parse by replacing Jinja macros (substrings in
Expand All @@ -110,7 +116,7 @@ def _v1_sub_jinja() -> None:
sub_list: list[str] = Regex.JINJA_V0_SUB.findall(s)
s = Regex.JINJA_V0_SUB.sub(RECIPE_MANAGER_SUB_MARKER, s)
output = RecipeReader._parse_yaml_recursive_sub(
cast(JsonType, yaml.safe_load(s)), lambda d: substitute_markers(d, sub_list)
cast(JsonType, yaml.load(s, Loader=SafeLoader)), lambda d: substitute_markers(d, sub_list)
)
# Because we leverage PyYaml to parse the data structures, we need to perform a second pass to perform
# variable substitutions.
Expand Down Expand Up @@ -259,7 +265,7 @@ def _set_on_schema_version() -> tuple[int, re.Pattern[str]]:
# - Ensures the returned value is YAML-parsable
elif self._schema_version == SchemaVersion.V0:
s = f"${s}"
return cast(JsonType, yaml.safe_load(s))
return cast(JsonType, yaml.load(s, Loader=SafeLoader))

def _init_vars_tbl(self) -> None:
"""
Expand Down Expand Up @@ -652,7 +658,7 @@ def _render_object_tree(self, node: Node, replace_variables: bool, data: JsonTyp
if replace_variables:
value = self._render_jinja_vars(value)
elif child.multiline_variant != MultilineVariant.NONE:
value = cast(str, yaml.safe_load(value))
value = cast(str, yaml.load(value, Loader=SafeLoader))

# Empty keys are interpreted to point to `None`
if child.is_empty_key():
Expand Down Expand Up @@ -769,7 +775,7 @@ def get_value(self, path: str, default: JsonType | SentinelType = _sentinel, sub
)
if sub_vars:
return self._render_jinja_vars(multiline_str)
return cast(JsonType, yaml.safe_load(multiline_str))
return cast(JsonType, yaml.load(multiline_str, Loader=SafeLoader))
return_value = cast(Primitives, node.children[0].value)
# Leaf nodes can return their value directly
elif node.is_leaf():
Expand Down

0 comments on commit dafada1

Please sign in to comment.