v2.1 — nine outside contributors
Nine people outside the project shipped changes in this release. Two days ago that number was zero. Everything below came from someone who read the code, disagreed with it, and sent a patch.
Fixed
The elapsed-time clock kept counting after a run finished. snapshot() computed the elapsed time from now - t0 unconditionally, so the display carried on ticking after the last file landed. The engine now records the end time at the single point where a run terminates — covering both a normal finish and a crash — and freezes the value there. (#73, @RubenSanosh)
A discarded partial download said nothing. When a server answers 200 instead of 206 it is refusing to resume, and the code correctly restarted from zero — silently. A multi-gigabyte transfer appeared to begin again for no reason. The restart is now recorded and appears in moontech_*.log, with a regression test that fakes the response without touching the network. (#98, @XEDAB)
--proxies failed silently. A misspelled path, or a file the parser did not recognise, loaded zero proxies and printed nothing — so a run started specifically to avoid direct connections made them anyway, with no indication. (#48, @AdvaitVarhade)
The headless CLI example documented a command that never worked. README.md showed positional URLs the parser does not accept and a -o flag that does not exist. (#53, @tomatotomata)
The guard that should have caught it could not see it. tests/test_docs_cli_flags.py matched only --long flags, so the bogus -o passed every check. It now validates single-dash flags against the parser too. (#104, @kocaemre)
docs/ARCHITECTURE.md still described the download engine as two copies, which #41 had made untrue. (#68, @Moferanoluwa)
Changed
The download engine exists once. download_file, Telemetry and ProxyPool moved into moon_download.py; both front-ends import them instead of each carrying a copy. A fix in the download path is now a one-file change, and the two copies can no longer drift apart. (#41, @pollychen-lab)
Exception handling says why. Handlers across moon_bridge.py, moon_cli.py, moon_download.py, moon_engine.py and the first slice of moon_extract.py are narrowed where the exception set is knowable, and where they must stay broad they now state a specific reason. moon_extract.py keeps its deliberate deferred playwright import, so a fuckingfast-only batch still never loads it. (#54, #71, #82 — @AdvaitVarhade, @Moferanoluwa)
Added
CI runs on Python 3.10, 3.11 and 3.12 and lints with ruff. The ignore list parks the rules that fire on the codebase as it stands, each with its count and the reason — a baseline that catches regressions rather than a reformat. (#69, @Moferanoluwa)
Documentation-only pull requests are checked against the real CLI parser. They previously ran no checks at all. A new workflow reads the true flag set from moon_cli.py --help at test time and fails on any documented invocation using a flag the parser does not accept. Reading --help rather than hardcoding means adding a flag never requires touching the test. (#70, @Moferanoluwa)
The byte-compile list cannot drift. The job named "Byte-compile every module" compiled a hand-written list that had fallen behind — moon_download.py, the shared download engine, was never compiled at all. It now derives the list from git ls-files, and the workflow watches its own file. (#77, @darlenepolek)
The verification suite is a pytest suite. (#38, @pollychen-lab)
moon_cli.py --version, recorded in both report flavours, from one VERSION constant. (#61, @Moferanoluwa)
docs/CLI.md — every flag, its default, and what it actually controls. (#37, @kushin25)
Contributors
| @kushin25 | the CLI reference |
| @pollychen-lab | the pytest suite, and the shared download engine |
| @AdvaitVarhade | proxy error reporting, and two slices of the exception cleanup |
| @Moferanoluwa | --version, the CI matrix and ruff, the docs guard, and two doc corrections |
| @RubenSanosh | the elapsed-time clock |
| @darlenepolek | the byte-compile list |
| @XEDAB | the silent resume discard |
| @tomatotomata | the broken CLI example |
| @kocaemre | short flags in the documentation guard |
Full detail in CHANGELOG.md, and who did what in AUTHORS.md.
Want to be in the next one?
The roadmap lists everything open, ranked by size and by whether it needs Windows — most of it does not. Three issues are reserved for people who have never had a pull request merged anywhere, and are done entirely in the browser.
Several of the open bugs were found by using the program and come with measurements from real runs, so you can check a fix against a number instead of a feeling.