Skip to content

Commit 69cf166

Browse files
committed
Issue #114/#211/#197 tests for load_geojson and its properties arg
1 parent 5eafa44 commit 69cf166

File tree

6 files changed

+471
-124
lines changed

6 files changed

+471
-124
lines changed

openeo_driver/ProcessGraphDeserializer.py

+9-3
Original file line numberDiff line numberDiff line change
@@ -1581,17 +1581,23 @@ def load_uploaded_files(args: dict, env: EvalEnv) -> Union[DriverVectorCube,Driv
15811581
.returns("vector-cube", schema={"type": "object", "subtype": "vector-cube"})
15821582
)
15831583
def to_vector_cube(args: Dict, env: EvalEnv):
1584-
# TODO: standardization of something like this? https://github.com/Open-EO/openeo-processes/issues/346
1584+
_log.warning("Experimental process `to_vector_cube` is deprecated, use `load_geojson` instead")
1585+
# TODO: remove this experimental/deprecated process
15851586
data = extract_arg(args, "data", process_id="to_vector_cube")
15861587
if isinstance(data, dict) and data.get("type") in {"Polygon", "MultiPolygon", "Feature", "FeatureCollection"}:
15871588
return env.backend_implementation.vector_cube_cls.from_geojson(data)
1588-
# TODO: support more inputs: string with geojson, string with WKT, list of WKT, string with URL to GeoJSON, ...
15891589
raise FeatureUnsupportedException(f"Converting {type(data)} to vector cube is not supported")
15901590

15911591

15921592
@process_registry_100.add_function(spec=read_spec("openeo-processes/2.x/proposals/load_geojson.json"))
15931593
def load_geojson(args: ProcessArgs, env: EvalEnv) -> DriverVectorCube:
1594-
data = args.get_required("data", validator=ProcessArgs.validator_geojson_dict())
1594+
data = args.get_required(
1595+
"data",
1596+
validator=ProcessArgs.validator_geojson_dict(
1597+
# TODO: also allow LineString and MultiLineString?
1598+
allowed_types=["Point", "MultiPoint", "Polygon", "MultiPolygon", "Feature", "FeatureCollection"]
1599+
),
1600+
)
15951601
properties = args.get_optional("properties", default=[], expected_type=(list, tuple))
15961602
vector_cube = env.backend_implementation.vector_cube_cls.from_geojson(data, columns_for_cube=properties)
15971603
return vector_cube

openeo_driver/datacube.py

+21-2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
import geopandas as gpd
1010
import numpy
11+
import pandas
1112
import pyproj
1213
import shapely.geometry
1314
import shapely.geometry.base
@@ -284,14 +285,21 @@ def from_geodataframe(
284285
elif columns_for_cube == cls.COLUMN_SELECTION_ALL:
285286
columns_for_cube = available_columns
286287
elif isinstance(columns_for_cube, list):
287-
# TODO #114 limit to subset with available columns (and automatically fill in missing columns with nodata)?
288288
columns_for_cube = columns_for_cube
289289
else:
290290
raise ValueError(columns_for_cube)
291291
assert isinstance(columns_for_cube, list)
292292

293293
if columns_for_cube:
294-
cube_df = data[columns_for_cube]
294+
existing = [c for c in columns_for_cube if c in available_columns]
295+
to_add = [c for c in columns_for_cube if c not in available_columns]
296+
if existing:
297+
cube_df = data[existing]
298+
if to_add:
299+
cube_df.loc[:, to_add] = numpy.nan
300+
else:
301+
cube_df = pandas.DataFrame(index=data.index, columns=to_add)
302+
295303
# TODO: remove `columns_for_cube` from geopandas data frame?
296304
# Enabling that triggers failure of som existing tests that use `aggregate_spatial`
297305
# to "enrich" a vector cube with pre-existing properties
@@ -311,6 +319,7 @@ def from_geodataframe(
311319
return cls(geometries=geometries_df, cube=cube)
312320

313321
else:
322+
# TODO: add a dummy 1D no-data cube?
314323
return cls(geometries=data)
315324

316325
@classmethod
@@ -429,6 +438,16 @@ def to_wkt(self) -> List[str]:
429438
wkts = [str(g) for g in self._geometries.geometry]
430439
return wkts
431440

441+
def to_internal_json(self) -> dict:
442+
"""
443+
Export to an internal JSON-style representation.
444+
Subject to change any time: not intended for public consumption, just for (unit) test purposes.
445+
"""
446+
return {
447+
"geometries": shapely.geometry.mapping(self._geometries),
448+
"cube": self._cube.to_dict(data="array") if self._cube is not None else None,
449+
}
450+
432451
def get_crs(self) -> pyproj.CRS:
433452
return self._geometries.crs or pyproj.CRS.from_epsg(4326)
434453

openeo_driver/testing.py

+6
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import http.server
77
import json
88
import logging
9+
import math
910
import multiprocessing
1011
import re
1112
import urllib.request
@@ -494,6 +495,11 @@ def approxify(x: Any, rel: Optional = None, abs: Optional[float] = None) -> Any:
494495
raise ValueError(x)
495496

496497

498+
class IsNan:
499+
def __eq__(self, other):
500+
return isinstance(other, float) and math.isnan(other)
501+
502+
497503
class ApproxGeometry:
498504
"""Helper to compactly and approximately compare geometries."""
499505

tests/test_testing.py

+15
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import logging
22
import re
33
import subprocess
4+
5+
import numpy
46
import sys
57
import textwrap
68
import urllib.error
@@ -22,6 +24,7 @@
2224
ephemeral_fileserver,
2325
preprocess_check_and_replace,
2426
ApproxGeoJSONByBounds,
27+
IsNan,
2528
)
2629

2730

@@ -261,6 +264,18 @@ def test_approxify_tolerance_rel():
261264
assert {"a": [10.1, 2.1]} != approxify({"a": [10, 2.3]}, rel=0.01)
262265

263266

267+
@pytest.mark.parametrize("other", [float("nan"), numpy.nan])
268+
def test_is_nan(other):
269+
assert other == IsNan()
270+
assert IsNan() == other
271+
272+
273+
@pytest.mark.parametrize("other", [0, 123, False, True, None, "dfd", [], {}, ()])
274+
def test_is_not_nan(other):
275+
assert other != IsNan()
276+
assert IsNan() != other
277+
278+
264279
@pytest.mark.parametrize(
265280
"format",
266281
[

0 commit comments

Comments
 (0)