Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

omnibus-2024-08-02 #557

Merged
merged 25 commits into from
Aug 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
85de46a
Squash-merge uw-632-schema-injection
maddenp-noaa Aug 2, 2024
e712d7e
Add py.typed
maddenp-noaa Aug 2, 2024
d970712
Explicitly import driver classes into uwtools.api.driver
maddenp-noaa Aug 2, 2024
f6a384f
Add cycle, leadtime properties
maddenp-noaa Aug 2, 2024
6fbff63
Update docstrings for config, config_full properties
maddenp-noaa Aug 2, 2024
e000422
Harmonize config, full_config, driver_config
maddenp-noaa Aug 2, 2024
c0980d8
Unit tets @ 100%
maddenp-noaa Aug 2, 2024
087c1a0
Simplify some Path() calls
maddenp-noaa Aug 2, 2024
3e4ff25
Simplify some Path() calls
maddenp-noaa Aug 2, 2024
f288751
Simplify some Path() calls
maddenp-noaa Aug 2, 2024
89ccb26
Use r/o .config[_full] where possible
maddenp-noaa Aug 2, 2024
e06a339
Use read-only .config in tests where possible
maddenp-noaa Aug 2, 2024
1758e5a
Merge branch 'main' into omnibus-2024-08-02
maddenp-noaa Aug 2, 2024
7a2dfcd
Formatting
maddenp-noaa Aug 2, 2024
1c30c5a
Use read-only .config in tests where possible
maddenp-noaa Aug 2, 2024
1969fd0
Factor out key-path walker
maddenp-noaa Aug 2, 2024
6342656
Add test stub
maddenp-noaa Aug 2, 2024
d9890bc
Use walk_key_path() in Assets ctor
maddenp-noaa Aug 2, 2024
3e7676d
Simplify
maddenp-noaa Aug 2, 2024
ed69710
Add unit tests
maddenp-noaa Aug 2, 2024
701ab4a
Tweak test
maddenp-noaa Aug 2, 2024
6e92d30
Remove some unnecessary mkdirs
maddenp-noaa Aug 2, 2024
fcaa1e4
Fix comment
maddenp-noaa Aug 2, 2024
bee089e
Undo unnecessary reordering to minimize diff
maddenp-noaa Aug 2, 2024
f233564
Add code comments about _config and _config_full
maddenp-noaa Aug 2, 2024
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
48 changes: 26 additions & 22 deletions src/uwtools/api/driver.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
API access to the ``uwtools`` driver base classes.
"""

import sys
from datetime import datetime, timedelta
from importlib import import_module
from importlib.util import module_from_spec, spec_from_file_location
Expand All @@ -11,6 +10,16 @@
from types import ModuleType
from typing import Optional, Type, Union

from uwtools.drivers.driver import ( # pylint: disable=unused-import
Assets,
AssetsCycleBased,
AssetsCycleLeadtimeBased,
AssetsTimeInvariant,
Driver,
DriverCycleBased,
DriverCycleLeadtimeBased,
DriverTimeInvariant,
)
maddenp-noaa marked this conversation as resolved.
Show resolved Hide resolved
from uwtools.drivers.support import graph
from uwtools.drivers.support import tasks as _tasks
from uwtools.logging import log
Expand Down Expand Up @@ -91,25 +100,6 @@ def tasks(module: str, classname: str) -> dict[str, str]:
return _tasks(class_)


_CLASSNAMES = [
"Assets",
"AssetsCycleBased",
"AssetsCycleLeadtimeBased",
"AssetsTimeInvariant",
"Driver",
"DriverCycleBased",
"DriverCycleLeadtimeBased",
"DriverTimeInvariant",
]


def _add_classes():
m = import_module("uwtools.drivers.driver")
for classname in _CLASSNAMES:
setattr(sys.modules[__name__], classname, getattr(m, classname))
__all__.append(classname)
maddenp-noaa marked this conversation as resolved.
Show resolved Hide resolved


def _get_driver_class(module: Union[Path, str], classname: str) -> Optional[Type]:
"""
Returns the driver class.
Expand Down Expand Up @@ -161,5 +151,19 @@ def _get_driver_module_implicit(module: str) -> Optional[ModuleType]:
return None


__all__: list[str] = [graph.__name__]
_add_classes()
__all__ = [
getattr(x, "__name__")
for x in (
Assets,
AssetsCycleBased,
AssetsCycleLeadtimeBased,
AssetsTimeInvariant,
Driver,
DriverCycleBased,
DriverCycleLeadtimeBased,
DriverTimeInvariant,
execute,
graph,
tasks,
)
]
maddenp-noaa marked this conversation as resolved.
Show resolved Hide resolved
44 changes: 29 additions & 15 deletions src/uwtools/config/tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,29 @@ def realize_config(
return input_obj.data


def walk_key_path(config: dict, key_path: list[str]) -> tuple[dict, str]:
"""
Navigate to the sub-config at the end of the path of given keys.

:param config: A config.
:param key_path: Path of keys to subsection of config file.
:return: The sub-config and a string representation of the key path.
"""
keys = []
pathstr = "<unknown>"
for key in key_path:
keys.append(key)
pathstr = " -> ".join(keys)
try:
subconfig = config[key]
except KeyError as e:
raise log_and_error(f"Bad config path: {pathstr}") from e
if not isinstance(subconfig, dict):
raise log_and_error(f"Value at {pathstr} must be a dictionary")
config = subconfig
return config, pathstr
maddenp-noaa marked this conversation as resolved.
Show resolved Hide resolved


# Private functions


Expand Down Expand Up @@ -138,25 +161,16 @@ def _ensure_format(

def _print_config_section(config: dict, key_path: list[str]) -> None:
"""
Descends into the config via the given keys, then prints the contents of the located subtree as
key=value pairs, one per line.
Prints the contents of the located subtree as key=value pairs, one per line.

:param config: A config.
:param key_path: Path of keys to subsection of config file.
"""
keys = []
current_path = "<unknown>"
for section in key_path:
keys.append(section)
current_path = " -> ".join(keys)
try:
subconfig = config[section]
except KeyError as e:
raise log_and_error(f"Bad config path: {current_path}") from e
if not isinstance(subconfig, dict):
raise log_and_error(f"Value at {current_path} must be a dictionary")
config = subconfig
config, pathstr = walk_key_path(config, key_path)
output_lines = []
for key, value in config.items():
if type(value) not in (bool, float, int, str):
raise log_and_error(f"Non-scalar value {value} found at {current_path}")
raise log_and_error(f"Non-scalar value {value} found at {pathstr}")
output_lines.append(f"{key}={value}")
print("\n".join(sorted(output_lines)))

Expand Down
10 changes: 4 additions & 6 deletions src/uwtools/drivers/cdeps.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ def atm_nml(self):
path = self._rundir / fn
yield asset(path, path.is_file)
yield None
path.parent.mkdir(parents=True, exist_ok=True)
maddenp-noaa marked this conversation as resolved.
Show resolved Hide resolved
self._model_namelist_file("atm_in", path)

@task
Expand All @@ -54,7 +53,7 @@ def atm_stream(self):
yield self._taskname(f"stream file {fn}")
path = self._rundir / fn
yield asset(path, path.is_file)
template_file = self._driver_config["atm_streams"]["template_file"]
template_file = self.config["atm_streams"]["template_file"]
maddenp-noaa marked this conversation as resolved.
Show resolved Hide resolved
yield file(path=Path(template_file))
self._model_stream_file("atm_streams", path, template_file)

Expand All @@ -79,7 +78,6 @@ def ocn_nml(self):
path = self._rundir / fn
yield asset(path, path.is_file)
yield None
path.parent.mkdir(parents=True, exist_ok=True)
self._model_namelist_file("ocn_in", path)

@task
Expand All @@ -91,7 +89,7 @@ def ocn_stream(self):
yield self._taskname(f"stream file {fn}")
path = self._rundir / fn
yield asset(path, path.is_file)
template_file = self._driver_config["ocn_streams"]["template_file"]
template_file = self.config["ocn_streams"]["template_file"]
yield file(path=Path(template_file))
self._model_stream_file("ocn_streams", path, template_file)

Expand All @@ -112,7 +110,7 @@ def _model_namelist_file(self, group: str, path: Path) -> None:
:param path: Path to write namelist to.
"""
self._create_user_updated_config(
config_class=NMLConfig, config_values=self._driver_config[group], path=path
config_class=NMLConfig, config_values=self.config[group], path=path
)

def _model_stream_file(self, group: str, path: Path, template_file: str) -> None:
Expand All @@ -126,7 +124,7 @@ def _model_stream_file(self, group: str, path: Path, template_file: str) -> None
_render(
input_file=Path(template_file),
output_file=path,
values_src=self._driver_config[group],
values_src=self.config[group],
)


Expand Down
4 changes: 2 additions & 2 deletions src/uwtools/drivers/chgres_cube.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ def namelist_file(self):
path = self._rundir / fn
yield asset(path, path.is_file)
input_files = []
namelist = self._driver_config[STR.namelist]
namelist = self.config[STR.namelist]
if base_file := namelist.get(STR.basefile):
input_files.append(base_file)
if update_values := namelist.get(STR.updatevalues):
Expand Down Expand Up @@ -84,7 +84,7 @@ def runscript(self):
yield None
envvars = {
"KMP_AFFINITY": "scatter",
"OMP_NUM_THREADS": self._driver_config.get(STR.execution, {}).get(STR.threads, 1),
"OMP_NUM_THREADS": self.config.get(STR.execution, {}).get(STR.threads, 1),
"OMP_STACKSIZE": "1024m",
}
self._write_runscript(path=path, envvars=envvars)
Expand Down
Loading
Loading