Skip to content

Commit

Permalink
Improved chgres_cube logging & dot delimited key paths
Browse files Browse the repository at this point in the history
  • Loading branch information
Byrnetp committed Nov 26, 2024
1 parent 33e4c21 commit c6a6d56
Show file tree
Hide file tree
Showing 8 changed files with 20 additions and 38 deletions.
2 changes: 1 addition & 1 deletion src/uwtools/config/tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ def walk_key_path(config: dict, key_path: list[str]) -> tuple[dict, str]:
pathstr = "<unknown>"
for key in key_path:
keys.append(key)
pathstr = " -> ".join(keys)
pathstr = ".".join(keys)
try:
subconfig = config[key]
except KeyError as e:
Expand Down
2 changes: 1 addition & 1 deletion src/uwtools/config/validator.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ def validate(schema: dict, desc: str, config: dict) -> bool:
log_msg = "%s UW schema-validation error%s found in %s"
log_method(log_msg, len(errors), "" if len(errors) == 1 else "s", desc)
for error in errors:
log.error("Error at %s:", " -> ".join(str(k) for k in error.path))
log.error("Error at %s:", ".".join(str(k) for k in error.path))
log.error("%s%s", INDENT, error.message)
return not bool(errors)

Expand Down
25 changes: 8 additions & 17 deletions src/uwtools/drivers/chgres_cube.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ class ChgresCube(DriverCycleLeadtimeBased):
# Workflow tasks

@task
def namelist_file(self, log_path: bool = False):
def namelist_file(self):
"""
The namelist file.
"""
Expand All @@ -30,18 +30,13 @@ def namelist_file(self, log_path: bool = False):
path = self.rundir / fn
yield asset(path, path.is_file)
input_files = []
pathstr = ""
namelist = self.config[STR.namelist]
if base_file := namelist.get(STR.basefile):
if log_path:
pathstr = " -> ".join([STR.namelist, STR.basefile])
input_files.append((pathstr, base_file))
input_files.append((base_file, STR.basefile))
if update_values := namelist.get(STR.updatevalues):
config_files = update_values["config"]
for k in ["mosaic_file_target_grid", "varmap_file", "vcoord_file_target_grid"]:
if log_path:
pathstr = " -> ".join([STR.namelist, STR.updatevalues, "config", k])
input_files.append((pathstr, config_files[k]))
input_files.append((config_files[k], k))
for k in [
"atm_core_files_input_grid",
"atm_files_input_grid",
Expand All @@ -53,26 +48,22 @@ def namelist_file(self, log_path: bool = False):
if k in config_files:
grid_path = Path(config_files["data_dir_input_grid"])
v = config_files[k]
if log_path:
pathstr = " -> ".join([STR.namelist, STR.updatevalues, "config", k])
if isinstance(v, str):
input_files.append((pathstr, grid_path / v))
input_files.append((grid_path / v, k))
else:
input_files.extend([(pathstr, grid_path / f) for f in v])
input_files.extend([(grid_path / f, k) for f in v])
for k in [
"orog_files_input_grid",
"orog_files_target_grid",
]:
if k in config_files:
grid_path = Path(config_files[k.replace("files", "dir")])
v = config_files[k]
if log_path:
pathstr = " -> ".join([STR.namelist, STR.updatevalues, "config", k])
if isinstance(v, str):
input_files.append((pathstr, grid_path / v))
input_files.append((grid_path / v, k))
else:
input_files.extend([(pathstr, grid_path / f) for f in v])
yield [file(Path(input_file), pathstr) for pathstr, input_file in input_files]
input_files.extend([(grid_path / f, k) for f in v])
yield [file(Path(input_file), pathstr) for input_file, pathstr in input_files]
self._create_user_updated_config(
config_class=NMLConfig,
config_values=namelist,
Expand Down
2 changes: 1 addition & 1 deletion src/uwtools/fs.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ def _set_config_block(self) -> None:
for key in self._keys:
nav.append(key)
if key not in cfg:
raise UWConfigError("Failed following YAML key(s): %s" % " -> ".join(nav))
raise UWConfigError("Failed following YAML key(s): %s" % ".".join(nav))
log.debug("Following config key '%s'", key)
cfg = cfg[key]
if not isinstance(cfg, dict):
Expand Down
6 changes: 3 additions & 3 deletions src/uwtools/tests/config/test_tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -556,17 +556,17 @@ def test_realize_config_values_needed_yaml(caplog):
def test_walk_key_path_fail_bad_key_path():
with raises(UWError) as e:
tools.walk_key_path({"a": {"b": {"c": "cherry"}}}, ["a", "x"])
assert str(e.value) == "Bad config path: a -> x"
assert str(e.value) == "Bad config path: a.x"


def test_walk_key_path_fail_bad_leaf_value():
with raises(UWError) as e:
tools.walk_key_path({"a": {"b": {"c": "cherry"}}}, ["a", "b", "c"])
assert str(e.value) == "Value at a -> b -> c must be a dictionary"
assert str(e.value) == "Value at a.b.c must be a dictionary"


def test_walk_key_path_pass():
expected = ({"c": "cherry"}, "a -> b")
expected = ({"c": "cherry"}, "a.b")
assert tools.walk_key_path({"a": {"b": {"c": "cherry"}}}, ["a", "b"]) == expected


Expand Down
12 changes: 1 addition & 11 deletions src/uwtools/tests/drivers/test_chgres_cube.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,17 +144,7 @@ def test_ChgresCube_namelist_file_missing_base_file(caplog, driverobj):
driverobj._config["namelist"]["base_file"] = base_file
path = Path(refs(driverobj.namelist_file()))
assert not path.exists()
assert regex_logged(caplog, "missing.nml: State: Not Ready (external asset)")


def test_ChgresCube_namelist_file_missing_base_file_path_logging(caplog, driverobj):
log.setLevel(logging.DEBUG)
base_file = str(Path(driverobj.config["rundir"], "missing.nml"))
driverobj._config["namelist"]["base_file"] = base_file
path = Path(refs(driverobj.namelist_file(log_path=True)))
assert not path.exists()
assert regex_logged(caplog, "namelist -> base_file: ")
assert regex_logged(caplog, "missing.nml: State: Not Ready (external asset)")
assert regex_logged(caplog, "missing.nml (base_file): State: Not Ready (external asset)")


def test_ChgresCube_output(driverobj):
Expand Down
2 changes: 1 addition & 1 deletion src/uwtools/tests/test_fs.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ def test_Stager__config_block_fail_bad_key_path(assets, source):
config = cfgdict if source == "dict" else cfgfile
with raises(UWConfigError) as e:
ConcreteStager(target_dir=dstdir, config=config, keys=["a", "x"])
assert str(e.value) == "Failed following YAML key(s): a -> x"
assert str(e.value) == "Failed following YAML key(s): a.x"


@mark.parametrize("val", [None, True, False, "str", 42, 3.14, [], tuple()])
Expand Down
7 changes: 4 additions & 3 deletions src/uwtools/utils/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,15 @@ def existing(path: Path):


@external
def file(path: Path, pathstr: str = ""):
def file(path: Path, context: str = ""):
"""
An existing file or symlink to an existing file.
:param path: Path to the file.
:param context: Optional additional context for the file.
"""
prefix = pathstr + ": " if pathstr else ""
yield "%sFile %s" % (prefix, path)
suffix = " (" + context + ")" if context else ""
yield "File %s%s" % (path, suffix)
yield asset(path, path.is_file)


Expand Down

0 comments on commit c6a6d56

Please sign in to comment.