Implement CLI: walk parent directory, --dry-run, --verbose #9

Closed
opened 2026-06-17 08:57:03 +00:00 by coding-agent-marvin8 · 2 comments
coding-agent-marvin8 commented 2026-06-17 08:57:03 +00:00 (Migrated from codeberg.org)

The sub2pod CLI entry point (src/sub2pod/cli.py) is currently a skeleton with an empty cyclopts App. This issue tracks wiring it up to the existing business logic.

The CLI should:

  • Accept a parent directory and a base URL as required positional arguments
  • Walk the parent directory and generate one feed.xml per channel subdirectory (directories containing tvshow.nfo)
  • Support a --dry-run flag that prints the feed.xml paths that would be written without actually writing them
  • Support a --verbose flag that logs per-episode information during processing
  • Silently skip subdirectories that do not contain a tvshow.nfo file
The sub2pod CLI entry point (src/sub2pod/cli.py) is currently a skeleton with an empty cyclopts App. This issue tracks wiring it up to the existing business logic. The CLI should: - Accept a parent directory and a base URL as required positional arguments - Walk the parent directory and generate one feed.xml per channel subdirectory (directories containing tvshow.nfo) - Support a --dry-run flag that prints the feed.xml paths that would be written without actually writing them - Support a --verbose flag that logs per-episode information during processing - Silently skip subdirectories that do not contain a tvshow.nfo file
coding-agent-marvin8 commented 2026-06-17 08:57:19 +00:00 (Migrated from codeberg.org)

Findings

All business logic is already complete and tested:

  • in nfo.py
  • in discovery.py
  • in feed.py

The full pipeline from directory → feed.xml is already exercised in test_feed.py.

Plan of attack

Signature — cyclopts v4.x: non-keyword-only params become positional args, keyword-only (after *) become flags:

@app.default
def main(parent_dir: Path, base_url: str, *, dry_run: bool = False, verbose: bool = False) -> None:

Logic:

  1. Collect sorted subdirs of parent_dir that contain tvshow.nfo
  2. For each: parse channel NFO → discover episodes → optionally log them → write or print the feed path

Tests (TDD — tests written before implementation):

  • normal run writes feed.xml
  • --dry-run prints path, does not write file
  • --verbose lists episode titles in stdout
  • --dry-run + --verbose compose correctly
  • dirs without tvshow.nfo are skipped
  • multiple channel dirs processed in one pass

Branch: feat/issue-9-cli

Commits:

  1. :white_check_mark: add failing tests for Phase 5 CLI
  2. :sparkles: implement CLI — parent dir walk, --dry-run, --verbose
  3. :memo: mark Phase 5 items complete in ROADMAP.md
## Findings All business logic is already complete and tested: - in nfo.py - in discovery.py - in feed.py The full pipeline from directory → feed.xml is already exercised in test_feed.py. ## Plan of attack **Signature** — cyclopts v4.x: non-keyword-only params become positional args, keyword-only (after `*`) become flags: ```python @app.default def main(parent_dir: Path, base_url: str, *, dry_run: bool = False, verbose: bool = False) -> None: ``` **Logic**: 1. Collect sorted subdirs of `parent_dir` that contain `tvshow.nfo` 2. For each: parse channel NFO → discover episodes → optionally log them → write or print the feed path **Tests** (TDD — tests written before implementation): - normal run writes feed.xml - `--dry-run` prints path, does not write file - `--verbose` lists episode titles in stdout - `--dry-run + --verbose` compose correctly - dirs without tvshow.nfo are skipped - multiple channel dirs processed in one pass **Branch**: `feat/issue-9-cli` **Commits**: 1. `:white_check_mark: add failing tests for Phase 5 CLI` 2. `:sparkles: implement CLI — parent dir walk, --dry-run, --verbose` 3. `:memo: mark Phase 5 items complete in ROADMAP.md`
coding-agent-marvin8 commented 2026-06-17 08:57:48 +00:00 (Migrated from codeberg.org)

Findings

All business logic is already complete and tested:

  • parse_channel_nfo(path) -> ChannelInfo in nfo.py
  • discover_episodes(channel_dir) -> list[Episode] in discovery.py
  • write_feed(channel_dir, channel_info, episodes, base_url) -> Path in feed.py

The full pipeline from directory -> feed.xml is already exercised in test_feed.py.

Plan of attack

Signature — cyclopts v4.x: non-keyword-only params become positional args, keyword-only (after *) become flags:

@app.default
def main(parent_dir: Path, base_url: str, *, dry_run: bool = False, verbose: bool = False) -> None:

Logic:

  1. Collect sorted subdirs of parent_dir that contain tvshow.nfo
  2. For each: parse channel NFO -> discover episodes -> optionally log them -> write or print the feed path

Tests (TDD — tests written before implementation):

  • normal run writes feed.xml
  • --dry-run prints path, does not write file
  • --verbose lists episode titles in stdout
  • --dry-run + --verbose compose correctly
  • dirs without tvshow.nfo are skipped
  • multiple channel dirs processed in one pass

Branch: feat/issue-9-cli

Commits:

  1. :white_check_mark: add failing tests for Phase 5 CLI
  2. :sparkles: implement CLI — parent dir walk, --dry-run, --verbose
  3. :memo: mark Phase 5 items complete in ROADMAP.md
## Findings All business logic is already complete and tested: - `parse_channel_nfo(path) -> ChannelInfo` in nfo.py - `discover_episodes(channel_dir) -> list[Episode]` in discovery.py - `write_feed(channel_dir, channel_info, episodes, base_url) -> Path` in feed.py The full pipeline from directory -> feed.xml is already exercised in test_feed.py. ## Plan of attack **Signature** — cyclopts v4.x: non-keyword-only params become positional args, keyword-only (after `*`) become flags: ```python @app.default def main(parent_dir: Path, base_url: str, *, dry_run: bool = False, verbose: bool = False) -> None: ``` **Logic**: 1. Collect sorted subdirs of `parent_dir` that contain `tvshow.nfo` 2. For each: parse channel NFO -> discover episodes -> optionally log them -> write or print the feed path **Tests** (TDD — tests written before implementation): - normal run writes feed.xml - `--dry-run` prints path, does not write file - `--verbose` lists episode titles in stdout - `--dry-run + --verbose` compose correctly - dirs without tvshow.nfo are skipped - multiple channel dirs processed in one pass **Branch**: `feat/issue-9-cli` **Commits**: 1. `:white_check_mark: add failing tests for Phase 5 CLI` 2. `:sparkles: implement CLI — parent dir walk, --dry-run, --verbose` 3. `:memo: mark Phase 5 items complete in ROADMAP.md`
Sign in to join this conversation.
No labels
No milestone
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Reference
marvin8/sub2pod#9
No description provided.