Make progress.py portable and stop redrawing per character - #15
Merged
Conversation
ESultanik
force-pushed
the
fix-gzip-filename-leak
branch
from
August 7, 2026 19:23
6a6e634 to
d89f488
Compare
`progress.py` imported `fcntl` and `termios` at module scope for a hand-rolled
20-line terminal-size probe. Both are Unix-only, and `__main__` imports
`progress` unconditionally, so the whole package was unimportable on Windows --
`import lenticrypt.__main__` failed outright. `shutil.get_terminal_size()` does
the same job portably, including the COLUMNS fallback, in one line. Both bare
`except:` clauses go with it.
Other fixes:
* `ProgressBar.update` divided by `max_value` without guarding zero. The index
builder derives its range from the certificate length, which is <= 0 for a
short certificate and a long nibble-gram, so ZeroDivisionError was reachable.
* `ProgressBarCallback` bound `max_value` from its first call and never updated
it, so every phase after the first was drawn against the first phase's scale.
`update` now takes the maximum per call.
* Rendering issued one `stream.write()` per column -- 200 write calls per
redraw on a 200-column terminal. The bar is built as one string and written
once. Redraws are also skipped when neither the rounded percentage nor the
status text would change.
Adds a `StatusCallback` Protocol so the reporter contract is explicit and
checkable, and makes `ProgressBarCallback` a context manager, which replaces the
create/try/finally-clear dance repeated three times in `main`.
windows-latest joins the CI matrix in the same commit, so the leg demonstrates
the import fix rather than being added on faith.
First tests for this module: ten cases covering the zero and negative maxima,
clamping, rescaling across phases, width, redraw suppression, the Protocol, the
context manager, and importability with `fcntl`/`termios` blocked. The zero-max
xfail marker is removed since it now passes.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01367hFob9sd4xpDmVT4uoFy
ESultanik
force-pushed
the
progress-portability
branch
from
August 7, 2026 19:25
36f70db to
794125c
Compare
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.
Stacked on #14.
progress.pyimportedfcntlandtermiosat module scope for a hand-rolled 20-line terminal-size probe. Both are Unix-only, and__main__importsprogressunconditionally, so the whole package was unimportable on Windows —import lenticrypt.__main__failed outright.shutil.get_terminal_size()does the same job portably, including the COLUMNS fallback, in one line. Both bareexcept:clauses go with it.Other fixes
ProgressBar.updatedivided bymax_valuewithout guarding zero. The index builder derives its range from the certificate length, which is<= 0for a short certificate and a long nibble-gram, soZeroDivisionErrorwas reachable.ProgressBarCallbackboundmax_valuefrom its first call and never updated it, so every phase after the first was drawn against the first phase's scale.updatenow takes the maximum per call.stream.write()per column — 200 write calls per redraw on a 200-column terminal. The bar is built as one string and written once. Redraws are also skipped when neither the rounded percentage nor the status text would change.Adds a
StatusCallbackProtocol so the reporter contract is explicit and checkable, and makesProgressBarCallbacka context manager, replacing the create/try/finally-clear dance repeated three times inmain.CI
windows-latestjoins the matrix in this commit, so the leg demonstrates the import fix rather than being added on faith.Verification
First tests for this module: ten cases covering zero and negative maxima, clamping, rescaling across phases, width, redraw suppression, the Protocol, the context manager, and importability with
fcntl/termiosblocked. The zero-maxxfailmarker is removed since it now passes.🤖 Generated with Claude Code
https://claude.ai/code/session_01367hFob9sd4xpDmVT4uoFy