diff --git a/openeo_driver/_version.py b/openeo_driver/_version.py index e9d2db99..418acaa2 100644 --- a/openeo_driver/_version.py +++ b/openeo_driver/_version.py @@ -1 +1 @@ -__version__ = "0.77.2a1" +__version__ = "0.77.3a1" diff --git a/openeo_driver/config/load.py b/openeo_driver/config/load.py index 3bf0fefc..b50a115d 100644 --- a/openeo_driver/config/load.py +++ b/openeo_driver/config/load.py @@ -96,19 +96,6 @@ def flush(self): """Flush the config, to force a reload on next get.""" self._config = None - @contextlib.contextmanager - def _pytest_override_context(self, overrides: Optional[dict] = None): - """ - Important: this context manger specifically intended for usage in pytest fixtures, - to override specific config fields during the lifetime of a test - """ - orig = self.get() - kwargs = {**attrs.asdict(orig, recurse=False), **overrides} - overridden = self.expected_class(**kwargs) - self._config = overridden - yield overridden - self.flush() - # "Singleton by convention" config getter _backend_config_getter = ConfigGetter() diff --git a/openeo_driver/dummy/dummy_config.py b/openeo_driver/dummy/dummy_config.py index b2095c9e..3e3db08d 100644 --- a/openeo_driver/dummy/dummy_config.py +++ b/openeo_driver/dummy/dummy_config.py @@ -66,7 +66,7 @@ def _valid_basic_auth(username: str, password: str) -> bool: config = OpenEoBackendConfig( - id="dummy", + id="openeo-python-driver-dummy", capabilities_title="Dummy openEO Backend", capabilities_description="Dummy openEO backend provided by [openeo-python-driver](https://github.com/Open-EO/openeo-python-driver).", capabilities_backend_version="1.2.3-foo", diff --git a/openeo_driver/testing.py b/openeo_driver/testing.py index b93f826b..6648f9d7 100644 --- a/openeo_driver/testing.py +++ b/openeo_driver/testing.py @@ -14,6 +14,7 @@ from typing import Any, Callable, Collection, Dict, Optional, Pattern, Tuple, Union from unittest import mock +import attrs import openeo import openeo.processes import pytest @@ -24,6 +25,7 @@ from openeo.capabilities import ComparableVersion from werkzeug.datastructures import Headers +from openeo_driver.config.load import ConfigGetter, _backend_config_getter from openeo_driver.users.auth import HttpAuthHandler from openeo_driver.util.geometry import as_geojson_feature, as_geojson_feature_collection from openeo_driver.utils import generate_unique_id @@ -667,3 +669,35 @@ def run(queue: multiprocessing.Queue): server_process.join(timeout=2) _log.info(f"ephemeral_fileserver: terminated with exitcode={server_process.exitcode}") server_process.close() + + +def config_overrides(config_getter: ConfigGetter = _backend_config_getter, **kwargs): + """ + *Only to be used in tests* + + `mock.patch` based mocker to override the config returned by `get_backend_config()` + + Can be used as context manager + + >>> with config_overrides(id="foobar"): + ... ... + + in a fixture (as context manager): + + >>> @pytest.fixture + ... def custom_setup() + ... with config_overrides(id="foobar"): + ... yield + + or as test function decorator + + >>> @config_overrides(id="foobar") + ... def test_stuff(): + """ + orig_config = config_getter.get() + config_kwargs = { + **attrs.asdict(orig_config, recurse=False), + **kwargs, + } + overriden_config = config_getter.expected_class(**config_kwargs) + return mock.patch.object(config_getter, "_config", new=overriden_config) diff --git a/tests/conftest.py b/tests/conftest.py index 2318f385..35a5a080 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -15,7 +15,7 @@ from openeo_driver.backend import UserDefinedProcesses from openeo_driver.config import OpenEoBackendConfig from openeo_driver.dummy.dummy_backend import DummyBackendImplementation -from openeo_driver.testing import UrllibMocker +from openeo_driver.testing import UrllibMocker, config_overrides from openeo_driver.util.logging import ( LOGGING_CONTEXT_BATCH_JOB, LOGGING_CONTEXT_FLASK, @@ -52,9 +52,7 @@ def backend_config(backend_config_overrides) -> OpenEoBackendConfig: if backend_config_overrides is None: yield openeo_driver.config.load.get_backend_config() else: - with openeo_driver.config.load._backend_config_getter._pytest_override_context( - overrides=backend_config_overrides - ): + with config_overrides(**backend_config_overrides): yield openeo_driver.config.load.get_backend_config() diff --git a/tests/test_config.py b/tests/test_config.py index ecb3bf84..93ccdc60 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -158,12 +158,12 @@ class MyConfig(OpenEoBackendConfig): @pytest.mark.parametrize( ["backend_config_overrides", "expected_id"], [ - (None, "dummy"), - ({}, "dummy"), + (None, "openeo-python-driver-dummy"), + ({}, "openeo-python-driver-dummy"), ({"id": "overridden!"}, "overridden!"), ], ) -def test_pytest_override_context(backend_config, backend_config_overrides, expected_id): +def test_backend_config_overrides(backend_config, backend_config_overrides, expected_id): config = get_backend_config() assert config.id == expected_id diff --git a/tests/test_testing.py b/tests/test_testing.py index a71fa6f5..c84a71b9 100644 --- a/tests/test_testing.py +++ b/tests/test_testing.py @@ -11,6 +11,7 @@ import pytest import requests +from openeo_driver.config import get_backend_config from openeo_driver.testing import ( ApiTester, ApproxGeoJSONByBounds, @@ -22,6 +23,7 @@ UrllibMocker, approxify, caplog_with_custom_formatter, + config_overrides, ephemeral_fileserver, preprocess_check_and_replace, ) @@ -348,3 +350,52 @@ def test_types(self): expected = ApproxGeoJSONByBounds(1, 1, 3, 4, types=["MultiPolygon"], abs=0.1) assert geometry != expected assert "Wrong type 'Polygon'" in repr(expected) + + +class TestConfigOverrides: + def test_baseline(self): + assert get_backend_config().id == "openeo-python-driver-dummy" + + def test_context(self): + assert get_backend_config().id == "openeo-python-driver-dummy" + with config_overrides(id="hello-inline-context"): + assert get_backend_config().id == "hello-inline-context" + assert get_backend_config().id == "openeo-python-driver-dummy" + + def test_context_nesting(self): + assert get_backend_config().id == "openeo-python-driver-dummy" + with config_overrides(id="hello-inline-context"): + assert get_backend_config().id == "hello-inline-context" + with config_overrides(id="hello-again"): + assert get_backend_config().id == "hello-again" + assert get_backend_config().id == "hello-inline-context" + assert get_backend_config().id == "openeo-python-driver-dummy" + + @pytest.fixture + def special_stuff(self): + with config_overrides(id="hello-fixture"): + yield + + def test_fixture(self, special_stuff): + assert get_backend_config().id == "hello-fixture" + + def test_fixture_and_context(self, special_stuff): + assert get_backend_config().id == "hello-fixture" + with config_overrides(id="hello-inline-context"): + assert get_backend_config().id == "hello-inline-context" + assert get_backend_config().id == "hello-fixture" + + @config_overrides(id="hello-decorator") + def test_decorator(self): + assert get_backend_config().id == "hello-decorator" + + @config_overrides(id="hello-decorator") + def test_decorator_and_context(self): + assert get_backend_config().id == "hello-decorator" + with config_overrides(id="hello-inline-context"): + assert get_backend_config().id == "hello-inline-context" + assert get_backend_config().id == "hello-decorator" + + @config_overrides(id="hello-decorator") + def test_decorator_vs_fixture(self, special_stuff): + assert get_backend_config().id == "hello-decorator"