Changelog ========= All notable changes to ``gcamreader`` are documented here. The format is based on `Keep a Changelog `_, and the project adheres to `Semantic Versioning `_. This page is the canonical, rendered changelog. Each released version also records its **release verification** — the behavioral regression results proving that the release reproduces the previous version's query outputs exactly. New releases should add their own ``Release verification`` block following the pattern shown for :ref:`changelog-1-5-0` below. .. _changelog-unreleased: Unreleased ---------- No unreleased changes yet. .. _changelog-1-5-0: 1.5.0 — 2026-06-15 ------------------ This release modernizes the package without changing its computational results. A behavioral baseline captured from v1.4.0 is preserved in ``benchmarks/`` and is used as a regression gate to guarantee identical query outputs. Added ~~~~~ - Behavioral baseline harness and regression test suite in ``benchmarks/`` that lock query, scenario, ``importdata``, and CLI outputs to the v1.4.0 results. - ``pyproject.toml`` as the single source of build metadata and configuration. - ``CHANGELOG.md`` to track project changes. Changed ~~~~~~~ - Migrated packaging from ``setup.py`` and ``setup.cfg`` to ``pyproject.toml`` (setuptools backend). - Raised the minimum supported Python version to 3.11. - Replaced the Click based command line interface (and the ``click-default-group-wheel`` dependency) with a Typer based CLI. - Relaxed the pinned ``requests~=2.20.0`` requirement to a modern minimum and refreshed the ``pandas`` and ``lxml`` minimum versions. - Modernized ``querymi.py``: removed Python 2 and Python 3.5 compatibility branches, replaced ``pkg_resources`` with ``importlib.resources``, and added type hints and complete docstrings. - Moved the test suite to a top level ``tests/`` directory and the example notebooks to a top level ``notebooks/`` directory. Fixed ~~~~~ - Result parsing in ``_parserslt`` now aggregates with ``dropna=False``, so rows that contain missing values in one or more grouping columns are retained instead of being silently dropped during the ``groupby().sum()`` step (PR #40). Removed ~~~~~~~ - ``setup.py``, ``setup.cfg``, ``requirements.txt``, and ``MANIFEST.in`` (superseded by ``pyproject.toml``). .. _changelog-1-5-0-verification: Release verification ~~~~~~~~~~~~~~~~~~~~~~ **Result: PASS — v1.5.0 reproduces the v1.4.0 outputs exactly.** Because v1.5.0 is a modernization release, its central guarantee is that it changes *no* computational results. To prove this, a behavioral baseline was captured from **v1.4.0** and committed under ``benchmarks/baseline/``; the v1.5.0 code is then re-run through the same operations and its outputs are compared against that baseline by ``benchmarks/test_regression.py``. Every fixture matches the v1.4.0 baseline. CSV outputs are compared byte-for-byte by SHA-256 checksum, and DataFrame outputs are compared with :func:`pandas.testing.assert_frame_equal` after a deterministic sort. ============================================ ========= ================================== ======== Operation Result Comparison method Java ============================================ ========= ================================== ======== ``parse_batch_query`` (query structure) identical exact title/region/query strings not req. ``listScenariosInDB`` identical ``assert_frame_equal`` required ``runQuery`` (land-allocation query) identical ``assert_frame_equal`` (sorted) required ``importdata`` (land-allocation query) identical ``assert_frame_equal`` (sorted) required ``gcamreader local`` CLI CSV output identical SHA-256 (byte-for-byte) required ============================================ ========= ================================== ======== The committed v1.4.0 baseline fixtures and their SHA-256 checksums (from ``benchmarks/baseline/manifest.json``) are: ========================================== ================================================================== Fixture SHA-256 ========================================== ================================================================== ``cli_outputs/crop_land_allocation.csv`` ``82dd106d12e14f32d4e9828e5a4ebb3d0cb78580da33dc5de9a8b9f0124f250b`` ``parse_batch_query.json`` ``b83c9a39d7aee7cbc76535c4bb154bdafdfe96e550ac1709740bd856eb3fbdd2`` ``query_outputs/importdata_land.csv`` ``a7574c25b04446bcb27029b4547acac45f546415ebd5cc3fa310bd8c9742a445`` ``query_outputs/land_query.csv`` ``a7574c25b04446bcb27029b4547acac45f546415ebd5cc3fa310bd8c9742a445`` ``query_outputs/list_scenarios.csv`` ``341660163c5f0c578f0aa44cdfe29dee4feca5af030bdeeea4652cccb98da690`` ========================================== ================================================================== Baseline capture environment: ================ ==================================================== Component Value ================ ==================================================== Baseline version ``gcamreader`` 1.4.0 Python ``3.13.3`` Java OpenJDK ``23.0.2`` (Homebrew) Platform macOS 26.5.1 (arm64) Benchmark query Crop Land Allocation (bundled land query) ================ ==================================================== Reproduce the parity check locally with: .. code-block:: bash pytest benchmarks/test_regression.py The structural ``parse_batch_query`` check runs without Java; the database-backed checks require a Java runtime and the bundled sample database. See :doc:`verified_versions` for the separate study confirming compatibility across GCAM database versions 5.3 through 9.1.