Skip to content

Commit

Permalink
Return assets from driver invocation (#685)
Browse files Browse the repository at this point in the history
  • Loading branch information
maddenp-noaa authored Jan 16, 2025
1 parent f776e48 commit ab7c70a
Show file tree
Hide file tree
Showing 5 changed files with 40 additions and 33 deletions.
1 change: 1 addition & 0 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
nitpick_ignore = [
("py:class", "Path"),
("py:class", "f90nml.Namelist"),
("py:class", "iotaa.Asset"),
]
numfig = True
numfig_format = {"figure": "Figure %s"}
Expand Down
42 changes: 21 additions & 21 deletions docs/sections/user_guide/cli/tools/config/validate-verbose.out
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
[2025-01-05T21:15:07] DEBUG Command: uw config validate --schema-file schema.jsonschema --input-file values.yaml --verbose
[2025-01-05T21:15:07] DEBUG Using schema file: schema.jsonschema
[2025-01-05T21:15:07] DEBUG [dereference] Dereferencing, current value:
[2025-01-05T21:15:07] DEBUG [dereference] values:
[2025-01-05T21:15:07] DEBUG [dereference] greeting: Hello
[2025-01-05T21:15:07] DEBUG [dereference] recipient: World
[2025-01-05T21:15:07] DEBUG [dereference] Rendering: values
[2025-01-05T21:15:07] DEBUG [dereference] Rendered: values
[2025-01-05T21:15:07] DEBUG [dereference] Rendering: greeting
[2025-01-05T21:15:07] DEBUG [dereference] Rendered: greeting
[2025-01-05T21:15:07] DEBUG [dereference] Rendering: Hello
[2025-01-05T21:15:07] DEBUG [dereference] Rendered: Hello
[2025-01-05T21:15:07] DEBUG [dereference] Rendering: recipient
[2025-01-05T21:15:07] DEBUG [dereference] Rendered: recipient
[2025-01-05T21:15:07] DEBUG [dereference] Rendering: World
[2025-01-05T21:15:07] DEBUG [dereference] Rendered: World
[2025-01-05T21:15:07] DEBUG [dereference] Dereferencing, final value:
[2025-01-05T21:15:07] DEBUG [dereference] values:
[2025-01-05T21:15:07] DEBUG [dereference] greeting: Hello
[2025-01-05T21:15:07] DEBUG [dereference] recipient: World
[2025-01-05T21:15:07] INFO 0 schema-validation errors found in config
[2025-01-15T20:22:34] DEBUG Command: uw config validate --schema-file schema.jsonschema --input-file values.yaml --verbose
[2025-01-15T20:22:34] DEBUG [dereference] Dereferencing, current value:
[2025-01-15T20:22:34] DEBUG [dereference] values:
[2025-01-15T20:22:34] DEBUG [dereference] greeting: Hello
[2025-01-15T20:22:34] DEBUG [dereference] recipient: World
[2025-01-15T20:22:34] DEBUG [dereference] Rendering: values
[2025-01-15T20:22:34] DEBUG [dereference] Rendered: values
[2025-01-15T20:22:34] DEBUG [dereference] Rendering: greeting
[2025-01-15T20:22:34] DEBUG [dereference] Rendered: greeting
[2025-01-15T20:22:34] DEBUG [dereference] Rendering: Hello
[2025-01-15T20:22:34] DEBUG [dereference] Rendered: Hello
[2025-01-15T20:22:34] DEBUG [dereference] Rendering: recipient
[2025-01-15T20:22:34] DEBUG [dereference] Rendered: recipient
[2025-01-15T20:22:34] DEBUG [dereference] Rendering: World
[2025-01-15T20:22:34] DEBUG [dereference] Rendered: World
[2025-01-15T20:22:34] DEBUG [dereference] Dereferencing, final value:
[2025-01-15T20:22:34] DEBUG [dereference] values:
[2025-01-15T20:22:34] DEBUG [dereference] greeting: Hello
[2025-01-15T20:22:34] DEBUG [dereference] recipient: World
[2025-01-15T20:22:34] DEBUG Using schema file: schema.jsonschema
[2025-01-15T20:22:34] INFO 0 schema-validation errors found in config
18 changes: 11 additions & 7 deletions src/uwtools/api/execute.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,17 @@
from types import ModuleType
from typing import Optional, Type, Union

from iotaa import Asset

from uwtools.config.support import YAMLKey
from uwtools.drivers.support import graph
from uwtools.drivers.support import tasks as _tasks
from uwtools.logging import log
from uwtools.strings import STR
from uwtools.utils.api import ensure_data_source

_AssetsT = Optional[Union[Asset, list[Asset], dict[str, Asset]]]


def execute(
module: Union[Path, str],
Expand All @@ -31,7 +35,7 @@ def execute(
graph_file: Optional[Union[Path, str]] = None,
key_path: Optional[list[YAMLKey]] = None,
stdin_ok: Optional[bool] = False,
) -> bool:
) -> _AssetsT:
"""
Execute a driver task.
Expand All @@ -51,23 +55,23 @@ def execute(
:param graph_file: Write Graphviz DOT output here.
:param key_path: Path of keys to config block to use.
:param stdin_ok: OK to read from stdin?
:return: ``True`` if task completes without raising an exception.
:return: The assets yielded by the task, if it completes without raising an exception.
"""
class_, module_path = _get_driver_class(module, classname)
if not class_:
return False
return None
assert module_path is not None
args = dict(locals())
accepted = set(getfullargspec(class_).args)
non_optional = {STR.cycle, STR.leadtime}
for arg in sorted([STR.batch, *non_optional]):
if args.get(arg) and arg not in accepted:
log.error("%s does not accept argument '%s'", classname, arg)
return False
return None
for arg in sorted(non_optional):
if arg in accepted and args[arg] is None:
log.error("%s requires argument '%s'", classname, arg)
return False
return None
kwargs = dict(
config=ensure_data_source(config, bool(stdin_ok)),
dry_run=dry_run,
Expand All @@ -80,11 +84,11 @@ def execute(
kwargs[arg] = args[arg]
driverobj = class_(**kwargs)
log.debug("Instantiated %s with: %s", classname, kwargs)
getattr(driverobj, task)()
assets: _AssetsT = getattr(driverobj, task)()
if graph_file:
with open(graph_file, "w", encoding="utf-8") as f:
print(graph(), file=f)
return True
return assets


def tasks(module: Union[Path, str], classname: str) -> dict[str, str]:
Expand Down
3 changes: 2 additions & 1 deletion src/uwtools/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,7 @@ def _dispatch_execute(args: Args) -> bool:
:param args: Parsed command-line args.
"""
return uwtools.api.execute.execute(
assets = uwtools.api.execute.execute(
classname=args[STR.classname],
module=args[STR.module],
task=args[STR.task],
Expand All @@ -303,6 +303,7 @@ def _dispatch_execute(args: Args) -> bool:
batch=args[STR.batch],
stdin_ok=True,
)
return bool(assets)


# Mode fs
Expand Down
9 changes: 5 additions & 4 deletions src/uwtools/tests/api/test_execute.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from types import SimpleNamespace as ns
from unittest.mock import patch

from iotaa import refs
from pytest import fixture, mark, raises

from uwtools.api import execute
Expand Down Expand Up @@ -46,7 +47,7 @@ def kwargs(args):
@mark.parametrize("key,val", [("batch", True), ("leadtime", 6)])
def test_execute_fail_bad_args(caplog, key, kwargs, val):
kwargs.update({"cycle": dt.datetime.now(), key: val})
assert execute.execute(**kwargs) is False
assert execute.execute(**kwargs) is None
assert logged(caplog, f"TestDriver does not accept argument '{key}'")


Expand All @@ -69,15 +70,15 @@ def test_execute_pass(caplog, kwargs, remove, tmp_path):
graph_code = "DOT code"
kwargs["graph_file"] = graph_file
with patch.object(execute, "graph", return_value=graph_code):
assert execute.execute(**kwargs) is True
assert refs(execute.execute(**kwargs)) == 42
assert regex_logged(caplog, "Instantiated %s with" % kwargs["classname"])
with open(graph_file, "r", encoding="utf-8") as f:
assert f.read().strip() == graph_code


def test_execute_fail_cannot_load_driver_class(kwargs):
kwargs["module"] = "bad_module_name"
assert execute.execute(**kwargs) is False
assert execute.execute(**kwargs) is None


def test_tasks_fail(args, caplog, tmp_path):
Expand All @@ -91,7 +92,7 @@ def test_tasks_fail(args, caplog, tmp_path):

def test_tasks_fail_no_cycle(args, caplog, kwargs):
log.setLevel(logging.DEBUG)
assert execute.execute(**kwargs) is False
assert execute.execute(**kwargs) is None
assert logged(caplog, "%s requires argument '%s'" % (args.classname, "cycle"))


Expand Down

0 comments on commit ab7c70a

Please sign in to comment.