Repository navigation
Refactor/structure tests and docs - #17
Merged
Merged
Conversation
No matching behaviour changes. Every elapsed time, match flag and matched trackpoint the library produced before, it produces after -- verified by differential testing against the previous implementation: 4061 checks over a parameter sweep, run on both the old dependency stack and the new one, with zero mismatches. With the RNG seeded identically the warping distances come out bit-identical, not merely close. BREAKING CHANGE: requires Python 3.11 and Shapely 2. Tests first ----------- The suite was five tests over two matches, which is enough to notice a crash and not enough to notice a numerical drift. It is now 134 tests at 98% coverage, written and made green against the *previous* implementation before any code moved, so the restructuring had something to be measured against. Times, flags and trackpoints are asserted exactly. Only the warping distance carries a tolerance: interpolation jitters coordinates from the unseeded global RNG, six consecutive runs spread over 0.1% of the mean, so DTW_RTOL is 1%. Structure --------- One 747-line geopard.py becomes ten modules under src/geopard/, the largest 329 lines. Geopard keeps every method it had and delegates to them, so the class stays the documented interface while each stage becomes importable and testable on its own. No public method was added or removed; nine of twelve signatures are unchanged and three gained optional arguments. `from geopard.geopard import Geopard` -- the only import path that worked before -- still resolves, and a test guards it. Adds geopard/__init__.py, so the `import geopard; geopard.Geopard()` the README has always documented actually works. It never did. Tooling ------- uv and hatchling replace Poetry, setup.py, setup.cfg and requirements.txt. ruff replaces black, isort, flake8, pylint, pydocstyle and autoflake. mypy is added and passes. The version now has one home, src/geopard/version.py, read dynamically by pyproject.toml, with a test that fails if that wiring breaks. Shapely was pinned <2, which has no wheels for any supported Python -- a fresh install fell back to compiling from source and usually failed. Unpinned to 2.x and verified numerically identical across the upgrade. Fixes ----- - nearest_neighbours logged a list with %f, failing on every call. Invisible, because the logging module swallows formatting errors. - parse_response raised a formatting error on an unmatched response, where dtw is None, and logged the bound method rather than calling is_success(). - The PyPI workflow ran on every push and every pull request to main rather than on a release. - GeopardResponse declared six methods permanently shadowed by instance attributes of the same name, so none could ever be called. It is now a frozen dataclass; is_success() stays a method, because the examples call it. - nearest_neighbours had `centroid=list` as a default -- the type object. - requirements.txt listed haversine and similaritymeasures, neither imported. Plots ----- A single palette, and aspect-ratio correction for latitude: at 47 degrees north a degree of longitude is two-thirds of a degree of latitude, so the previous raw scatter squashed every route by a third and made a good match look bad. Legends moved outside the data, marker sizes are readable rather than 500 points, and style() returns rcParams instead of applying them globally, so importing geopard no longer changes anyone else's plots. plot_track_comparison gained show= and save_to=, so figures can be produced in a script or in CI. Example scripts take real --flags with defaults and exit with a status code.
The README explained how to install Poetry before it explained what the library does, and the usage it documented -- `import geopard; geopard.Geopard()` -- did not work. Rewritten around the problem the library actually solves: an activity is longer than the segment inside it, a start line is not a point, and an activity may cover a segment several times, so the answer has to be the fastest of many candidate attempts rather than the first one found. Adds a light/dark banner drawing the one idea in the library -- two tracks tied point to point, the ties deliberately not one-to-one, because that stretching is the mechanism -- and a mermaid flowchart of the match loop. The example figures are regenerated with the new plotting style. AGENTS.md is the source of truth, split into using the library and changing it. The half worth having is A5, what to do when a match is not what you expected: work down the list rather than reaching for dtw_threshold, because loosening the threshold is the one change that makes every result less trustworthy. CLAUDE.md and GEMINI.md point at it and hold no content of their own. docs/architecture.md records the decisions that look wrong until you know why: why candidates are warped shortest-first and the loop stops at the first match, why the cost matrix stays a Python loop, why the interpolation count is a constant rather than an argument, why failures are returned instead of raised, and why elevation is loaded and never used. Also adds CHANGELOG.md and SECURITY.md, and drops README.rst, which duplicated the README and documented an API that had since moved.
The 3.12 and 3.13 jobs were failing, and not on the tests -- pytest passed on
all three. `[tool.mypy] python_version = "3.11"` made mypy reject its own
dependencies' stubs when run on a newer interpreter:
numpy/__init__.pyi:737: error: Type statement is only supported in
Python 3.12 and greater [syntax]
numpy's stubs use PEP 695 `type` statements, which are legal on the 3.12 and
3.13 runners but refused by a 3.11 target. Unset, mypy targets whichever
interpreter it runs under. That also unbreaks `make check` for anyone working
on 3.12 or 3.13, which the pin broke locally in exactly the same way.
The matrix drops to 3.11 alone. It would pass on all three now, so restoring
the other two is a one-line change if the wider coverage is ever wanted.
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.
No description provided.