Skip to content

Commit

Permalink
Repin iotaa and remove file() dependency on driver executables (ufs-c…
Browse files Browse the repository at this point in the history
  • Loading branch information
maddenp-noaa authored Apr 30, 2024
1 parent 4636617 commit ac9fb9c
Show file tree
Hide file tree
Showing 5 changed files with 49 additions and 19 deletions.
4 changes: 2 additions & 2 deletions recipe/meta.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"coverage =7.4.*",
"docformatter =1.7.*",
"f90nml =1.4.*",
"iotaa =0.8.*",
"iotaa =0.7.*",
"isort =5.13.*",
"jinja2 =3.1.*",
"jq =1.7.*",
Expand All @@ -24,7 +24,7 @@
],
"run": [
"f90nml =1.4.*",
"iotaa =0.8.*",
"iotaa =0.7.*",
"jinja2 =3.1.*",
"jsonschema =4.21.*",
"lxml =5.1.*",
Expand Down
2 changes: 1 addition & 1 deletion recipe/meta.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ requirements:
- pip
run:
- f90nml 1.4.*
- iotaa 0.8.*
- iotaa 0.7.*
- jinja2 3.1.*
- jsonschema 4.21.*
- lxml 5.1.*
Expand Down
11 changes: 2 additions & 9 deletions src/uwtools/drivers/driver.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
from uwtools.logging import log
from uwtools.scheduler import JobScheduler
from uwtools.utils.processing import execute
from uwtools.utils.tasks import file


class Driver(ABC):
Expand Down Expand Up @@ -85,10 +84,7 @@ def _run_via_batch_submission(self):
yield self._taskname("run via batch submission")
path = Path("%s.submit" % self._runscript_path)
yield asset(path, path.is_file)
yield [
self.provisioned_run_directory(),
file(Path(self._driver_config["execution"]["executable"])),
]
yield self.provisioned_run_directory()
self._scheduler.submit_job(runscript=self._runscript_path, submit_file=path)

@task
Expand All @@ -99,10 +95,7 @@ def _run_via_local_execution(self):
yield self._taskname("run via local execution")
path = self._rundir / f"done.{self._driver_name}"
yield asset(path, path.is_file)
yield [
self.provisioned_run_directory(),
file(Path(self._driver_config["execution"]["executable"])),
]
yield self.provisioned_run_directory()
cmd = "{x} >{x}.out 2>&1".format(x=self._runscript_path)
execute(cmd=cmd, cwd=self._rundir, log_output=True)

Expand Down
37 changes: 31 additions & 6 deletions src/uwtools/tests/utils/test_tasks.py
Original file line number Diff line number Diff line change
@@ -1,42 +1,67 @@
# pylint: disable=missing-function-docstring

import os
import stat
from unittest.mock import patch

from uwtools.utils import tasks

# Helpers


def ready(taskval):
return taskval.ready()


# Tests


def test_tasks_executable(tmp_path):
p = tmp_path / "program"
# Ensure that only our temp directory is on the path:
with patch.dict(os.environ, {"PATH": str(tmp_path)}, clear=True):
# Program does not exist:
assert not ready(tasks.executable(program=p))
# Program exists but is not executable:
p.touch()
assert not ready(tasks.executable(program=p))
# Program exists and is executable:
os.chmod(p, os.stat(p).st_mode | stat.S_IEXEC) # set executable bits
assert ready(tasks.executable(program=p))


def test_tasks_existing_missing(tmp_path):
path = tmp_path / "x"
assert not tasks.existing(path=path).ready() # type: ignore # pylint: disable=no-member
assert not ready(tasks.existing(path=path))


def test_tasks_existing_present_directory(tmp_path):
path = tmp_path / "directory"
path.mkdir()
assert tasks.existing(path=path).ready() # type: ignore # pylint: disable=no-member
assert ready(tasks.existing(path=path))


def test_tasks_existing_present_file(tmp_path):
path = tmp_path / "file"
path.touch()
assert tasks.existing(path=path).ready() # type: ignore # pylint: disable=no-member
assert ready(tasks.existing(path=path))


def test_tasks_existing_present_symlink(tmp_path):
path = tmp_path / "symlink"
path.symlink_to(os.devnull)
assert tasks.existing(path=path).ready() # type: ignore # pylint: disable=no-member
assert ready(tasks.existing(path=path))


def test_tasks_file_missing(tmp_path):
path = tmp_path / "file"
assert not tasks.file(path=path).ready() # type: ignore # pylint: disable=no-member
assert not ready(tasks.file(path=path))


def test_tasks_file_present(tmp_path):
path = tmp_path / "file"
path.touch()
assert tasks.file(path=path).ready() # type: ignore # pylint: disable=no-member
assert ready(tasks.file(path=path))


def test_tasks_filecopy(tmp_path):
Expand Down
14 changes: 13 additions & 1 deletion src/uwtools/utils/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,23 @@

import os
from pathlib import Path
from shutil import copy
from shutil import copy, which
from typing import Union

from iotaa import asset, external, task


@external
def executable(program: Union[Path, str]):
"""
An executable program located on the current path.
:param program: Name of or path to the program.
"""
yield "Executable program %s" % program
yield asset(program, lambda: bool(which(program)))


@external
def existing(path: Path):
"""
Expand Down

0 comments on commit ac9fb9c

Please sign in to comment.