Repository: ibis-project/ibis

Issue:
feat: add an example geo dataset to `ibis.examples`
Having an example geo dataset in `ibis.examples` would make it easier to demonstrate the new geo functionality added in the duckdb backend.


Discussion:

Resolving patch:
diff --git a/ibis/examples/__init__.py b/ibis/examples/__init__.py
--- a/ibis/examples/__init__.py
+++ b/ibis/examples/__init__.py
@@ -126,6 +126,33 @@ def __dir__() -> list[str]:
     return sorted(_get_metadata().keys())
 
 
+class Zones(Concrete):
+    name: str
+    help: Optional[str]
+
+    def fetch(
+        self,
+        *,
+        table_name: str | None = None,
+        backend: BaseBackend | None = None,
+    ) -> ir.Table:
+        if backend is None:
+            backend = ibis.get_backend()
+
+        name = self.name
+
+        if table_name is None:
+            table_name = name
+
+        board = _get_board()
+
+        (path,) = board.pin_download(name)
+        return backend.read_geo(path)
+
+
+zones = Zones("zones", help="Taxi zones in New York City (EPSG:2263)")
+
+
 def __getattr__(name: str) -> Example:
     try:
         meta = _get_metadata()
diff --git a/ibis/examples/gen_registry.py b/ibis/examples/gen_registry.py
--- a/ibis/examples/gen_registry.py
+++ b/ibis/examples/gen_registry.py
@@ -11,6 +11,7 @@
 from collections import Counter
 from pathlib import Path
 from typing import TYPE_CHECKING, Any
+from urllib.request import urlretrieve
 
 import pins
 import requests
@@ -107,6 +108,16 @@ def add_movielens_example(
             con.read_csv(csv_path).to_parquet(parquet_path, codec="zstd")
 
 
+def add_zones_geojson(data_path: Path) -> None:
+    file_name = "zones.geojson"
+    url = "https://raw.githubusercontent.com/ibis-project/testing-data/master/geojson/zones.geojson"
+
+    file_path = Path(file_name)
+
+    if not file_path.exists():
+        urlretrieve(url, data_path / file_path)
+
+
 def add_imdb_example(data_path: Path) -> None:
     def convert_to_parquet(
         base: Path,
@@ -229,6 +240,8 @@ def main(parser):
 
     add_wowah_example(data_path, client=storage.Client(), metadata=metadata)
 
+    add_zones_geojson(data_path)
+
     # generate data from R
     subprocess.check_call(["Rscript", str(EXAMPLES_DIRECTORY / "gen_examples.R")])
 


Test patch:
diff --git a/ibis/backends/tests/test_examples.py b/ibis/backends/tests/test_examples.py
--- a/ibis/backends/tests/test_examples.py
+++ b/ibis/backends/tests/test_examples.py
@@ -49,3 +49,39 @@ def test_load_examples(con, example, columns):
     t = getattr(ibis.examples, example).fetch(backend=con)
     assert t.columns == columns
     assert t.count().execute() > 0
+
+
+@pytest.mark.skipif(
+    (LINUX or MACOS) and SANDBOXED,
+    reason="nix on linux cannot download duckdb extensions or data due to sandboxing",
+)
+@pytest.mark.notimpl(
+    [
+        # everything except duckdb
+        "bigquery",
+        "clickhouse",
+        "dask",
+        "datafusion",
+        "druid",
+        "exasol",
+        "flink",
+        "impala",
+        "mssql",
+        "mysql",
+        "oracle",
+        "pandas",
+        "polars",
+        "postgres",
+        "pyspark",
+        "snowflake",
+        "sqlite",
+        "trino",
+    ]
+)
+def test_load_geo_example(con):
+    pytest.importorskip("geopandas")
+    pytest.importorskip("shapely")
+    pytest.importorskip("geoalchemy2")
+
+    t = ibis.examples.zones.fetch(backend=con)
+    assert t.geom.type().is_geospatial()