Skip to content

Commit b0b07a4

Browse files
authored
Merge pull request #29 from kompre:fix/graceful-no-files-exit
fix: exit gracefully when no files found
2 parents f487043 + 788bee2 commit b0b07a4

6 files changed

Lines changed: 123 additions & 12 deletions

File tree

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
# Task Proposal: Graceful Exit When No Files Found
2+
3+
## Original Objective
4+
When no .ipynb files (or .qmd files) are found to process, the CLI currently terminates with error code 1. This should be handled gracefully - just exit with code 0 since there's no work to do.
5+
6+
## Current Behavior
7+
The CLI exits with error code 1 in two scenarios:
8+
1. **No files found initially** (quarto_batch_convert.py:301-303): When input paths contain no files with the target extension
9+
2. **No files after regex filtering** (quarto_batch_convert.py:321-326): When regex pattern matches no files
10+
11+
Both cases print error messages and call `ctx.exit(1)`.
12+
13+
## Proposed Changes
14+
15+
### 1. Exit with Code 0 for "No Work to Do" Scenarios
16+
**File**: `src/quarto_batch_convert/quarto_batch_convert.py`
17+
18+
**Change 1** (lines 301-303):
19+
```python
20+
# Before:
21+
if not files:
22+
click.echo("Error: No files found to process")
23+
ctx.exit(1)
24+
25+
# After:
26+
if not files:
27+
click.echo("No files found to process")
28+
return # Exit gracefully with code 0
29+
```
30+
31+
**Change 2** (lines 321-326):
32+
```python
33+
# Before:
34+
if not files:
35+
if match_regex:
36+
click.echo(f"No files found matching the regex pattern: {match_regex}")
37+
else:
38+
click.echo("No files found to process")
39+
ctx.exit(1)
40+
41+
# After:
42+
if not files:
43+
if match_regex:
44+
click.echo(f"No files found matching the regex pattern: {match_regex}")
45+
else:
46+
click.echo("No files found to process")
47+
return # Exit gracefully with code 0
48+
```
49+
50+
### 2. Update Tests (if needed)
51+
**File**: `tests/test_quarto_batch_convert.py`
52+
53+
Check if any tests expect exit code 1 for "no files found" scenarios. Update them to expect code 0 instead.
54+
55+
## Implementation Steps
56+
57+
1. Read `src/quarto_batch_convert/quarto_batch_convert.py`
58+
2. Update lines 301-303: Remove "Error:" prefix, change `ctx.exit(1)` to `return`
59+
3. Update lines 321-326: Change `ctx.exit(1)` to `return`
60+
4. Read `tests/test_quarto_batch_convert.py` to check for affected tests
61+
5. Update any tests that assert exit code 1 for "no files found"
62+
6. Run test suite: `uv run pytest tests -v`
63+
7. Verify locally with test case: run CLI on empty directory
64+
65+
## Rationale
66+
67+
- **Exit code 0**: No files to process is not an error condition - it's a valid state where the tool has nothing to do
68+
- **Remove "Error:" prefix**: Since this isn't an error, the message shouldn't be labeled as such
69+
- **Graceful termination**: Tools that find no work shouldn't fail CI/CD pipelines or automated scripts
70+
- **Consistency**: Many Unix tools (grep, find, etc.) exit with 0 when finding no matches
71+
72+
## Testing Scenarios
73+
74+
1. Empty directory with `-r` flag
75+
2. Directory with files but wrong extension
76+
3. Regex pattern that matches no files
77+
4. Non-existent glob pattern
78+
79+
All should exit with code 0 and informative (non-error) message.
80+
81+
## Implementation Summary
82+
83+
**Status**: ✅ Completed
84+
85+
### Changes Made
86+
87+
1. **quarto_batch_convert.py:301-303** - Updated first exit point
88+
- Removed "Error:" prefix from message
89+
- Changed `ctx.exit(1)` to `return` for graceful exit
90+
91+
2. **quarto_batch_convert.py:321-326** - Updated second exit point
92+
- Changed `ctx.exit(1)` to `return` for graceful exit
93+
- Kept informative message about regex pattern
94+
95+
3. **test_quarto_batch_convert.py:128-145** - Updated test
96+
- Changed `test_no_match_found()` to expect exit code 0
97+
- Updated docstring to reflect graceful exit behavior
98+
99+
### Test Results
100+
All 17 tests passed successfully:
101+
- ✅ test_no_match_found now validates exit code 0
102+
- ✅ All other tests remain passing
103+
- ✅ Test suite completed in 7.79s
104+
105+
### Verification
106+
The CLI now exits gracefully (code 0) when:
107+
- No files with target extension are found in input paths
108+
- Regex pattern matches no files
109+
- Directory is empty
110+
111+
Non-error scenarios no longer fail CI/CD pipelines or automated scripts.

_todo/todo.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
## Active Tasks
44

5-
<!-- Add tasks here. When creating a proposal, move the task description to the proposal file -->
5+
1. **graceful-no-files-exit** - In progress in `pending/graceful-no-files-exit.md`
66

77
## Proposed Tasks (Awaiting Review)
88

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "quarto-batch-convert"
3-
version = "2025.9.1"
3+
version = "2025.9.2"
44
description = "Converts multiple Jupyter notebooks to Quarto documents at once"
55
readme = "README.md"
66
license = "MIT"

src/quarto_batch_convert/quarto_batch_convert.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -299,8 +299,8 @@ def convert_files(
299299

300300
# Check if any files were found
301301
if not files:
302-
click.echo("Error: No files found to process")
303-
ctx.exit(1)
302+
click.echo("No files found to process")
303+
return
304304

305305
if output_path is None:
306306
output_path = base_input_path
@@ -323,7 +323,7 @@ def convert_files(
323323
click.echo(f"No files found matching the regex pattern: {match_regex}")
324324
else:
325325
click.echo("No files found to process")
326-
ctx.exit(1)
326+
return
327327

328328
print(f"Found {len(files)} file(s) to be converted:\n")
329329
print(f"\n\t{files}\n")

tests/test_quarto_batch_convert.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -128,20 +128,20 @@ def test_invalid_regex_pattern() -> None:
128128
def test_no_match_found(setup_teardown_test_env: str) -> None:
129129
"""Test that a non-matching pattern results in no files being processed.
130130
131-
Verifies that when a regex pattern matches no files, the CLI exits with
132-
an error code and displays an appropriate message.
131+
Verifies that when a regex pattern matches no files, the CLI exits gracefully
132+
with exit code 0 and displays an appropriate message.
133133
134134
Args:
135135
setup_teardown_test_env: Path to the temporary test directory.
136136
"""
137137
runner = CliRunner()
138138
test_dir = setup_teardown_test_env
139-
139+
140140
input_files = glob.glob(test_dir + "/**/*", recursive=True)
141-
141+
142142
result = runner.invoke(quarto_batch_convert, [*input_files, "-m", "non_existent_pattern"])
143-
144-
assert result.exit_code != 0
143+
144+
assert result.exit_code == 0
145145
assert "No files found matching the regex pattern" in result.output
146146

147147
def test_prefix_option(setup_teardown_test_env: str) -> None:

uv.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)