Skip to content

Fix dependency-handling bugs: RAR probe, PDF guard, config errors - #229

Merged
ajslater merged 1 commit into
developfrom
fix/dependency-bugs
Oct 2, 2026
Merged

ajslater merged 1 commit into
developfrom
fix/dependency-bugs

Conversation

@ajslater

@ajslater ajslater commented Oct 2, 2026

Copy link
Copy Markdown
Owner

Seven bugs in how comicbox detects and reports its external dependencies, found while planning a comicbox --doctor command.

Changes

  • RAR support is probed, not guessed. is_unrar_supported() / check_unrar_executable() now extract the compressed member of a bundled 110-byte RAR5 archive (comicbox/_rar_probe.rar) through whichever tool rarfile selects, via the new cached comicbox._rar.rar_unsupported_reason(). Checking which("unrar") was wrong in both directions, and so is trusting rarfile.tool_setup(). rarfile 4.5's bsdtar command line opens a file named --, and Homebrew's 7zz has no RAR codec. Both pass rarfile's tool check but extract nothing, so on every Mac the check would report CBR support that doesn't work.
  • Tool failures map to UnsupportedArchiveTypeError. RarCannotExec, and tool failures while constructing a RarFile (RAR3 compressed comments), now map the way BadRarFile already did, when the probe says the host can't extract.
  • is_pdf_supported() returns PDF_ENABLED. It used to check "pdffile" in sys.modules, which is also true when the guard rejected pdffile or the embedding app imported it.
  • A broken PDF extra no longer breaks the rest of comicbox. _pdf.py survives any pdffile import failure; pymupdf asserts its libmupdf version at import, which raised past the except ImportError. It warns unless pdffile is simply not installed.
  • A malformed user config.yaml no longer drops the package defaults. Previously validation then died on comicbox.paths not found.
  • Config errors are typed and print cleanly. They raise a new ConfigurationError(ComicboxError, ValueError), so callers catching ValueError are unaffected. The CLI prints those and confuse's ConfigError as one yellow line instead of a traceback. Messages are escaped so rich no longer eats [digital] as markup.
  • online.tuning.per_source blocks are type-checked. They use the existing but previously unused tuning template. Null blocks are allowed, and unknown source names warn and are skipped.
  • _archive_errors() tolerates an unimportable rarfile or py7zr. It previously raised inside the except clause and aborted batch reads.
  • Stale zipremove comment corrected. Python 3.14 has no ZipFile.remove / repack.

Codex impact (after it bumps comicbox)

  • Codex calls Comicbox.is_unrar_supported() (codex/librarian/fs/filters.py), which now runs one cached probe subprocess per process.
  • A host whose only RAR tool can't extract stays CBR-unsupported.
  • A host with a working tool other than unrar becomes supported.

Testing

  • make fix, make lint (ruff, basedpyright 0 warnings, vulture, complexipy) and make ty are clean.
  • radon cc --min C and radon mi --min B on the changed files print nothing.
  • make test: 2289 passed, 1 pre-existing skip.
  • New tests: tests/unit/test_rar_tool_probe.py, test_pdf_import_guard.py, test_config_errors.py, test_process_archive_errors.py, plus three CLI cases in tests/cli/test_cli_exit_code.py.
  • The process-error, PDF-guard and CLI tests fail against unfixed develop, run in a throwaway worktree. The RAR-probe and config tests import new names, so that check couldn't apply to them.
  • A built wheel contains comicbox/_rar_probe.rar.

🤖 Generated with Claude Code

Found while planning `comicbox --doctor`.

- RAR support is probed by extracting a compressed member of a bundled
  110-byte RAR5 archive (comicbox/_rar_probe.rar) through whichever tool
  rarfile picks, instead of `which("unrar")`. rarfile 4.5's bsdtar
  command line opens a file named `--`, and Homebrew's 7zz has no RAR
  codec: both pass rarfile's tool check and extract nothing, so trusting
  that check would make every Mac look CBR-capable to Codex.
- RarCannotExec, and tool failures while constructing a RarFile (RAR3
  comments), map to UnsupportedArchiveTypeError as BadRarFile already did.
- is_pdf_supported() returns PDF_ENABLED instead of checking sys.modules,
  which is also true when the guard rejected pdffile or Codex imported it.
- _pdf.py survives any pdffile import failure (pymupdf asserts its
  libmupdf version at import) and warns unless pdffile is simply absent.
- A malformed user config no longer drops the package defaults beneath
  it. Config errors raise ConfigurationError(ComicboxError, ValueError);
  the CLI prints those and confuse's ConfigError as one line, escaped so
  rich keeps "[digital]" instead of eating it as markup.
- online.tuning.per_source blocks are type-checked with the existing but
  unused tuning template; unknown source names warn and are skipped.
- _archive_errors() tolerates an unimportable rarfile or py7zr instead of
  raising inside the except clause and aborting batch reads.
- Correct the zipremove comment: 3.14 has no ZipFile.remove/repack.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ajslater
ajslater merged commit 21482e8 into develop Oct 2, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant