Skip to content

Harden saved-list place links and canonical coordinates#51

Merged
michaelmwu merged 2 commits into
mainfrom
codex/harden-place-coordinate-links
Jul 12, 2026
Merged

Harden saved-list place links and canonical coordinates#51
michaelmwu merged 2 commits into
mainfrom
codex/harden-place-coordinate-links

Conversation

@michaelmwu

@michaelmwu michaelmwu commented Jul 12, 2026

Copy link
Copy Markdown
Member

Summary

  • emit direct CID links for addressless saved-list rows instead of ambiguous name-only searches
  • prefer explicit !3d/!4d pin coordinates from a canonical resolved place URL over conflicting preview payload coordinates
  • retain @lat,lng viewport coordinates only as a fallback when structured coordinates are unavailable
  • reject out-of-range canonical and viewport coordinate pairs
  • record resolved-URL coordinate provenance in diagnostics

Why

The issue surfaced while investigating demflyers-favorites PR #101: the saved-list feed itself supplied two incoherent rows, and a separate place-page path could let coordinates from an unrelated preview entity outrank the selected place marker.

Verification

  • ./scripts/lint.sh
  • ./scripts/typecheck.sh
  • uv run python3 -m unittest discover -s tests — 280 tests passed
  • git diff --check

Note

Medium Risk
Changes core coordinate and URL emission logic for place and list outputs; wrong regex or precedence could shift lat/lng or links for many records, though behavior is covered by new unit tests.

Overview
Hardens saved-list place links and place-page coordinates so downstream feeds get less ambiguous location data.

For saved-list rows, maps_url now prefers a direct https://www.google.com/maps?cid=… link when there is no address but a CID is known; name-only search URLs remain when both address and CID are missing.

For place scraping, lat/lng from the resolved canonical /maps/place/ URL’s !3d/!4d pin now override conflicting preview (or merged snapshot) coordinates, with @lat,lng viewport values used only when structured pin coords are absent. field_sources records resolved_url provenance for those coordinates; the same preference runs after DOM/preview merge in place_scraper and in the CLI debug scrape path.

docs/ARCHITECTURE.md documents both behaviors.

Reviewed by Cursor Bugbot for commit 28b36b8. Bugbot is set up for automated code reviews on this repo. Configure here.

Summary by CodeRabbit

  • Bug Fixes

    • Improved place coordinate accuracy by prioritizing canonical coordinates from Google Maps URLs.
    • Added fallback handling when canonical coordinates are unavailable or only viewport coordinates are provided.
    • Saved places without addresses now use direct CID links when available; otherwise, they use name-based search links.
  • Documentation

    • Clarified coordinate precedence and saved-list URL behavior in the extraction strategy guidance.

@coderabbitai

coderabbitai Bot commented Jul 12, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The PR adds direct CID-based Maps URLs for addressless saved-list records and changes place-coordinate extraction to prioritize structured coordinates from canonical resolved URLs over preview or viewport data.

Changes

Extraction strategy updates

Layer / File(s) Summary
CID-based saved-list Maps URLs
src/gmaps_scraper/parser.py, tests/test_parser.py, docs/ARCHITECTURE.md
Saved-list parsing passes CID metadata into Maps URL construction, producing direct CID URLs when addresses are missing and name-only search URLs when both fields are absent.
Canonical place coordinate precedence
src/gmaps_scraper/place_scraper.py, src/gmaps_scraper/cli.py, tests/test_place_scraper.py, docs/ARCHITECTURE.md
Structured !3d/!4d coordinates from resolved place URLs override preview coordinates, while preview coordinates remain the fallback for unavailable or viewport-only URL coordinates.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant DebugScraper
  participant SourceMerger
  participant ResolvedPlaceURL
  participant PlaceDetails
  participant Diagnostics
  DebugScraper->>SourceMerger: merge DOM and preview sources
  SourceMerger->>ResolvedPlaceURL: provide resolved_url
  ResolvedPlaceURL-->>SourceMerger: return canonical !3d/!4d coordinates
  SourceMerger->>PlaceDetails: build details from adjusted snapshot
  PlaceDetails->>Diagnostics: record coordinate field sources
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is concise and accurately summarizes the main changes to saved-list links and canonical coordinate handling.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/harden-place-coordinate-links

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/gmaps_scraper/place_scraper.py (1)

4287-4296: 🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

Fallback coordinate extraction bypasses the range validation applied to the canonical path.

_extract_canonical_place_coordinates rejects out-of-range !3d/!4d pairs via _valid_coordinates (Line 4315-4316), causing _build_place_details to fall into the else branch (Lines 2052-2058). That branch calls _extract_coordinate_from_url, which now also matches the same !3d(...)!4d(...) pattern (Line 4288) but performs no range check before returning the value. An out-of-range/malformed canonical coordinate is thus silently re-admitted through the fallback path instead of being rejected end-to-end.

The !3d/!4d regex is also now duplicated verbatim between the two functions, increasing the chance the checks drift apart further.

As per coding guidelines, **/*.py should "preserve diagnostics and quality flags for partial or uncertain extraction," but this bypass admits unvalidated coordinates without any quality flag.

🛡️ Proposed fix to share the regex and validate the fallback range
+_CANONICAL_COORDINATE_PATTERN = re.compile(r"!3d(-?\d+(?:\.\d+)?)!4d(-?\d+(?:\.\d+)?)")
+
+
 def _extract_coordinate_from_url(url: str, *, index: int) -> float | None:
-    match = re.search(r"!3d(-?\d+(?:\.\d+)?)!4d(-?\d+(?:\.\d+)?)", url)
+    match = _CANONICAL_COORDINATE_PATTERN.search(url)
     if match is None:
         match = re.search(r"@(-?\d+(?:\.\d+)?),(-?\d+(?:\.\d+)?)", url)
     if match is None:
         return None
     try:
-        return float(match.group(index + 1))
+        value = float(match.group(index + 1))
     except ValueError:
         return None
+    bound = 90 if index == 0 else 180
+    if not (-bound <= value <= bound):
+        return None
+    return value

Also applies to: 4299-4319

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/gmaps_scraper/place_scraper.py` around lines 4287 - 4296, Update
_extract_coordinate_from_url and _extract_canonical_place_coordinates to share
one module-level regex for !3d/!4d extraction, and validate extracted
latitude/longitude pairs with _valid_coordinates before returning them. Ensure
fallback extraction cannot re-admit out-of-range or malformed canonical
coordinates, while preserving the existing `@lat`,long fallback behavior and
partial-extraction handling.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@src/gmaps_scraper/place_scraper.py`:
- Around line 4287-4296: Update _extract_coordinate_from_url and
_extract_canonical_place_coordinates to share one module-level regex for !3d/!4d
extraction, and validate extracted latitude/longitude pairs with
_valid_coordinates before returning them. Ensure fallback extraction cannot
re-admit out-of-range or malformed canonical coordinates, while preserving the
existing `@lat`,long fallback behavior and partial-extraction handling.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 8b72a279-2e33-40d1-a62d-1fc27058ae40

📥 Commits

Reviewing files that changed from the base of the PR and between 3d04c84 and 28b36b8.

📒 Files selected for processing (6)
  • docs/ARCHITECTURE.md
  • src/gmaps_scraper/cli.py
  • src/gmaps_scraper/parser.py
  • src/gmaps_scraper/place_scraper.py
  • tests/test_parser.py
  • tests/test_place_scraper.py

@cursor

cursor Bot commented Jul 12, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: serverGenReqId_86f2ffff-235c-4d0e-818f-b7342901f543)

@michaelmwu

Copy link
Copy Markdown
Member Author

Addressed the outside-diff coordinate validation finding from CodeRabbit review 4680412102 in c4bd9af. Canonical !3d/!4d and viewport @lat,lng pairs now share pairwise range validation; an invalid canonical pair cannot be re-admitted through fallback, while valid viewport-only fallback remains covered. Full result: 280 tests, lint, typecheck, and diff-check pass.

@michaelmwu
michaelmwu merged commit f1b676d into main Jul 12, 2026
9 checks passed
@michaelmwu
michaelmwu deleted the codex/harden-place-coordinate-links branch July 12, 2026 23:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant