feat(geocode): add OpenCage online geocoding subcommands (#1295)#3876
Merged
Conversation
Add `opencage` and `opencagenow` subcommands to the `geocode` command for
online forward (address) and reverse (coordinate) geocoding via the OpenCage
Geocoding API. The offline subcommands (suggest/reverse/countryinfo/iplookup)
are unchanged.
- calls the OpenCage REST API directly with the async reqwest client
(rustls, honors --timeout); no new crate dependency
- persistent on-disk result cache (OpenCage's TOS permits caching) plus
in-run de-duplication; controlled by --cache-ttl / --no-cache
- governor rate limiter (--rate-limit, default 1/sec) over a sequential
row loop, routed around the offline rayon pipeline
- API key via --api-key flag or QSV_OPENCAGE_API_KEY env var
- OpenCage-specific %-formats and dotted-key dynamic templating
({components.city}, {annotations.timezone.name})
- governor added to the geocode feature in Cargo.toml
- CI tests for arg validation; live-API tests are #[ignore]'d
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Up to standards ✅🟢 Issues
|
Contributor
There was a problem hiding this comment.
Pull request overview
Adds online OpenCage geocoding support to qsv geocode, complementing the existing offline GeoNames/MaxMind-based subcommands. This introduces new CLI surface area, online HTTP integration (with caching and rate limiting), and associated documentation/tests.
Changes:
- Add
geocode opencage/geocode opencagenowsubcommands with API key handling, rate limiting, and persistent disk caching. - Extend geocode formatting to support OpenCage-specific
%formats and dotted-key dynamic templates. - Update docs/help and README references; add basic argument-validation tests plus ignored live-API tests.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
src/cmd/geocode.rs |
Implements OpenCage online geocoding flow, CLI flags, caching, rate limiting, and formatting helpers. |
tests/test_geocode.rs |
Adds CI-safe argument-validation tests and ignored live-API integration tests for OpenCage. |
docs/help/geocode.md |
Documents new OpenCage subcommands and OpenCage-only options. |
README.md |
Updates the command table entry for geocode to mention OpenCage online support. |
Cargo.toml |
Adds governor to the geocode feature set. |
.claude/skills/qsv/qsv-geocode.json |
Extends the geocode skill schema to include new subcommands and OpenCage-related flags. |
Comments suppressed due to low confidence (1)
tests/test_geocode.rs:2044
- This test runs the live OpenCage command twice (
assert_successand thenread_stdouteach invokecmd.output()), which doubles API usage when running ignored live tests. Prefer capturingcmd.output()once and parsing stdout from that output to avoid extra API calls.
wrk.assert_success(&mut cmd);
let got: Vec<Vec<String>> = wrk.read_stdout(&mut cmd);
assert_eq!(got.len(), 4);
…rify README - log a warning when remove_expired_entries() fails instead of silently discarding the error (Copilot review) - the geocode_opencage CI tests now capture cmd.output() once and assert on both status and stderr, instead of running the command twice (Copilot review) - README: attribute the 360k records/sec figure to the offline path and note that OpenCage online geocoding is sequential and rate-limited (Copilot review) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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.
Closes #1295.
Adds
opencageandopencagenowsubcommands to thegeocodecommand for online forward (address → coordinates) and reverse (coordinates → address) geocoding via the OpenCage Geocoding API. The existing offline subcommands (suggest/reverse/countryinfo/iplookup) are unchanged.Per the issue's 2026-05-20 comment, this brings OpenCage support into OSS qsv (out of "qsv pro 2.x") for the DataPusher+/Prefect work — the offline GeoNames engine cannot geocode real street addresses.
What's included
qsv geocode opencage <column>andqsv geocode opencagenow <location>. The query column may hold an address (forward) or alat,longcoordinate (reverse); the mode is auto-detected per row (--reverseforces reverse).reqwestclient (rustls, honors--timeout). Thegeocodingcrate was evaluated but rejected — it is unmaintained, pinsreqwest 0.11, and pulls innative-tls/OpenSSL, breaking qsv's rustls-only policy. No new crate dependency is added.cached::DiskCache) keyed on query+language+country+format, plus in-run de-duplication. Controlled by--cache-ttl(default 14 days) and--no-cache.governorrate limiter (--rate-limit, default 1 req/sec — the free-tier limit) over a sequential row loop, routed entirely around the offline rayon pipeline so the offline path is untouched.--api-keyflag orQSV_OPENCAGE_API_KEYenv var (flag wins); missing key is a clean usage error.%-formats (%formatted,%city,%country,%json, …) and dotted-key dynamic templating ({components.city},{annotations.timezone.name}).governoradded to thegeocodeCargo feature.Testing
qsv,qsvdp, andqsvmcpall build;clippyandcargo +nightly fmtare clean.--admin1rejection).#[ignore]'d. They have not been run — verifying the actual geocoding round-trip requires an OpenCage API key:🤖 Generated with Claude Code