diff --git a/emrichen/context.py b/emrichen/context.py index 9ad5b9d..efb52b8 100644 --- a/emrichen/context.py +++ b/emrichen/context.py @@ -61,3 +61,25 @@ def add_variables(self, *variable_sources, **override_variables) -> None: self.update(yaml_document) self.update(override_variables) + + +class EnrichingProxy: + __slots__ = ('_context', '_target') + + def __init__(self, context, target): + self._context = context + self._target = target + + def __getitem__(self, key): + return EnrichingProxy( + context=self._context, + target=self._context.enrich(self._target[key]), + ) + + def __len__(self): + return len(self._target) + + @classmethod + def unwrap(cls, obj): + assert isinstance(obj, cls) + return obj._target diff --git a/emrichen/tags/lookup.py b/emrichen/tags/lookup.py index 106a507..eb35b60 100644 --- a/emrichen/tags/lookup.py +++ b/emrichen/tags/lookup.py @@ -3,7 +3,7 @@ import jsonpath_rw -from ..context import Context +from ..context import Context, EnrichingProxy from .base import BaseTag @@ -13,7 +13,10 @@ def parse_jsonpath(expr: str): def find_jsonpath_in_context(jsonpath_str: str, context: Context) -> List[jsonpath_rw.DatumInContext]: - return parse_jsonpath(jsonpath_str).find(context) + result = parse_jsonpath(jsonpath_str).find(EnrichingProxy(context, context)) + for datum in result: + datum.value = EnrichingProxy.unwrap(datum.value) + return result class Lookup(BaseTag): diff --git a/tests/test_lookup.py b/tests/test_lookup.py index 995ff9a..9590294 100644 --- a/tests/test_lookup.py +++ b/tests/test_lookup.py @@ -68,7 +68,6 @@ def test_lookup_no_match(): assert 'no matches for' in str(ei.value) -@pytest.mark.xfail def test_late_enrich(): template = Template.parse( ''' @@ -103,3 +102,17 @@ def test_lookup_enrich(): ''' ) assert template.enrich({}) == [{'should_contain_5': [5]}] + + +@pytest.mark.xfail +def test_recursive_data_structure(): + template = Template.parse(''' +!Defaults +x: + y: 5 + x: !Var x +--- +five: !Lookup x.y +also_five: !Lookup x.x.x.x.x.y +''') + assert template.enrich({}) == [{'five': 5, 'also_five': 5}]