v2.0.0
[2.0.0] — 2026-07-08
The 2020 JPL site restructure broke v1 (it silently downloaded nothing), and v1
carried latent security and correctness defects. v2 is a modernization: same
purpose, packaged, tested, and fixed.
Added
- Packaged as the
cosmic_crunchdistribution with a singlecosmic-crunch
console entry point (getandconvertsubcommands) viapyproject.toml
(hatchling); requires Python 3.10+. --base-urlflag andCOSMIC_CRUNCH_BASE_URLenvironment variable to override
the crawl root.--instrumentflag (defaultcosmic) to select other instrument trees
(champ,gracea,gracefo1, …).- Atomic, resumable downloads: stream to
<name>.partthen rename; skip files
already present with a matching size. - Offline
pytestsuite and a GitHub Actions CI workflow (ruff + pytest on
Python 3.10–3.13 +build/twine check). CHANGELOG.mdandCITATION.cff.
Changed
- New crawl root
https://genesis.jpl.nasa.gov/ftp/glevels/(the v1
/ftp/pub/genesis/glevelsroot is dead). - Fail loud: a crawl that finds zero data files now raises and exits
non-zero instead of silently "succeeding" with nothing downloaded. - Bounded retry: the v1 infinite silent retry is replaced with a bounded
retry (default 3 attempts, exponential backoff, logged, re-raises on failure). - Relicensed from AGPL-3.0 to MIT.
- Logging is configured only under the CLI, not at import time (importing the
package no longer creates a stray log file). - Deduplicated the copy-pasted
parallelize/flatten/retry helpers into
cosmic_crunch/_parallel.py; single-sourced__version__.
Fixed
- Security: removed
eval()of downloaded header content (arbitrary code
execution); header values are parsed withast.literal_eval+ raw-string
fallback, preserving brace-set element order. - Security: path traversal in downloads — a hostile or tampered directory
listing could smuggle../through a filename and write outside the save
directory. Downloaded filenames are now reduced to a bare leaf and confined
to the save root (irreducible unsafe names are rejected before any fetch). - The v1
FILES_TO_GET = -1default silently dropped the last crawled file on
every non-test run ([:-1]); it now defaults to downloading everything. crawl_convertprocessed only the first path argument (areturninside the
per-path loop, plus apathsshadowing typo) — it now converts all paths.- Column-name loop-leak: rows of DataTypes with differing field counts were
parsed with the wrong column names — each type now keeps its own columns. - Single-file conversion creates its output directory; directory creation uses
os.makedirs(exist_ok=True).
Migration
- The invocation changed:
python get_files.py …/python convert_files.py …
becomecosmic-crunch get …/cosmic-crunch convert …. This is the breaking
change behind the major version bump. There are no deprecation shims (the tool
was never published and has no known downstream users).