diff --git a/CHANGELOG.md b/CHANGELOG.md index 8cd8e54c4..76b158e6a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Add support for `log_level` in `create_job()` and `execute_job()` ([#704](https://github.com/Open-EO/openeo-python-client/issues/704)) - Add initial support for "geometry" dimension type in `CubeMetadata` ([#705](https://github.com/Open-EO/openeo-python-client/issues/705)) - Add support for parameterized `bands` argument in `load_stac()` +- Argument `spatial_extent` in `load_collection` supports type `shapely` and loading geometry from a local path. ### Changed diff --git a/openeo/rest/connection.py b/openeo/rest/connection.py index 5407c8839..e33e99b1d 100644 --- a/openeo/rest/connection.py +++ b/openeo/rest/connection.py @@ -1256,7 +1256,7 @@ def datacube_from_json(self, src: Union[str, Path], parameters: Optional[dict] = def load_collection( self, collection_id: Union[str, Parameter], - spatial_extent: Union[Dict[str, float], Parameter, None] = None, + spatial_extent: Union[Dict[str, float], Parameter, shapely.geometry.base.BaseGeometry, None] = None, temporal_extent: Union[Sequence[InputDate], Parameter, str, None] = None, bands: Union[Iterable[str], Parameter, str, None] = None, properties: Union[ @@ -1269,7 +1269,12 @@ def load_collection( Load a DataCube by collection id. :param collection_id: image collection identifier - :param spatial_extent: limit data to specified bounding box or polygons + :param spatial_extent: limit data to specified bounding box or polygons. Can be provided in different ways: + - a shapely geometry + - a GeoJSON-style dictionary, + - a path (:py:class:`str` or :py:class:`~pathlib.Path`) to a local, client-side GeoJSON file, + which will be loaded automatically to get the geometries as GeoJSON construct. + - a :py:class:`~openeo.api.process.Parameter` instance. :param temporal_extent: limit data to specified temporal interval. Typically, just a two-item list or tuple containing start and end date. See :ref:`filtering-on-temporal-extent-section` for more details on temporal extent handling and shorthand notation. diff --git a/openeo/rest/datacube.py b/openeo/rest/datacube.py index 3aa737db7..5e80d23da 100644 --- a/openeo/rest/datacube.py +++ b/openeo/rest/datacube.py @@ -158,7 +158,12 @@ def load_collection( :param collection_id: image collection identifier :param connection: The backend connection to use. Can be ``None`` to work without connection and collection metadata. - :param spatial_extent: limit data to specified bounding box or polygons + :param spatial_extent: limit data to specified bounding box or polygons. Can be provided in different ways: + - a shapely geometry + - a GeoJSON-style dictionary, + - a path (:py:class:`str` or :py:class:`~pathlib.Path`) to a local, client-side GeoJSON file, + which will be loaded automatically to get the geometries as GeoJSON construct. + - a :py:class:`~openeo.api.process.Parameter` instance. :param temporal_extent: limit data to specified temporal interval. Typically, just a two-item list or tuple containing start and end date. See :ref:`filtering-on-temporal-extent-section` for more details on temporal extent handling and shorthand notation. @@ -188,7 +193,7 @@ def load_collection( f" expected schema compatible with type 'object' but got {spatial_extent.schema!r}." ) valid_geojson_types = [ - "Polygon", "MultiPolygon", "GeometryCollection", "FeatureCollection" + "Polygon", "MultiPolygon", "Feature", "FeatureCollection" ] if spatial_extent and not (isinstance(spatial_extent, dict) and spatial_extent.keys() & {"west", "east", "north", "south"}): spatial_extent = _get_geometry_argument(argument=spatial_extent,valid_geojson_types=valid_geojson_types,connection=connection) diff --git a/tests/rest/datacube/test_datacube.py b/tests/rest/datacube/test_datacube.py index 5121cf645..48a05444f 100644 --- a/tests/rest/datacube/test_datacube.py +++ b/tests/rest/datacube/test_datacube.py @@ -150,6 +150,20 @@ def test_load_collection_connectionless_shapely_spatial_extent(self): } } + @pytest.mark.parametrize("path_factory", [str, pathlib.Path]) + def test_load_collection_connectionless_local_path_spatial_extent(self, path_factory, test_data): + path = path_factory(test_data.get_path("geojson/polygon02.json")) + cube = DataCube.load_collection("T3", spatial_extent=path) + assert cube.flat_graph() == { + "loadcollection1": { + "arguments": {"id": "T3", "spatial_extent": + {"type": "Polygon", "coordinates": [[[3, 50], [4, 50], [4, 51], [3, 50]]]}, + "temporal_extent": None}, + "process_id": "load_collection", + "result": True, + } + } + def test_load_collection_connectionless_save_result(self): cube = DataCube.load_collection("T3").save_result(format="GTiff") assert cube.flat_graph() == {