Conversation
`main()` was a single 165-line function mixing argument definition, logging
setup, three subcommands and handle cleanup. It is now `build_parser()` (with
three focused `_add_*_arguments` helpers), `configure_logging`, and one
`do_encrypt` / `do_decrypt` / `do_test` / `do_version` per action. Every function
is under 50 lines and within the branch limits.
Defects fixed along the way:
* **`-5/--best` was silently identical to `-4`.** The five levels were separate
`store_true` flags with `-4` defaulting to True, so the dispatching `elif`
chain reached `-4` before it could consider `-5`, and 16-nibble-grams were
unreachable. One `store_const` destination makes every level distinct.
* **`-t` reported every byte combination as missing.** It probed
`tuple((c,) for c in combination)` -- a tuple of int-tuples -- against an
alphabet keyed by tuples of `bytes`, so membership could never match. It also
rendered results with `chr()` of values 0-15, i.e. control characters, and
accumulated the message by repeated string concatenation. Now probes the
right shape, renders hex nibbles, and caps the listing at 64 entries with a
count of the remainder (four secrets means 65,536 of them).
* **Non-gzipped ciphertexts raised an uncaught `BadGzipFile` traceback.** The
decrypt path now uses `auto_unzip`, which accepts either, and `-` for stdin
works as the help has always claimed.
* `--same-length` / `--length-checksum` / `--dictionary` were three overlapping
booleans, one of which defaulted to True and was never read. Now one
`store_const` mode.
* `exit(main())` becomes `sys.exit(main())`; `exit` comes from `site` and is
absent under `-S`.
* `LenticryptError` is caught and logged as a message rather than a traceback.
`argparse.FileType` is replaced by taking paths and opening them after parsing.
It is deprecated -- `ty` and Python both warn that it "may leave files open" --
because it opens eagerly during parsing, so a file could be opened and leaked
when a later argument failed to validate. Opening in the action that uses the
file, under an ExitStack, removes both the deprecation and the handle-tracking
bookkeeping. This clears 135 PendingDeprecationWarnings from the test run.
Three stale help strings corrected: `-e` cited "the `-l` argument" for truncation
when it meant `--same-length` (`-l` is `--log-level`), `--dictionary` cited a
nonexistent `-c` option, and `-t` claimed its report goes to stdout when it goes
to the logger on stderr. `--dictionary`'s claim about reducing ciphertext size is
now qualified: measured, it only wins above roughly 8 KiB of plaintext.
Two xfail markers are removed. Both had tested *replicas* of the buggy logic
rather than the real code, so they were retargeted at `build_parser` and
`missing_combinations` before being unmarked. 13 new CLI tests cover mode and
level selection, every compression level round-tripping end to end, and both
gzipped and plain ciphertexts.
`ruff` and `ty` are clean on `__main__.py`.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01367hFob9sd4xpDmVT4uoFy
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.
main()was a single 165-line function mixing argument definition, logging setup, three subcommands, and handle cleanup. It is nowbuild_parser()(with three focused_add_*_argumentshelpers),configure_logging, and onedo_encrypt/do_decrypt/do_test/do_versionper action. Every function is under 50 lines and within the branch limits.Defects fixed
-5/--bestwas silently identical to-4. The five levels were separatestore_trueflags with-4defaulting toTrue, so the dispatchingelifchain reached-4before it could consider-5, making 16-nibble-grams unreachable. Onestore_constdestination makes every level distinct:-treported every byte combination as missing. It probedtuple((c,) for c in combination)— a tuple of int-tuples — against an alphabet keyed by tuples ofbytes, so membership could never match. It also rendered results withchr()of values 0–15, i.e. control characters, and accumulated the message by repeated string concatenation. Now probes the right shape, renders hex nibbles, and caps the listing at 64 entries with a count of the remainder (four secrets means 65,536 of them).Non-gzipped ciphertexts raised an uncaught
BadGzipFiletraceback. The decrypt path now usesauto_unzip, which accepts either, and-for stdin works as the help has always claimed.--same-length/--length-checksum/--dictionarywere three overlapping booleans, one of which defaulted toTrueand was never read. Now onestore_constmode.exit(main())becomessys.exit(main());exitcomes fromsiteand is absent under-S.LenticryptErroris caught and logged as a message rather than a traceback.argparse.FileType removed
Replaced by taking paths and opening them after parsing.
FileTypeis deprecated — bothtyand Python warn it "may leave files open" — because it opens eagerly during parsing, so a file could be opened and leaked when a later argument failed to validate. Opening in the action that uses the file, under anExitStack, removes both the deprecation and the handle-tracking bookkeeping. This clears 135PendingDeprecationWarnings from the test run.Help text
Three stale strings corrected:
-ecited "the-largument" for truncation when it meant--same-length(-lis--log-level),--dictionarycited a nonexistent-coption, and-tclaimed its report goes to stdout when it goes to the logger on stderr.--dictionary's claim about reducing ciphertext size is now qualified — measured, it only wins above roughly 8 KiB of plaintext.Verification
Two
xfailmarkers removed. Both had tested replicas of the buggy logic rather than the real code, so they were retargeted atbuild_parserandmissing_combinationsbefore being unmarked. 13 new CLI tests cover mode and level selection, every compression level round-tripping end to end, and both gzipped and plain ciphertexts.173 passed / 3 xfailed.
ruffandtyclean on__main__.py.🤖 Generated with Claude Code
https://claude.ai/code/session_01367hFob9sd4xpDmVT4uoFy