diff --git a/cylc/flow/network/scan.py b/cylc/flow/network/scan.py index 7c8116b1a70..c929c2079a7 100644 --- a/cylc/flow/network/scan.py +++ b/cylc/flow/network/scan.py @@ -238,7 +238,10 @@ def _scan_subdirs(listing: List[Path], depth: int) -> None: ) # perform the first directory listing - scan_dir_listing = await scandir(scan_dir) + try: + scan_dir_listing = await scandir(scan_dir) + except FileNotFoundError: + return if scan_dir != cylc_run_dir and dir_is_flow(scan_dir_listing): # If the scan_dir itself is a workflow run dir, yield nothing return diff --git a/tests/functional/cylc-clean/00-basic.t b/tests/functional/cylc-clean/00-basic.t index f7fd40c1700..1f4cec84984 100644 --- a/tests/functional/cylc-clean/00-basic.t +++ b/tests/functional/cylc-clean/00-basic.t @@ -21,7 +21,7 @@ if ! command -v 'tree' >'/dev/null'; then skip_all '"tree" command not available' fi -set_test_number 8 +set_test_number 10 # Generate random name for symlink dirs to avoid any clashes with other tests SYM_NAME="$(mktemp -u)" @@ -94,7 +94,7 @@ ${TEST_DIR}/${SYM_NAME}/work/cylc-run/${CYLC_TEST_REG_BASE} \`-- work __TREE__ # ----------------------------------------------------------------------------- -TEST_NAME="cylc-clean" +TEST_NAME="clean" run_ok "$TEST_NAME" cylc clean "$WORKFLOW_NAME" dump_std "$TEST_NAME" # ----------------------------------------------------------------------------- @@ -109,5 +109,11 @@ ${TEST_DIR}/${SYM_NAME}/log/cylc-run/${CYLC_TEST_REG_BASE} \`-- leave-me-alone __TREE__ # ----------------------------------------------------------------------------- +TEST_NAME="clean-non-exist" +run_ok "$TEST_NAME" cylc clean "$WORKFLOW_NAME" +dump_std "$TEST_NAME" +cmp_ok "${TEST_NAME}.stdout" << __EOF__ +INFO - No directory to clean at ${WORKFLOW_RUN_DIR} +__EOF__ +# ----------------------------------------------------------------------------- purge -exit diff --git a/tests/integration/test_async_util.py b/tests/integration/test_async_util.py deleted file mode 100644 index 6c9bfaa565e..00000000000 --- a/tests/integration/test_async_util.py +++ /dev/null @@ -1,41 +0,0 @@ -# THIS FILE IS PART OF THE CYLC WORKFLOW ENGINE. -# Copyright (C) NIWA & British Crown (Met Office) & Contributors. -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -from pathlib import Path -from shutil import rmtree - -import pytest - -from cylc.flow.async_util import scandir - - -@pytest.fixture() -def directory(tmp_path): - """A directory with two files and a symlink.""" - (tmp_path / 'a').touch() - (tmp_path / 'b').touch() - (tmp_path / 'c').symlink_to(tmp_path / 'b') - yield tmp_path - rmtree(tmp_path) - - -async def test_scandir(directory): - """It should list directory contents (including symlinks).""" - assert sorted(await scandir(directory)) == [ - Path(directory, 'a'), - Path(directory, 'b'), - Path(directory, 'c') - ] diff --git a/tests/integration/test_scan.py b/tests/integration/test_scan.py index cef762c394e..94edbfc9b29 100644 --- a/tests/integration/test_scan.py +++ b/tests/integration/test_scan.py @@ -250,6 +250,13 @@ async def test_scan_nasty_symlinks(run_dir_with_nasty_symlinks): ] +async def test_scan_non_exist(tmp_path: Path): + """Calling scan() on a scan_dir that doesn't exist should not raise.""" + assert await listify( + scan(scan_dir=(tmp_path / 'HORSE')) + ) == [] + + async def test_is_active(sample_run_dir): """It should filter flows by presence of a contact file.""" # running flows diff --git a/tests/unit/test_async_util.py b/tests/unit/test_async_util.py index 13cda504b48..17823817dbe 100644 --- a/tests/unit/test_async_util.py +++ b/tests/unit/test_async_util.py @@ -16,13 +16,15 @@ import asyncio import logging +from pathlib import Path from random import random import pytest from cylc.flow.async_util import ( pipe, - asyncqgen + asyncqgen, + scandir, ) LOG = logging.getLogger('test') @@ -238,3 +240,23 @@ async def test_asyncqgen(): ret.append(item) assert ret == [1, 2, 3] + + +async def test_scandir(tmp_path: Path): + """It should list directory contents (including symlinks).""" + (tmp_path / 'a').touch() + (tmp_path / 'b').touch() + (tmp_path / 'c').symlink_to(tmp_path / 'b') + + assert sorted(await scandir(tmp_path)) == [ + Path(tmp_path, 'a'), + Path(tmp_path, 'b'), + Path(tmp_path, 'c') + ] + + +async def test_scandir_non_exist(tmp_path: Path): + """scandir() should raise FileNotFoundError if called on a path that + doesn't exist.""" + with pytest.raises(FileNotFoundError): + await scandir(tmp_path / 'HORSE')