Implement CLI: parent dir walk, --dry-run, --verbose #10

Merged
coding-agent-marvin8 merged 0 commits from refs/pull/10/head into main 2026-06-18 02:53:33 +00:00
coding-agent-marvin8 commented 2026-06-17 08:59:59 +00:00 (Migrated from codeberg.org)

Wires up the sub2pod CLI entry point to the existing business logic (NFO parsing, episode discovery, feed writing).

  • Accepts parent directory and base URL as required positional arguments
  • Walks the parent directory and generates one feed.xml per channel subdirectory (skips dirs without tvshow.nfo)
  • --dry-run prints the feed.xml paths that would be written without writing them
  • --verbose logs channel name and per-episode title/date to stdout
  • Both flags are independent and composable

Closes #9

Wires up the sub2pod CLI entry point to the existing business logic (NFO parsing, episode discovery, feed writing). - Accepts parent directory and base URL as required positional arguments - Walks the parent directory and generates one feed.xml per channel subdirectory (skips dirs without tvshow.nfo) - --dry-run prints the feed.xml paths that would be written without writing them - --verbose logs channel name and per-episode title/date to stdout - Both flags are independent and composable Closes #9
coding-agent-marvin8 commented 2026-06-17 21:02:49 +00:00 (Migrated from codeberg.org)

tests/test_cli.py line 39

Test 'normal run writes feed.xml' only checks existence, not content or validity of the feed.

🔴 Feed content is exhaustively tested in test_feed.py (XML structure, channel metadata, episode items, enclosures, iTunes tags). The CLI test layer tests orchestration — routing to the right function, flag behaviour, which directories get processed. Duplicating feed-content assertions at the CLI layer would test the wrong abstraction and couple these tests to feed internals.

[`tests/test_cli.py` line 39](https://codeberg.org/marvin8/sub2pod/pulls/10#issuecomment-17611445) > Test 'normal run writes feed.xml' only checks existence, not content or validity of the feed. 🔴 Feed content is exhaustively tested in `test_feed.py` (XML structure, channel metadata, episode items, enclosures, iTunes tags). The CLI test layer tests orchestration — routing to the right function, flag behaviour, which directories get processed. Duplicating feed-content assertions at the CLI layer would test the wrong abstraction and couple these tests to feed internals.
coding-agent-marvin8 commented 2026-06-17 21:02:56 +00:00 (Migrated from codeberg.org)

src/sub2pod/cli.py line 23

Call to parent_dir.iterdir() can raise PermissionError or OSError if the directory is not readable or does not exist.

🔴 Not adding error handling here. parent_dir is a required positional arg: if it doesn't exist or isn't readable, the Python exception message (No such file or directory / Permission denied) is clear and the right signal. Wrapping this would add defensive validation for a dev/ops-facing CLI where crashing loudly on bad input is correct behaviour (per project guidelines: only validate at system boundaries — the OS error message already fulfils that role here).

[`src/sub2pod/cli.py` line 23](https://codeberg.org/marvin8/sub2pod/pulls/10#issuecomment-17611433) > Call to parent_dir.iterdir() can raise PermissionError or OSError if the directory is not readable or does not exist. 🔴 Not adding error handling here. `parent_dir` is a required positional arg: if it doesn't exist or isn't readable, the Python exception message (`No such file or directory` / `Permission denied`) is clear and the right signal. Wrapping this would add defensive validation for a dev/ops-facing CLI where crashing loudly on bad input is correct behaviour (per project guidelines: *only validate at system boundaries — the OS error message already fulfils that role here*).
coding-agent-marvin8 commented 2026-06-17 21:03:02 +00:00 (Migrated from codeberg.org)

src/sub2pod/cli.py line 27

parse_channel_nfo(channel_dir / "tvshow.nfo") assumes the file exists and is valid.

🔴 The filter at line 24 ((child / "tvshow.nfo").exists()) ensures the file is always present before we reach this line, so the missing-file case truly cannot happen. For a malformed tvshow.nfo, loud failure is intentional — silently skipping a broken channel would hide a data problem the operator needs to know about. A test was added in commit 396d3a4 that documents this intended behaviour: malformed tvshow.nfo raises an exception (does not silently skip).

[`src/sub2pod/cli.py` line 27](https://codeberg.org/marvin8/sub2pod/pulls/10#issuecomment-17611436) > parse_channel_nfo(channel_dir / "tvshow.nfo") assumes the file exists and is valid. 🔴 The filter at line 24 (`(child / "tvshow.nfo").exists()`) ensures the file is always present before we reach this line, so the missing-file case truly cannot happen. For a malformed `tvshow.nfo`, loud failure is intentional — silently skipping a broken channel would hide a data problem the operator needs to know about. A test was added in commit `396d3a4` that documents this intended behaviour: *malformed tvshow.nfo raises an exception (does not silently skip)*.
coding-agent-marvin8 commented 2026-06-17 21:03:09 +00:00 (Migrated from codeberg.org)

src/sub2pod/cli.py line 28

discover_episodes(channel_dir) can fail for various reasons (e.g., permission denied on files, unexpected directory stru

🔴 Aborting on the first failure is the right behaviour. If a channel directory can't be read, we don't want to silently produce incomplete feeds for the remaining channels and give the operator the impression everything succeeded. A loud failure with a clear traceback pointing at the problematic channel is more useful than catching the error and continuing.

[`src/sub2pod/cli.py` line 28](https://codeberg.org/marvin8/sub2pod/pulls/10#issuecomment-17611439) > discover_episodes(channel_dir) can fail for various reasons (e.g., permission denied on files, unexpected directory stru 🔴 Aborting on the first failure is the right behaviour. If a channel directory can't be read, we don't want to silently produce incomplete feeds for the remaining channels and give the operator the impression everything succeeded. A loud failure with a clear traceback pointing at the problematic channel is more useful than catching the error and continuing.
coding-agent-marvin8 commented 2026-06-17 21:03:16 +00:00 (Migrated from codeberg.org)

src/sub2pod/cli.py line 37

write_feed(...) can fail due to disk full, permissions, or invalid data. No error handling.

🔴 The Python traceback already identifies the channel directory (it's in the path being written). Disk-full and permission errors on write should be fatal — silently skipping a failed write would leave a stale or missing feed with no indication to the operator. Loud failure is correct here.

[`src/sub2pod/cli.py` line 37](https://codeberg.org/marvin8/sub2pod/pulls/10#issuecomment-17611442) > write_feed(...) can fail due to disk full, permissions, or invalid data. No error handling. 🔴 The Python traceback already identifies the channel directory (it's in the path being written). Disk-full and permission errors on write should be fatal — silently skipping a failed write would leave a stale or missing feed with no indication to the operator. Loud failure is correct here.
coding-agent-marvin8 commented 2026-06-17 21:03:22 +00:00 (Migrated from codeberg.org)

tests/test_cli.py line 78

Test covers missing tvshow.nfo being skipped, but no test for malformed tvshow.nfo (e.g., invalid XML).

Fixed in commit 396d3a4 — added malformed tvshow.nfo raises an exception (does not silently skip). The test writes invalid XML into tvshow.nfo, invokes main(), and asserts the exception propagates, documenting that loud failure is the intended behaviour.

[`tests/test_cli.py` line 78](https://codeberg.org/marvin8/sub2pod/pulls/10#issuecomment-17611448) > Test covers missing tvshow.nfo being skipped, but no test for malformed tvshow.nfo (e.g., invalid XML). ✅ Fixed in commit `396d3a4` — added *malformed tvshow.nfo raises an exception (does not silently skip)*. The test writes invalid XML into `tvshow.nfo`, invokes `main()`, and asserts the exception propagates, documenting that loud failure is the intended behaviour.
coding-agent-marvin8 commented 2026-06-17 21:03:28 +00:00 (Migrated from codeberg.org)

tests/test_cli.py line 88

No test verifies behavior when a channel has zero episodes.

🔴 An empty-episode feed is valid — this is already covered in test_feed.py which tests build_feed_xml with an empty episode list and confirms the output is well-formed XML. The CLI test layer tests orchestration (flag routing, directory filtering), not feed-content invariants that belong to the feed layer.

[`tests/test_cli.py` line 88](https://codeberg.org/marvin8/sub2pod/pulls/10#issuecomment-17611451) > No test verifies behavior when a channel has zero episodes. 🔴 An empty-episode feed is valid — this is already covered in `test_feed.py` which tests `build_feed_xml` with an empty episode list and confirms the output is well-formed XML. The CLI test layer tests orchestration (flag routing, directory filtering), not feed-content invariants that belong to the feed layer.
Sign in to join this conversation.
No reviewers
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!10
No description provided.