This is an automated email from the ASF dual-hosted git repository.

paleolimbot pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/sedona-db.git


The following commit(s) were added to refs/heads/main by this push:
     new 8c837de9 feat(python/sedonadb): Handle crs-like objects in 
parameterized queries (#660)
8c837de9 is described below

commit 8c837de94ac551b536768c1588c0e8ea57241c17
Author: Dewey Dunnington <[email protected]>
AuthorDate: Thu Feb 26 08:49:56 2026 -0600

    feat(python/sedonadb): Handle crs-like objects in parameterized queries 
(#660)
---
 python/sedonadb/python/sedonadb/expr/literal.py | 10 +++++++++-
 python/sedonadb/tests/expr/test_literal.py      | 21 +++++++++++++++++++++
 2 files changed, 30 insertions(+), 1 deletion(-)

diff --git a/python/sedonadb/python/sedonadb/expr/literal.py 
b/python/sedonadb/python/sedonadb/expr/literal.py
index cbde54d8..b65960a1 100644
--- a/python/sedonadb/python/sedonadb/expr/literal.py
+++ b/python/sedonadb/python/sedonadb/expr/literal.py
@@ -71,7 +71,8 @@ def lit(value: Any) -> Literal:
     - SedonaDB DataFrame objects that evaluate to a single column and
       row become a scalar value according to the single represented
       value.
-
+    - pyproj CRS objects become PROJJSON strings (e.g., so they may be used
+      in `ST_SetCRS()`, `ST_Point()`, or `ST_GeomFromWKT()`).
     """
     if isinstance(value, Literal):
         return value
@@ -155,11 +156,17 @@ def _lit_from_wkb_and_crs(wkb, crs):
     return type.wrap_array(storage)
 
 
+def _lit_from_crs(crs):
+    return _resolve_arrow_lit(crs.to_json())
+
+
 def _qualified_type_name(obj):
     return f"{type(obj).__module__}.{type(obj).__name__}"
 
 
 SPECIAL_CASED_LITERALS = {
+    "geoarrow.types.crs.ProjJsonCrs": _lit_from_crs,
+    "geoarrow.types.crs.StringCrs": _lit_from_crs,
     "geopandas.geodataframe.GeoDataFrame": _lit_from_dataframe,
     "geopandas.geoseries.GeoSeries": _lit_from_series,
     # pandas < 3.0
@@ -168,6 +175,7 @@ SPECIAL_CASED_LITERALS = {
     # pandas >= 3.0
     "pandas.DataFrame": _lit_from_dataframe,
     "pandas.Series": _lit_from_series,
+    "pyproj.crs.crs.CRS": _lit_from_crs,
     "sedonadb.dataframe.DataFrame": _lit_from_sedonadb,
     "shapely.geometry.point.Point": _lit_from_shapely,
     "shapely.geometry.linestring.LineString": _lit_from_shapely,
diff --git a/python/sedonadb/tests/expr/test_literal.py 
b/python/sedonadb/tests/expr/test_literal.py
index b1941131..51f0957f 100644
--- a/python/sedonadb/tests/expr/test_literal.py
+++ b/python/sedonadb/tests/expr/test_literal.py
@@ -149,3 +149,24 @@ def test_sedonadb_literal(con):
     with pytest.raises(ValueError, match="size != 1 row"):
         df = con.sql("SELECT 1 as one WHERE false")
         pa.array(lit(df))
+
+
+def test_crs_literal():
+    import pyproj
+
+    crs = pyproj.CRS("EPSG:26920")
+    assert pa.array(lit(crs)) == pa.array([crs.to_json()])
+
+    # Ensure this is also the case for whatever GeoSeries.crs returns
+    geoseries = geopandas.GeoSeries.from_wkt(["POINT (0 1)"], crs="EPSG:26920")
+    assert pa.array(lit(geoseries.crs)) == pa.array([crs.to_json()])
+
+    # Make sure geoarrow.pyarrow CRSes also work here
+
+    # A ProjjsonCrs
+    ga_crs = ga.wkb().with_crs(crs).crs
+    assert pa.array(lit(ga_crs)) == pa.array([crs.to_json()])
+
+    # A StringCrs
+    ga_crs = ga.wkb().with_crs("EPSG:26920").crs
+    assert pa.array(lit(ga_crs)) == pa.array([crs.to_json()])

Reply via email to