Skip to content

feat: add .codec-carver.json config file for repeat workflows#189

Open
seonghobae wants to merge 1 commit into
mainfrom
feat/config-file
Open

feat: add .codec-carver.json config file for repeat workflows#189
seonghobae wants to merge 1 commit into
mainfrom
feat/config-file

Conversation

@seonghobae

Copy link
Copy Markdown
Contributor

Summary

Users currently re-type long flag sets on every run (see the "Verified command for this folder" README example — 10 flags). This PR adds config-file support: store the flag set once in .codec-carver.json at the scan root (or cwd fallback), and repeat runs collapse to one short command.

{
    "flac_all": true,
    "exclude_dir_prefix": ["split_over"],
    "max_duration_seconds": 14400,
    "workers": 2,
    "output_dir": "under_2gb"
}

Design

  • New stdlib-only module config_file.py: load_config(root) discovers .codec-carver.json (scan root first, then cwd), parses JSON, and validates against an allowlist of real parse_args dests with per-key type checking (bool/int/float/str/Path/list-of-str, with True correctly rejected for int keys). Unknown keys, wrong types, and malformed JSON abort with a clear argparse-style error that lists the valid keys — never a traceback.
  • JSON instead of TOML: stdlib tomllib requires Python 3.11+, while this project also supports 3.10. json works on every supported interpreter with no third-party dependency. Documented in the module docstring and README.
  • CLI always wins: parse_args re-parses argv onto a sentinel-seeded namespace to detect which options were explicitly passed; config values apply only to unset options. No config file = byte-identical behavior to today.
  • Safety: root and --execute are deliberately not configurable — root is where the config is discovered, and a config file must never silently turn a dry run into a real conversion.

Tests

26 new tests in tests/test_config_file.py: root/cwd discovery and precedence, config-applied defaults, CLI-flag-overrides-config (including a flag equal to its argparse default), unknown-key error listing valid keys, per-type mismatch errors, malformed JSON and non-object top level, unreadable file, absent file = defaults, and an end-to-end main dry run driven by config.

Gates (python3.14)

  • coverage report --include=media_shrinker.py: 100% (593 stmts, 0 miss)
  • interrogate media_shrinker.py config_file.py: PASSED (100.0%)
  • unittest discover -s tests: 139 tests, no new failures (exactly the 5 pre-existing macOS os.listxattr mock errors from baseline)
  • New tests also verified green on Python 3.10.13

🤖 Generated with Claude Code

Users re-typing long flag sets every run can now store them once in a
.codec-carver.json file at the scan root (or cwd fallback) and collapse
repeat invocations to a single short command.

- New config_file.py module (stdlib-only): discovery, JSON parsing, and
  strict validation against an allowlist of real parse_args dests with
  per-key type checking. Unknown keys, type mismatches, and malformed
  JSON produce clear errors listing the valid keys instead of tracebacks.
- JSON chosen over TOML because stdlib tomllib requires Python 3.11+
  while the project also supports 3.10.
- media_shrinker.parse_args overlays config values only where the user
  did not pass an explicit CLI flag (sentinel-namespace re-parse), so
  CLI always wins and no config file means byte-identical behavior.
- root and --execute are deliberately not configurable: root locates the
  config itself, and a config file must never silently turn a dry run
  into a real conversion.
- 26 new tests covering root/cwd discovery and precedence, CLI-over-
  config priority, unknown-key and type-mismatch errors, malformed JSON,
  and absent-file default behavior. media_shrinker.py coverage stays
  100%; interrogate docstring coverage 100% on both modules.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CJRVbDrp1vGYkJgNHMGPpG
@seonghobae seonghobae enabled auto-merge (squash) July 6, 2026 14:26
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