Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 13 additions & 2 deletions src/uwtools/rocoto.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,16 @@
from time import sleep
from typing import TYPE_CHECKING, Any

from jinja2 import Environment, StrictUndefined, meta
from lxml import etree
from lxml.builder import E # type: ignore[import-not-found]
from lxml.etree import Element, SubElement, _Element

from uwtools.config.formats.yaml import YAMLConfig
from uwtools.config.jinja2 import unrendered
from uwtools.config.validator import validate_external as validate_yaml
from uwtools.exceptions import UWConfigError, UWError
from uwtools.logging import log
from uwtools.exceptions import UWConfigError, UWConfigRealizeError, UWError
from uwtools.logging import INDENT, log
from uwtools.utils.file import readable, resource_path, writable
from uwtools.utils.processing import run_shell_cmd

Expand Down Expand Up @@ -58,6 +60,15 @@ def realize(config: YAMLConfig | Path | None, output_file: Path | None = None) -
"""
rxml = _RocotoXML(config)
xml = str(rxml).strip()
if unrendered(xml):
log.error(xml)
log.error("Value(s) needed to render this XML are:")
for var in meta.find_undeclared_variables(
Environment(undefined=StrictUndefined).parse(xml)
):
log.error("%s%s", INDENT, var)
msg = "Rocoto XML could not be totally realized"
raise UWConfigRealizeError(msg)
if not validate_string(xml):
msg = "Internal error: Invalid Rocoto XML"
raise UWError(msg)
Expand Down
15 changes: 14 additions & 1 deletion src/uwtools/tests/test_rocoto.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

from uwtools import rocoto
from uwtools.config.formats.yaml import YAMLConfig
from uwtools.exceptions import UWConfigError, UWError
from uwtools.exceptions import UWConfigError, UWConfigRealizeError, UWError
from uwtools.tests.support import fixture_path, schema_validator

# Fixtures
Expand Down Expand Up @@ -88,6 +88,19 @@ def test_rocoto_realize__invalid_xml(assets):
rocoto.realize(config=cfgfile, output_file=outfile)


def test_rocoto_realize__unrendered_xml(assets, logged):
cfgfile, outfile = assets
template = "Hello {{ world }}."
with (
patch.object(rocoto, "_RocotoXML", return_value=template),
raises(UWConfigRealizeError, match=r"Rocoto XML could not be totally realized"),
):
rocoto.realize(config=cfgfile, output_file=outfile)
assert logged(template)
assert logged("Value(s) needed to render this XML are:")
assert logged("world")


def test_rocoto_validate__file_fail(validation_assets):
xml_file_bad, _, _, _ = validation_assets
assert rocoto.validate_file(xml_file=xml_file_bad) is False
Expand Down