Skip to content

Commit

Permalink
Issue #134 globally require at least 1.0.0 in Connection
Browse files Browse the repository at this point in the history
  • Loading branch information
soxofaan committed Mar 7, 2023
1 parent 5900420 commit 9d61f4d
Show file tree
Hide file tree
Showing 8 changed files with 44 additions and 43 deletions.
10 changes: 7 additions & 3 deletions CHANGELOG.md
Expand Up @@ -20,9 +20,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Removed

- Remove `ImageCollectionClient` (and related helpers),
a now unused leftover from the pre-1.0.0 versions of the openEO API
([#134](https://github.com/Open-EO/openeo-python-client/issues/134), [#100](https://github.com/Open-EO/openeo-python-client/issues/100))
- Dropped support for pre-1.0.0 versions of the openEO API
([#134](https://github.com/Open-EO/openeo-python-client/issues/134)):
- Remove `ImageCollectionClient` and related helpers
(now unused leftovers from version 0.4.0 and earlier).
([#134](https://github.com/Open-EO/openeo-python-client/issues/134), [#100](https://github.com/Open-EO/openeo-python-client/issues/100))
- Require at least version 1.0.0 of the openEO API for a back-end in `Connection`
([#134](https://github.com/Open-EO/openeo-python-client/issues/134))

### Fixed

Expand Down
7 changes: 7 additions & 0 deletions openeo/capabilities.py
Expand Up @@ -173,6 +173,13 @@ def accept_higher(self, other: Union[str, 'ComparableVersion']):
"""Other is higher than self."""
return ComparableVersion(other) > self

def require_at_least(self, other: Union[str, "ComparableVersion"]):
"""Raise exception if self is not at least other."""
if not self.at_least(other):
raise ApiVersionException(
f"openEO API version should be at least {other!s}, but got {self!s}."
)


class ApiVersionException(RuntimeError):
pass
6 changes: 3 additions & 3 deletions openeo/rest/auth/cli.py
Expand Up @@ -9,6 +9,7 @@
from typing import List, Tuple

from openeo import connect, Connection
from openeo.capabilities import ApiVersionException
from openeo.rest.auth.config import AuthConfig, RefreshTokenStore
from openeo.rest.auth.oidc import OidcProviderInfo

Expand Down Expand Up @@ -250,9 +251,8 @@ def main_add_oidc(args):
print("to config file: {c!r}".format(c=str(config.path)))

con = connect(backend)
api_version = con.capabilities().api_version_check
if api_version < "1.0.0":
raise CliToolException("Backend API version is too low: {v} < 1.0.0".format(v=api_version))
assert con.capabilities().api_version_check.at_least("1.0.0")

# Find provider ID
oidc_info = con.get("/credentials/oidc", expected_status=200).json()
providers = OrderedDict((p["id"], OidcProviderInfo.from_dict(p)) for p in oidc_info["providers"])
Expand Down
34 changes: 5 additions & 29 deletions openeo/rest/connection.py
Expand Up @@ -214,7 +214,7 @@ class Connection(RestApiConnection):
Connection to an openEO backend.
"""

_MINIMUM_API_VERSION = ComparableVersion("0.4.0")
_MINIMUM_API_VERSION = ComparableVersion("1.0.0")

def __init__(
self, url: str, auth: AuthBase = None, session: requests.Session = None, default_timeout: int = None,
Expand All @@ -237,10 +237,7 @@ def __init__(
self._capabilities_cache = LazyLoadCache()

# Initial API version check.
if self._api_version.below(self._MINIMUM_API_VERSION):
raise ApiVersionException("OpenEO API version should be at least {m!s}, but got {v!s}".format(
m=self._MINIMUM_API_VERSION, v=self._api_version)
)
self._api_version.require_at_least(self._MINIMUM_API_VERSION)

self._auth_config = auth_config
self._refresh_token_store = refresh_token_store
Expand Down Expand Up @@ -298,7 +295,6 @@ def authenticate_basic(self, username: str = None, password: str = None) -> 'Con
auth=HTTPBasicAuth(username, password)
).json()
# Switch to bearer based authentication in further requests.
assert self._api_version.at_least("1.0.0")
self.auth = BasicBearerAuth(access_token=resp["access_token"])
return self

Expand All @@ -310,7 +306,6 @@ def _get_oidc_provider(self, provider_id: Union[str, None] = None) -> Tuple[str,
Can be None if there is just one provider.
:return: updated provider_id and provider info object
"""
assert self._api_version.at_least("1.0.0")
oidc_info = self.get("/credentials/oidc", expected_status=200).json()
providers = OrderedDict((p["id"], p) for p in oidc_info["providers"])
if len(providers) < 1:
Expand Down Expand Up @@ -413,7 +408,6 @@ def _authenticate_oidc(
else:
_log.warning("No OIDC refresh token to store.")
token = tokens.access_token
assert self._api_version.at_least("1.0.0")
if refreshable:
refresh_data = OidcRefreshInfo(
provider_id=provider_id,
Expand Down Expand Up @@ -674,10 +668,7 @@ def capabilities(self) -> RESTCapabilities:
)

def list_output_formats(self) -> dict:
if self._api_version.at_least("1.0.0"):
return self.list_file_formats()["output"]
else:
return self.get('/output_formats', expected_status=200).json()
return self.list_file_formats().get("output", {})

list_file_types = legacy_alias(list_output_formats, "list_file_types")

Expand Down Expand Up @@ -928,13 +919,8 @@ def datacube_from_process(self, process_id: str, namespace: str = None, **kwargs
:param kwargs: The arguments of the custom process
:return: A :py:class:`DataCube`, without valid metadata, as the client is not aware of this custom process.
"""

if self._api_version.at_least("1.0.0"):
graph = PGNode(process_id, namespace=namespace, arguments=kwargs)
return DataCube(graph=graph, connection=self)
else:
raise OpenEoClientException(
"This method requires support for at least version 1.0.0 in the openEO backend.")
graph = PGNode(process_id, namespace=namespace, arguments=kwargs)
return DataCube(graph=graph, connection=self)

def datacube_from_flat_graph(self, flat_graph: dict, parameters: dict = None) -> DataCube:
"""
Expand All @@ -945,10 +931,6 @@ def datacube_from_flat_graph(self, flat_graph: dict, parameters: dict = None) ->
(and optionally parameter metadata under a "parameters" field).
:return: A :py:class:`DataCube` corresponding with the operations encoded in the process graph
"""
if self._api_version.below("1.0.0"):
raise OpenEoClientException(
"This method requires support for at least version 1.0.0 in the openEO backend.")

parameters = parameters or {}

if "process_graph" in flat_graph:
Expand Down Expand Up @@ -996,7 +978,6 @@ def load_collection(
.. versionadded:: 0.13.0
added the ``max_cloud_cover`` argument.
"""
assert self._api_version.at_least("1.0.0")
return DataCube.load_collection(
collection_id=collection_id, connection=self,
spatial_extent=spatial_extent, temporal_extent=temporal_extent, bands=bands, properties=properties,
Expand Down Expand Up @@ -1025,9 +1006,6 @@ def load_result(
:return: a :py:class:`DataCube`
"""
# TODO: add check that back-end supports `load_result` process?
if self._api_version.below("1.0.0"):
raise OpenEoClientException(
"This method requires support for at least version 1.0.0 in the openEO backend.")
metadata = CollectionMetadata({}, dimensions=[
SpatialDimension(name="x", extent=[]),
SpatialDimension(name="y", extent=[]),
Expand Down Expand Up @@ -1128,7 +1106,6 @@ def _build_request_with_process_graph(self, process_graph: Union[dict, Any], **k
"""
result = kwargs
process_graph = as_flat_graph(process_graph)
assert self._api_version.at_least("1.0.0")
if "process_graph" not in process_graph:
process_graph = {"process_graph": process_graph}
result["process"] = process_graph
Expand Down Expand Up @@ -1244,7 +1221,6 @@ def load_disk_collection(
:param options: options specific to the file format
:return: the data as an ImageCollection
"""
assert self._api_version.at_least("1.0.0")
return DataCube.load_disk_collection(
self, format, glob_pattern, **(options or {})
)
Expand Down
6 changes: 5 additions & 1 deletion tests/rest/auth/test_cli.py
Expand Up @@ -4,6 +4,7 @@

import pytest

from openeo.capabilities import ApiVersionException
from openeo.rest.auth import cli
from openeo.rest.auth.cli import CliToolException
from openeo.rest.auth.config import AuthConfig, RefreshTokenStore
Expand Down Expand Up @@ -225,7 +226,10 @@ def test_add_oidc_use_default_client_overwrite(auth_config, requests_mock, caplo

def test_add_oidc_04(auth_config, requests_mock):
requests_mock.get("https://oeo.test/", json={"api_version": "0.4.0"})
with pytest.raises(CliToolException, match="Backend API version is too low"):
with pytest.raises(
ApiVersionException,
match="openEO API version should be at least 1.0.0, but got 0.4.0",
):
cli.main(["add-oidc", "https://oeo.test"])


Expand Down
9 changes: 8 additions & 1 deletion tests/test_capabilities.py
@@ -1,6 +1,6 @@
import pytest

from openeo.capabilities import ComparableVersion
from openeo.capabilities import ComparableVersion, ApiVersionException


class TestComparableVersion:
Expand Down Expand Up @@ -135,3 +135,10 @@ def test_left_referencing(self):
assert v.accept_lower("1.2.2") is True
assert v.accept_lower("1.2.3") is False
assert v.accept_lower("1.2.4") is False

def test_require_at_least(self):
v = ComparableVersion("1.2.3")
v.require_at_least("1.0.0")
v.require_at_least("1.2.0")
with pytest.raises(ApiVersionException):
v.require_at_least("1.2.4")
9 changes: 5 additions & 4 deletions tests/test_rest_session.py
Expand Up @@ -56,6 +56,7 @@

@requests_mock.mock()
class TestUserFiles(TestCase):
# TODO: review this test class (looks very dated), most things are probably already covered elsewhere

def setUp(self):
# configuration phase: define username, endpoint, parameters?
Expand Down Expand Up @@ -121,7 +122,7 @@ def test_user_delete_file(self, m):

def test_list_capabilities(self, m):
capabilities = {
"api_version": "0.4.0",
"api_version": "1.0.0",
"endpoints": [
{"path": "/collections", "methods": ["GET"]},
]
Expand Down Expand Up @@ -170,7 +171,7 @@ def test_capabilities_api_version_check(self, m):
assert capabilities.api_version_check.above('1.2.2')

def test_list_collections(self, m):
m.get("http://localhost:8000/api/", json={"api_version": "0.4.0"})
m.get("http://localhost:8000/api/", json={"api_version": "1.0.0"})
con = openeo.connect(self.endpoint)

collection_url = "{}/collections".format(self.endpoint)
Expand All @@ -179,7 +180,7 @@ def test_list_collections(self, m):
assert collections == COLLECTIONS

def test_get_collection(self, m):
m.get("http://localhost:8000/api/", json={"api_version": "0.4.0"})
m.get("http://localhost:8000/api/", json={"api_version": "1.0.0"})
con = openeo.connect(self.endpoint)

collection_org = COLLECTIONS[0]
Expand All @@ -190,7 +191,7 @@ def test_get_collection(self, m):
assert collection == collection_org

def test_get_all_processes(self, m):
m.get("http://localhost:8000/api/", json={"api_version": "0.4.0"})
m.get("http://localhost:8000/api/", json={"api_version": "1.0.0"})
con = openeo.connect(self.endpoint)

processes_url = "{}/processes".format(self.endpoint)
Expand Down
6 changes: 4 additions & 2 deletions tests/test_usecase1.py
Expand Up @@ -9,6 +9,8 @@

@requests_mock.mock()
class TestUsecase1(TestCase):
# TODO: review this test class (looks very dated), most things are probably already covered elsewhere

_capabilities = {
"api_version": "1.0.0",
"endpoints": [{"path": "/credentials/basic", "methods": ["GET"]}],
Expand Down Expand Up @@ -41,7 +43,7 @@ def test_viewing_list_jobs(self, m):
assert jobs == [job_info]

def test_viewing_data(self, m):
m.get("http://localhost:8000/api/", json={"api_version": "0.4.0"})
m.get("http://localhost:8000/api/", json={"api_version": "1.0.0"})
m.get("http://localhost:8000/api/collections", json={"collections": [{"product_id": "sentinel2_subset"}]})
m.get("http://localhost:8000/api/collections/sentinel2_subset", json={"product_id": "sentinel2_subset"})

Expand All @@ -55,7 +57,7 @@ def test_viewing_data(self, m):
self.assertEqual(data_info["product_id"], self.data_id)

def test_viewing_processes(self, m):
m.get("http://localhost:8000/api/", json={"api_version": "0.4.0"})
m.get("http://localhost:8000/api/", json={"api_version": "1.0.0"})
con = openeo.connect(self.endpoint)

m.get("http://localhost:8000/api/processes", json={"processes": [{"process_id": "calculate_ndvi"}]})
Expand Down

0 comments on commit 9d61f4d

Please sign in to comment.