Ejemplo n.º 1
0
def _update_obj(
    obj: JsonType,
    key: str,
    value: JsonType,
    params: Dict[str, Any],
    defs: Dict[str, Def],
) -> None:
    if not isinstance(obj, dict):
        raise YATLSyntaxError(f"Cannot add field {key} to non-object")
    interpolated_key = render_interpolation(key, params)
    obj[interpolated_key] = render_from_obj(value, params, defs)
Ejemplo n.º 2
0
def _parse_filename(filename: JsonType, params: Dict[str, Any], load_type: str) -> str:
    if not isinstance(filename, str):
        raise YATLSyntaxError(
            f"{load_type} must be given a string or list of strings: {filename}"
        )
    filename = render_interpolation(filename, params)
    if not isinstance(filename, str):
        raise YATLSyntaxError(
            f"{load_type} directive must be given a string or list of strings: {filename}"
        )
    return filename
Ejemplo n.º 3
0
def test_render_interpolation():
    assert (render_interpolation(".(foo) and .(bar)", {
        "foo": "abc",
        "bar": "xyz"
    }) == "abc and xyz")
Ejemplo n.º 4
0
def test_render_interpolation_dot():
    assert render_interpolation(".", {}) == "."
Ejemplo n.º 5
0
def test_render_interpolation_incomplete():
    with pytest.raises(YATLSyntaxError):
        render_interpolation(".(", {})
Ejemplo n.º 6
0
def test_render_interpolation_escape():
    assert render_interpolation(r"\.(foo)", {"foo": "abc"}) == r"\.(foo)"
Ejemplo n.º 7
0
def render_from_obj(  # noqa: C901
    obj: JsonType, params: Dict[str, Any], defs: Dict[str, Def]
) -> JsonType:
    if isinstance(obj, dict):
        defaults_obj: JsonType = None
        rendered_obj: JsonType = {}
        last_if = None

        for key, value in obj.items():
            if isinstance(key, str) and key.startswith("."):
                # Note, elif and else require Python 3.7+ or a custom YAML loader to preserve key order.
                if _is_if(key):
                    rendered_obj, last_if = _render_if(
                        key, value, params, defs, rendered_obj
                    )
                elif _is_elif(key):
                    if last_if is None:
                        raise YATLSyntaxError(f"elif does not follow if: {key}")
                    if last_if is False:
                        rendered_obj, last_if = _render_if(
                            key, value, params, defs, rendered_obj
                        )
                elif key == ".else":
                    if last_if is None:
                        raise YATLSyntaxError(f"else does not follow if: {key}")
                    if last_if is False:
                        rendered_obj = _render_else(
                            key, value, params, defs, rendered_obj
                        )
                else:
                    last_if = None
                    if key == ".load":
                        rendered_obj = _render_load(value, params, defs, rendered_obj)
                    elif key == ".load_defaults_from":
                        defaults_obj = _load_defaults(value, params, defs)
                    elif _is_for(key):
                        rendered_obj = _render_for(
                            key, value, params, defs, rendered_obj
                        )
                    elif _is_def(key):
                        _store_def(key, value, defs)
                    elif _is_use(key):
                        rendered_obj = _render_use(
                            key, value, params, defs, rendered_obj
                        )
                    else:
                        _update_obj(rendered_obj, key, value, params, defs)
            else:
                last_if = None
                _update_obj(rendered_obj, key, value, params, defs)

        if defaults_obj:
            rendered_obj = _deep_merge_dicts(defaults_obj, rendered_obj)  # type: ignore

        return rendered_obj
    elif isinstance(obj, list):
        rendered_obj = []
        for elem in obj:
            rendered_elem = render_from_obj(elem, params, defs)
            if _can_extend_list(elem, rendered_elem):
                # Convert rendered_elem to [] if it's {}
                rendered_obj.extend(rendered_elem or [])  # type: ignore
            else:
                rendered_obj.append(rendered_elem)
        return rendered_obj
    elif isinstance(obj, str):
        return render_interpolation(obj, params)
    else:
        return obj