Skip to content

feat: detect GeoArrow columns in PyArrow tables - #10558

Merged
kirangadhave merged 6 commits into
kg/geometry-contract-geopandasfrom
kg/geometry-pyarrow-adapter
Aug 20, 2026
Merged

feat: detect GeoArrow columns in PyArrow tables#10558
kirangadhave merged 6 commits into
kg/geometry-contract-geopandasfrom
kg/geometry-pyarrow-adapter

Conversation

@kirangadhave

@kirangadhave kirangadhave commented Aug 14, 2026

Copy link
Copy Markdown
Member

Summary

Detect GeoArrow extension metadata on PyArrow tables as the geometry semantic type (MO-6362).

The generic NarwhalsTableManager formats geometry cells in to_json_str and preserves PyArrow field metadata through apply_formatting. Existing host guards (search, sort, stats, top-k, unique values) activate via _geometry_columns with no new guard code.

GeoPandas and pandas tables are unchanged; they continue to use PandasTableManager overrides from #10536.

No frontend changes.

🗺️ Stack

This PR is part of a four-PR stack that adds a semantic geometry type for geospatial columns (MO-6362). Merge bottom-up with squash. Each PR targets the branch below it, so each diff shows only its own commits. After each merge, I rebase the remaining PRs.

  1. test: add geometry fixture corpus and baselines #10516: geometry fixture corpus and ordinary-table baselines
  2. feat: add GeoPandas geometry table support #10536: geometry contract and GeoPandas detection
  3. feat: detect GeoArrow columns in PyArrow tables #10558: PyArrow adapter (GeoArrow field metadata) ⬅️ this PR
  4. feat: detect duckdb spatial columns as geometry #10592: DuckDB adapter and SQL metadata (completes the release gate)

ibis detection is deferred: no user demand, and nothing downstream depends on it.

Important

Release gate: do not include this PR in a marimo release until #10592 also merges.

Closes MO-7324

@vercel

vercel Bot commented Aug 14, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
marimo-docs Ready Ready Preview Aug 20, 2026 8:05pm

Request Review

@github-actions

Copy link
Copy Markdown
Contributor

All contributors have signed the CLA ✍️ ✅
Posted by the CLA Assistant Lite bot.

@kirangadhave
kirangadhave marked this pull request as ready for review August 14, 2026 22:38
Copilot AI lite review requested due to automatic review settings August 14, 2026 22:38
@kirangadhave kirangadhave added enhancement New feature or request bash-focus Area to focus on during release bug bash labels Aug 14, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR extends marimo’s table geometry support to PyArrow-backed (Narwhals) tables by detecting GeoArrow extension metadata and treating those columns as the geometry semantic type, ensuring correct serialization and operation-guard behavior.

Changes:

  • Detect GeoArrow geometry columns in PyArrow tables by reading ARROW:extension:name field metadata (geoarrow.*, ogc.wkb).
  • Format geometry cells during NarwhalsTableManager.to_json_str() (WKB → placeholder; WKT/objects → capped text) while preserving schema metadata across apply_formatting().
  • Add/update characterization and contract tests covering detection, formatting, and guard behavior (search/top-k/unique/stats).

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated no comments.

File Description
tests/_plugins/ui/_impl/tables/test_geometry.py Adds PyArrow/GeoArrow detection + manager behavior tests (serialization + operation guards).
tests/_plugins/ui/_impl/tables/test_geometry_fixtures.py Updates GeoArrow characterization expectations to geometry semantic type.
marimo/_plugins/ui/_impl/tables/narwhals_table.py Formats geometry cells in JSON output and changes formatting application to preserve PyArrow field metadata.
marimo/_plugins/ui/_impl/tables/geometry.py Adds PyArrow GeoArrow detection via field extension metadata parsing.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

All reported issues were addressed across 4 files

Architecture diagram
sequenceDiagram
    participant UI as Marimo UI
    participant TM as Table Manager
    participant NTM as NarwhalsTableManager
    participant GEO as Geometry Utils
    participant NW as Narwhals Frame
    participant PA as PyArrow Table

    Note over UI,PA: GeoArrow Column Detection and Formatting Flow

    UI->>TM: Request table data
    TM->>NTM: get_field_types()
    
    NTM->>GEO: find_geometry_columns(frame)
    GEO->>NW: Check implementation type
    
    alt PyArrow implementation
        NW-->>GEO: is_pyarrow() = true
        GEO->>PA: Get schema fields
        PA-->>GEO: Field metadata
        
        loop For each field
            GEO->>GEO: Read ARROW:extension:name
            alt geoarrow.wkb or ogc.wkb
                GEO->>GEO: Set encoding = "wkb"
            else geoarrow.wkt
                GEO->>GEO: Set encoding = "wkt"
            else geoarrow.* prefix
                GEO->>GEO: Set encoding = "other"
            else Non-geo extension
                GEO->>GEO: Skip column
            end
        end
        
        GEO-->>NTM: Geometry column map
        NTM-->>TM: Field types with "geometry" semantic
    else Pandas implementation
        NW-->>GEO: is_pandas() = true
        GEO->>GEO: Use Pandas-specific detection
        GEO-->>NTM: Geometry column map
        NTM-->>TM: Field types with "geometry" semantic
    end

    Note over UI,PA: Table JSON Serialization Flow
    
    UI->>TM: Get table data (to_json_str)
    TM->>NTM: to_json_str()
    
    NTM->>NTM: Apply formatting if mapping
    
    alt Format mapping provided
        NTM->>NW: Apply column formatting
        loop For each formatted column
            NTM->>NW: Create new series
            NW->>PA: with_columns()
            PA-->>NW: Updated table with preserved metadata
        end
    end
    
    NTM->>NW: Get rows as named dicts
    NW-->>NTM: Row data with raw geometry values
    
    alt Geometry columns found
        loop For each row
            loop For each column
                alt Is geometry column
                    NTM->>GEO: format_geometry_cell(value, encoding)
                    alt WKB encoding
                        GEO->>GEO: Generate placeholder with byte size
                    else WKT encoding
                        GEO->>GEO: Pass through text, cap length
                    else Other encoding
                        GEO->>GEO: Skip or minimal formatting
                    end
                    GEO-->>NTM: Formatted geometry value
                end
            end
        end
    end
    
    NTM->>NTM: sanitize_json_bigint()
    NTM-->>UI: JSON string with formatted geometry

    Note over UI,PA: Downstream Operations
    
    UI->>TM: Search / sort / stats request
    TM->>NTM: Operation on geometry column
    
    NTM->>GEO: Check _geometry_columns
    
    alt Search on geometry
        NTM-->>TM: Skip search (0 results)
    else Top-K on geometry
        NTM-->>TM: Return empty list
    else Unique values on geometry
        NTM-->>TM: Return empty list
    else Stats on geometry
        NTM->>PA: Count total and nulls
        PA-->>NTM: Stats with unique = null
        NTM-->>TM: Stats summary
    end
Loading

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread marimo/_plugins/ui/_impl/tables/narwhals_table.py
mscolnick
mscolnick previously approved these changes Aug 20, 2026
@kirangadhave
kirangadhave force-pushed the kg/geometry-contract-geopandas branch from fee6cd1 to 9d1c439 Compare August 20, 2026 18:05
@kirangadhave
kirangadhave force-pushed the kg/geometry-pyarrow-adapter branch from f1a83b2 to 50c03c5 Compare August 20, 2026 18:05
@kirangadhave
kirangadhave requested a review from mscolnick August 20, 2026 18:10
kirangadhave added a commit that referenced this pull request Aug 20, 2026
## 📝 Summary

Add shared geometry fixtures and current-behavior baselines for the
geospatial foundation work in MO-6362. Freeze false-positive and
ordinary-table payloads, and keep geometry characterization local until
it runs reliably in CI.

## 🗺️ Stack

This PR is part of a four-PR stack that adds a semantic `geometry` type
for geospatial columns
([MO-6362](https://linear.app/marimo/issue/MO-6362)). Merge bottom-up
with squash. Each PR targets the branch below it, so each diff shows
only its own commits. After each merge, I rebase the remaining PRs.

1. #10516: geometry fixture corpus and ordinary-table baselines ⬅️ this
PR
2. #10536: `geometry` contract and GeoPandas detection
3. #10558: PyArrow adapter (GeoArrow field metadata)
4. #10592: DuckDB adapter and SQL metadata (completes the release gate)

ibis detection is deferred: no user demand, and nothing downstream
depends on it.

Closes MO-7322
apply_formatting must not rebuild geometry columns via new_series, which
drops GeoArrow field metadata. to_json_str now reads geometry detection
from the formatted manager so the two views stay aligned.
@kirangadhave
kirangadhave force-pushed the kg/geometry-contract-geopandas branch from 9d1c439 to 501d40f Compare August 20, 2026 18:14
@kirangadhave
kirangadhave merged commit 4e6b1c5 into kg/geometry-contract-geopandas Aug 20, 2026
39 checks passed
@kirangadhave
kirangadhave deleted the kg/geometry-pyarrow-adapter branch August 20, 2026 20:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bash-focus Area to focus on during release bug bash enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants