]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
parsing: yaml: support for !include in root docs-parsing-yaml-jpfrdq/deployments/7282
authorAleš Mrázek <ales.mrazek@nic.cz>
Mon, 21 Jul 2025 13:42:06 +0000 (15:42 +0200)
committerAleš Mrázek <ales.mrazek@nic.cz>
Fri, 25 Jul 2025 21:00:35 +0000 (23:00 +0200)
python/knot_resolver/utils/modeling/parsing.py

index b9c76378a277c8dbf01d6af8354083ed97caf2a5..7f66fbd76f467dddbbff2308efecde656b334857 100644 (file)
@@ -81,15 +81,31 @@ def construct_include(loader: _RaiseDuplicatesIncludeLoader, node: Any) -> Any:
         return "".join(file.readlines())
 
 
+def include_root(text: str) -> str:
+    ntext = ""
+    for line in iter(text.splitlines()):
+        if line.startswith(_include_key):
+            file_path = line[len(_include_key) + 1 :]
+            with open(file_path, "r") as file:
+                include_text = file.read()
+            ntext += include_root(include_text)
+        else:
+            ntext += line + "\n"
+    return ntext
+
+
 class DataFormat(Enum):
     YAML = auto()
     JSON = auto()
 
     def parse_to_dict(self, text: str) -> Any:
         if self is DataFormat.YAML:
+            # handle root includes separately, pyyaml loader cannot do that
+            included = include_root(text)
+
             # _RaiseDuplicatesIncludeLoader extends yaml.SafeLoader, so this should be safe
             # https://python.land/data-processing/python-yaml#PyYAML_safe_load_vs_load
-            return renamed(yaml.load(text, Loader=_RaiseDuplicatesIncludeLoader))  # type: ignore
+            return renamed(yaml.load(included, Loader=_RaiseDuplicatesIncludeLoader))  # type: ignore
         if self is DataFormat.JSON:
             return renamed(json.loads(text, object_pairs_hook=_json_raise_duplicates))
         raise NotImplementedError(f"Parsing of format '{self}' is not implemented")