Skip to content

Commit 88f4359

Browse files
committed
Issue #424 initial support for load_url (vector cubes)
1 parent dd7ad7e commit 88f4359

File tree

5 files changed

+81
-2
lines changed

5 files changed

+81
-2
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1010
### Added
1111

1212
- Initial `load_geojson` support with `Connection.load_geojson()` ([#424](https://github.com/Open-EO/openeo-python-client/issues/424))
13+
- Initial `load_url` (for vector cubes) support with `Connection.load_url()` ([#424](https://github.com/Open-EO/openeo-python-client/issues/424))
1314

1415
### Changed
1516

openeo/rest/connection.py

+24-1
Original file line numberDiff line numberDiff line change
@@ -802,6 +802,9 @@ def capabilities(self) -> RESTCapabilities:
802802
load=lambda: RESTCapabilities(data=self.get('/', expected_status=200).json(), url=self._orig_url)
803803
)
804804

805+
def list_input_formats(self) -> dict:
806+
return self.list_file_formats().get("input", {})
807+
805808
def list_output_formats(self) -> dict:
806809
return self.list_file_formats().get("output", {})
807810

@@ -1319,7 +1322,6 @@ def load_geojson(
13191322
"""
13201323
Converts GeoJSON data as defined by RFC 7946 into a vector data cube.
13211324
1322-
:param connection: the connection to use to connect with the openEO back-end.
13231325
:param data: the geometry to load. One of:
13241326
13251327
- GeoJSON-style data structure: e.g. a dictionary with ``"type": "Polygon"`` and ``"coordinates"`` fields
@@ -1337,6 +1339,27 @@ def load_geojson(
13371339

13381340
return VectorCube.load_geojson(connection=self, data=data, properties=properties)
13391341

1342+
@openeo_process
1343+
def load_url(self, url: str, format: str, options: Optional[dict] = None):
1344+
"""
1345+
Loads a file from a URL
1346+
1347+
:param url: The URL to read from. Authentication details such as API keys or tokens may need to be included in the URL.
1348+
:param format: The file format to use when loading the data.
1349+
:param options: The file format parameters to use when reading the data.
1350+
Must correspond to the parameters that the server reports as supported parameters for the chosen ``format``
1351+
:return: new VectorCube instance
1352+
1353+
.. warning:: EXPERIMENTAL: this process is experimental with the potential for major things to change.
1354+
1355+
.. versionadded:: 0.22.0
1356+
"""
1357+
if format not in self.list_input_formats():
1358+
# TODO: make this an error?
1359+
_log.warning(f"Format {format!r} not listed in back-end input formats")
1360+
# TODO: Inspect format's gis_data_type to see if we need to load a VectorCube or classic raster DataCube
1361+
return VectorCube.load_url(connection=self, url=url, format=format, options=options)
1362+
13401363
def create_service(self, graph: dict, type: str, **kwargs) -> Service:
13411364
# TODO: type hint for graph: is it a nested or a flat one?
13421365
req = self._build_request_with_process_graph(process_graph=graph, type=type, **kwargs)

openeo/rest/vectorcube.py

+24-1
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ def load_geojson(
5858
connection: "openeo.Connection",
5959
data: Union[dict, str, pathlib.Path, shapely.geometry.base.BaseGeometry, Parameter],
6060
properties: Optional[List[str]] = None,
61-
):
61+
) -> "VectorCube":
6262
"""
6363
Converts GeoJSON data as defined by RFC 7946 into a vector data cube.
6464
@@ -78,6 +78,7 @@ def load_geojson(
7878
.. versionadded:: 0.22.0
7979
"""
8080
# TODO: unify with `DataCube._get_geometry_argument`
81+
# TODO: also support client side fetching of GeoJSON from URL?
8182
if isinstance(data, str) and data.strip().startswith("{"):
8283
# Assume JSON dump
8384
geometry = json.loads(data)
@@ -98,6 +99,28 @@ def load_geojson(
9899
pg = PGNode(process_id="load_geojson", data=geometry, properties=properties or [])
99100
return cls(graph=pg, connection=connection)
100101

102+
@classmethod
103+
@openeo_process
104+
def load_url(
105+
cls, connection: "openeo.Connection", url: str, format: str, options: Optional[dict] = None
106+
) -> "VectorCube":
107+
"""
108+
Loads a file from a URL
109+
110+
:param connection: the connection to use to connect with the openEO back-end.
111+
:param url: The URL to read from. Authentication details such as API keys or tokens may need to be included in the URL.
112+
:param format: The file format to use when loading the data.
113+
:param options: The file format parameters to use when reading the data.
114+
Must correspond to the parameters that the server reports as supported parameters for the chosen ``format``
115+
:return: new VectorCube instance
116+
117+
.. warning:: EXPERIMENTAL: this process is experimental with the potential for major things to change.
118+
119+
.. versionadded:: 0.22.0
120+
"""
121+
pg = PGNode(process_id="load_url", arguments=dict_no_none(url=url, format=format, options=options))
122+
return cls(graph=pg, connection=connection)
123+
101124
@openeo_process
102125
def run_udf(
103126
self,

tests/rest/datacube/test_vectorcube.py

+13
Original file line numberDiff line numberDiff line change
@@ -240,3 +240,16 @@ def test_load_geojson_parameter(con100, dummy_backend):
240240
"result": True,
241241
}
242242
}
243+
244+
245+
def test_load_url(con100, dummy_backend):
246+
vc = VectorCube.load_url(connection=con100, url="https://example.com/geometry.json", format="GeoJSON")
247+
assert isinstance(vc, VectorCube)
248+
vc.execute()
249+
assert dummy_backend.get_pg() == {
250+
"loadurl1": {
251+
"process_id": "load_url",
252+
"arguments": {"url": "https://example.com/geometry.json", "format": "GeoJSON"},
253+
"result": True,
254+
}
255+
}

tests/rest/test_connection.py

+19
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
connect,
3131
paginate,
3232
)
33+
from openeo.rest.vectorcube import VectorCube
3334
from openeo.util import ContextTimer
3435

3536
from .. import load_json_resource
@@ -2370,6 +2371,7 @@ def test_extents(self, con120):
23702371
)
23712372
def test_load_geojson(con100, data, dummy_backend):
23722373
vc = con100.load_geojson(data)
2374+
assert isinstance(vc, VectorCube)
23732375
vc.execute()
23742376
assert dummy_backend.get_pg() == {
23752377
"loadgeojson1": {
@@ -2383,6 +2385,23 @@ def test_load_geojson(con100, data, dummy_backend):
23832385
}
23842386

23852387

2388+
def test_load_url(con100, dummy_backend, requests_mock):
2389+
file_formats = {
2390+
"input": {"GeoJSON": {"gis_data_type": ["vector"]}},
2391+
}
2392+
requests_mock.get(API_URL + "file_formats", json=file_formats)
2393+
vc = con100.load_url("https://example.com/geometry.json", format="GeoJSON")
2394+
assert isinstance(vc, VectorCube)
2395+
vc.execute()
2396+
assert dummy_backend.get_pg() == {
2397+
"loadurl1": {
2398+
"process_id": "load_url",
2399+
"arguments": {"url": "https://example.com/geometry.json", "format": "GeoJSON"},
2400+
"result": True,
2401+
}
2402+
}
2403+
2404+
23862405
def test_list_file_formats(requests_mock):
23872406
requests_mock.get(API_URL, json={"api_version": "1.0.0"})
23882407
conn = Connection(API_URL)

0 commit comments

Comments
 (0)