11import os
2+ import textwrap
23from collections import defaultdict
34from pathlib import Path
45from typing import Any , Literal , Iterator , Tuple , Callable
@@ -47,6 +48,11 @@ def load_jinja_yaml_configs(
4748 :param file_extensions: File extensions to use. Defaults to `{'.yml', '.yaml'}`. The leading dot is ignored.
4849 """
4950
51+ custom_filters = custom_filters or {}
52+ for func in _FILTERS :
53+ if func .__name__ not in custom_filters :
54+ custom_filters [func .__name__ ] = func
55+
5056 namespace_files : dict [str , list [Path ]] = defaultdict (list )
5157 for namespace , file_path in _iter_files_with_namespaces (Path (base_path ), file_extensions or {".yml" , ".yaml" }):
5258 namespace_files [namespace ].append (file_path )
@@ -94,7 +100,7 @@ def load_jinja_yaml_configs(
94100 return result
95101
96102
97- def _iter_files_with_namespaces (base_path : Path , extensions : list [str ]) -> Iterator [Tuple [str , Path ]]:
103+ def _iter_files_with_namespaces (base_path : Path , extensions : set [str ]) -> Iterator [Tuple [str , Path ]]:
98104 """Iterate (namespace, path) tuples for every YAML file in the specified path.
99105
100106 Namespaces are determined by the file's top dir or by its name before any double underscores.
@@ -108,3 +114,35 @@ def _iter_files_with_namespaces(base_path: Path, extensions: list[str]) -> Itera
108114 rel_path = file_path .relative_to (base_path )
109115 namespace = rel_path .parts [0 ] if len (rel_path .parts ) > 1 else file_path .stem .split ("__" )[0 ]
110116 yield namespace , file_path
117+
118+
119+ class _NotSet :
120+ pass
121+
122+
123+ class _Filters :
124+ """Built-in jinja filters."""
125+
126+ @staticmethod
127+ def to_yaml (
128+ arg : Any ,
129+ * ,
130+ indent : int = 0 ,
131+ if_none : Any | None = _NotSet ,
132+ if_falsy : Any | None = _NotSet ,
133+ ) -> str :
134+ if arg is None and if_none is not _NotSet :
135+ arg = if_none
136+
137+ if not arg and if_falsy is not _NotSet :
138+ arg = if_falsy
139+
140+ encoded = yaml .safe_dump (arg ).removesuffix ("\n " ).removesuffix ("\n ..." )
141+
142+ if prefix := indent * " " :
143+ encoded = textwrap .indent (encoded , prefix ).removeprefix (prefix )
144+
145+ return encoded
146+
147+
148+ _FILTERS = (_Filters .to_yaml ,)
0 commit comments