Validate positive CLI numeric options consistently (closes #15) - #20
Merged
Johnkothapalli merged 1 commit intoAug 20, 2026
Conversation
--workers 0 was silently swallowed by `args.workers or defaults.workers`
and fell back to the default worker count; --max-complexity 0 reached
AnalyzerConfig and surfaced as a ValueError traceback. Two different
wrong behaviours for the same class of bad input.
Added a reusable `_positive_int` argparse type and used it for both, so
each is reported by argparse as a usage error with exit code 2 and no
traceback. It also rejects non-integers with a clearer message than
argparse's default.
The `or` in main() is now an explicit `is None` check. _positive_int
means 0 can no longer reach it, but None (option omitted) is the only
fallback case and saying so keeps the bug from coming back.
AnalyzerConfig's own validation is untouched — CLI validation is
additive, and direct API callers keep their guard. A test pins that.
No dependency added.
Tests: 10 added to tests/test_cli.py — both option names x {0, -1},
both x non-integer, both with a valid explicit value, defaults preserved
when omitted, and AnalyzerConfig still raising for API callers. The 6
rejection tests fail against pristine cli.py.
Gate: pytest 24 passed (coverage 92.93%, threshold 85%); ruff check and
ruff format --check clean.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #15.
The two positive-integer options failed differently for the same class of bad input:
--workers 0was swallowed byargs.workers or defaults.workersand silently fell back to the default worker count, while--max-complexity 0reachedAnalyzerConfigand surfaced as aValueErrortraceback.What changed
A small reusable argparse type:
Applied to
--workersand--max-complexity. Both now fail as argparse usage errors with exit code 2:It also catches non-integers with a clearer message than argparse's default
invalid int value.The
orinmain()is now an explicitis Nonecheck._positive_intmeans 0 can't reach it any more, so this is belt-and-braces — but theorwas the bug, and spelling out thatNone(option omitted) is the only fallback case keeps it from coming back.AnalyzerConfig.__post_init__validation is deliberately untouched: CLI validation is additive and direct API callers keep their own guard. There's a test pinning that, since "moved the check to the CLI" would be the tempting wrong refactor.No dependency added.
Tests
10 added to
tests/test_cli.py, parametrized over both option names:0and-1→ exit code 2, stderr names the option and says "must be at least 1"--workers 2,--max-complexity 1) still scans and returns 0workers is Noneandmax_complexity == AnalyzerConfig().max_complexityAnalyzerConfig(workers=0)/AnalyzerConfig(max_complexity=0)still raiseValueErrorRed-before-green: with
git stash push -- src/code_health/cli.py, all 6 rejection tests fail against pristine code.Gate
Ran the full local gate from CONTRIBUTING on Windows / Python 3.12:
pytest— 24 passed, coverage 92.93% (threshold 85%)ruff check .— cleanruff format --check .— 28 files already formatted🤖 Generated with Claude Code