Skip to content

Commit

Permalink
fix(geometry): make output handling robust to text or bytes
Browse files Browse the repository at this point in the history
  • Loading branch information
cpcloud committed Nov 13, 2024
1 parent 197e964 commit 49b404a
Show file tree
Hide file tree
Showing 15 changed files with 64 additions and 105 deletions.
9 changes: 4 additions & 5 deletions ibis/backends/bigquery/converter.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@ def convert_GeoSpatial(cls, s, dtype, pandas_type):
import geopandas as gpd
import shapely as shp

return gpd.GeoSeries(shp.from_wkb(s))

convert_Point = convert_LineString = convert_Polygon = convert_MultiLineString = (
convert_MultiPoint
) = convert_MultiPolygon = convert_GeoSpatial
try:
return gpd.GeoSeries.from_wkt(s)
except shp.geos.GEOSException:
return gpd.GeoSeries.from_wkb(s)
29 changes: 29 additions & 0 deletions ibis/backends/bigquery/tests/system/test_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -460,3 +460,32 @@ def test_geospatial_interactive(con, monkeypatch):
)
result = repr(expr)
assert "POLYGON" in result


def test_geom_from_pyarrow(con, monkeypatch):
shp = pytest.importorskip("shapely")

monkeypatch.setattr(ibis.options, "interactive", True)

data = pa.Table.from_pydict(
{
"id": [1, 2],
"location": [
shp.Point(1, 1).wkb,
shp.Point(2, 2).wkb,
],
}
)

# Create table in BigQuery
name = gen_name("bq_test_geom")
schema = ibis.schema({"id": "int64", "location": "geospatial:geography;4326"})

t = con.create_table(name, data, schema=schema)

try:
assert repr(t)
assert len(t.to_pyarrow()) == 2
assert len(t.to_pandas()) == 2
finally:
con.drop_table(name)
Original file line number Diff line number Diff line change
@@ -1,8 +1,3 @@
SELECT
*
REPLACE (st_asbinary(`tmp`) AS `tmp`)
FROM (
SELECT
st_difference(`t0`.`geog0`, `t0`.`geog1`) AS `tmp`
FROM `t` AS `t0`
)
st_difference(`t0`.`geog0`, `t0`.`geog1`) AS `tmp`
FROM `t` AS `t0`
Original file line number Diff line number Diff line change
@@ -1,8 +1,3 @@
SELECT
*
REPLACE (st_asbinary(`tmp`) AS `tmp`)
FROM (
SELECT
st_intersection(`t0`.`geog0`, `t0`.`geog1`) AS `tmp`
FROM `t` AS `t0`
)
st_intersection(`t0`.`geog0`, `t0`.`geog1`) AS `tmp`
FROM `t` AS `t0`
Original file line number Diff line number Diff line change
@@ -1,8 +1,3 @@
SELECT
*
REPLACE (st_asbinary(`tmp`) AS `tmp`)
FROM (
SELECT
st_union(`t0`.`geog0`, `t0`.`geog1`) AS `tmp`
FROM `t` AS `t0`
)
st_union(`t0`.`geog0`, `t0`.`geog1`) AS `tmp`
FROM `t` AS `t0`
Original file line number Diff line number Diff line change
@@ -1,8 +1,3 @@
SELECT
*
REPLACE (st_asbinary(`tmp`) AS `tmp`)
FROM (
SELECT
st_geogpoint(`t0`.`lon`, `t0`.`lat`) AS `tmp`
FROM `t` AS `t0`
)
st_geogpoint(`t0`.`lon`, `t0`.`lat`) AS `tmp`
FROM `t` AS `t0`
Original file line number Diff line number Diff line change
@@ -1,8 +1,3 @@
SELECT
*
REPLACE (st_asbinary(`tmp`) AS `tmp`)
FROM (
SELECT
st_simplify(`t0`.`geog`, 5.2) AS `tmp`
FROM `t` AS `t0`
)
st_simplify(`t0`.`geog`, 5.2) AS `tmp`
FROM `t` AS `t0`
Original file line number Diff line number Diff line change
@@ -1,8 +1,3 @@
SELECT
*
REPLACE (st_asbinary(`tmp`) AS `tmp`)
FROM (
SELECT
st_buffer(`t0`.`geog`, 5.2) AS `tmp`
FROM `t` AS `t0`
)
st_buffer(`t0`.`geog`, 5.2) AS `tmp`
FROM `t` AS `t0`
Original file line number Diff line number Diff line change
@@ -1,8 +1,3 @@
SELECT
*
REPLACE (st_asbinary(`tmp`) AS `tmp`)
FROM (
SELECT
st_centroid(`t0`.`geog`) AS `tmp`
FROM `t` AS `t0`
)
st_centroid(`t0`.`geog`) AS `tmp`
FROM `t` AS `t0`
Original file line number Diff line number Diff line change
@@ -1,8 +1,3 @@
SELECT
*
REPLACE (st_asbinary(`tmp`) AS `tmp`)
FROM (
SELECT
st_endpoint(`t0`.`geog`) AS `tmp`
FROM `t` AS `t0`
)
st_endpoint(`t0`.`geog`) AS `tmp`
FROM `t` AS `t0`
Original file line number Diff line number Diff line change
@@ -1,8 +1,3 @@
SELECT
*
REPLACE (st_asbinary(`tmp`) AS `tmp`)
FROM (
SELECT
st_pointn(`t0`.`geog`, 3) AS `tmp`
FROM `t` AS `t0`
)
st_pointn(`t0`.`geog`, 3) AS `tmp`
FROM `t` AS `t0`
Original file line number Diff line number Diff line change
@@ -1,8 +1,3 @@
SELECT
*
REPLACE (st_asbinary(`tmp`) AS `tmp`)
FROM (
SELECT
st_startpoint(`t0`.`geog`) AS `tmp`
FROM `t` AS `t0`
)
st_startpoint(`t0`.`geog`) AS `tmp`
FROM `t` AS `t0`
Original file line number Diff line number Diff line change
@@ -1,8 +1,3 @@
SELECT
*
REPLACE (st_asbinary(`tmp`) AS `tmp`)
FROM (
SELECT
st_union_agg(`t0`.`geog`) AS `tmp`
FROM `t` AS `t0`
)
st_union_agg(`t0`.`geog`) AS `tmp`
FROM `t` AS `t0`
19 changes: 0 additions & 19 deletions ibis/backends/sql/compilers/bigquery/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,6 @@ def to_sqlglot(
sql = super().to_sqlglot(expr, limit=limit, params=params)

table_expr = expr.as_table()
geocols = table_expr.schema().geospatial

memtable_names = frozenset(
op.name for op in table_expr.op().find(ops.InMemoryTable)
Expand All @@ -250,24 +249,6 @@ def to_sqlglot(
memtable_names=memtable_names,
).transform(_remove_null_ordering_from_unsupported_window)

if geocols:
# if there are any geospatial columns, we have to convert them to WKB,
# so interactive mode knows how to display them
#
# by default bigquery returns data to python as WKT, and there's really
# no point in supporting both if we don't need to.
quoted = self.quoted
result = sg.select(
sge.Star(
replace=[
self.f.st_asbinary(sg.column(col, quoted=quoted)).as_(
col, quoted=quoted
)
for col in geocols
]
)
).from_(result.subquery())

sources = []

for udf_node in table_expr.op().find(ops.ScalarUDF):
Expand Down
13 changes: 9 additions & 4 deletions ibis/expr/types/pretty.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,15 @@ def _(dtype, values, **fmt_kwargs):
def _(dtype, values, **fmt_kwargs):
import shapely

return _format_nested(
[shapely.from_wkb(v) if isinstance(v, (bytes, str)) else v for v in values],
**fmt_kwargs,
)
def try_parse(v):
if v is None:
return v
try:
return shapely.from_wkb(v)
except shapely.errors.GEOSException:
return shapely.from_wkt(v)

return _format_nested(map(try_parse, values), **fmt_kwargs)


@format_values.register(dt.JSON)
Expand Down

0 comments on commit 49b404a

Please sign in to comment.