Ecmwf simplify config #3413
11 fail, 3 skipped, 576 pass in 3m 18s
Annotations
Check warning on line 0 in tests.units.test_http_server.RequestTestCase
github-actions / Test Results
All 2 runs failed: test_product_type_queryables_from_constraints (tests.units.test_http_server.RequestTestCase)
artifacts/unit-test-results-python3.13-ubuntu-latest/junit-report.xml [took 0s]
artifacts/unit-test-results-python3.9-ubuntu-latest/junit-report.xml [took 0s]
Raw output
TypeError: Search.get_product_type_def_params() got multiple values for argument 'product_type'
+ Exception Group Traceback (most recent call last):
| File "/home/runner/work/eodag/eodag/.tox/py313/lib/python3.13/site-packages/starlette/_utils.py", line 76, in collapse_excgroups
| yield
| File "/home/runner/work/eodag/eodag/.tox/py313/lib/python3.13/site-packages/starlette/middleware/base.py", line 186, in __call__
| async with anyio.create_task_group() as task_group:
| ~~~~~~~~~~~~~~~~~~~~~~~^^
| File "/home/runner/work/eodag/eodag/.tox/py313/lib/python3.13/site-packages/anyio/_backends/_asyncio.py", line 767, in __aexit__
| raise BaseExceptionGroup(
| "unhandled errors in a TaskGroup", self._exceptions
| )
| ExceptionGroup: unhandled errors in a TaskGroup (1 sub-exception)
+-+---------------- 1 ----------------
| Traceback (most recent call last):
| File "/home/runner/.local/share/uv/python/cpython-3.13.1-linux-x86_64-gnu/lib/python3.13/unittest/case.py", line 58, in testPartExecutor
| yield
| File "/home/runner/.local/share/uv/python/cpython-3.13.1-linux-x86_64-gnu/lib/python3.13/unittest/case.py", line 651, in run
| self._callTestMethod(testMethod)
| ~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^
| File "/home/runner/.local/share/uv/python/cpython-3.13.1-linux-x86_64-gnu/lib/python3.13/unittest/case.py", line 606, in _callTestMethod
| if method() is not None:
| ~~~~~~^^
| File "/home/runner/.local/share/uv/python/cpython-3.13.1-linux-x86_64-gnu/lib/python3.13/unittest/mock.py", line 1424, in patched
| return func(*newargs, **newkeywargs)
| File "/home/runner/work/eodag/eodag/tests/units/test_http_server.py", line 1626, in test_product_type_queryables_from_constraints
| res = self._request_valid(
| "collections/ERA5_SL/queryables?provider=cop_cds",
| check_links=False,
| )
| File "/home/runner/work/eodag/eodag/tests/units/test_http_server.py", line 379, in _request_valid
| response = self._request_valid_raw(
| url,
| ...<4 lines>...
| search_result=search_result,
| )
| File "/home/runner/.local/share/uv/python/cpython-3.13.1-linux-x86_64-gnu/lib/python3.13/unittest/mock.py", line 1424, in patched
| return func(*newargs, **newkeywargs)
| File "/home/runner/work/eodag/eodag/tests/units/test_http_server.py", line 337, in _request_valid_raw
| response = self.app.request(
| method,
| ...<3 lines>...
| headers={"Content-Type": "application/json"} if method == "POST" else {},
| )
| File "/home/runner/work/eodag/eodag/.tox/py313/lib/python3.13/site-packages/starlette/testclient.py", line 484, in request
| return super().request(
| ~~~~~~~~~~~~~~~^
| method,
| ^^^^^^^
| ...<11 lines>...
| extensions=extensions,
| ^^^^^^^^^^^^^^^^^^^^^^
| )
| ^
| File "/home/runner/work/eodag/eodag/.tox/py313/lib/python3.13/site-packages/httpx/_client.py", line 825, in request
| return self.send(request, auth=auth, follow_redirects=follow_redirects)
| ~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| File "/home/runner/work/eodag/eodag/.tox/py313/lib/python3.13/site-packages/httpx/_client.py", line 914, in send
| response = self._send_handling_auth(
| request,
| ...<2 lines>...
| history=[],
| )
| File "/home/runner/work/eodag/eodag/.tox/py313/lib/python3.13/site-packages/httpx/_client.py", line 942, in _send_handling_auth
| response = self._send_handling_redirects(
| request,
| follow_redirects=follow_redirects,
| history=history,
| )
| File "/home/runner/work/eodag/eodag/.tox/py313/lib/python3.13/site-packages/httpx/_client.py", line 979, in _send_handling_redirects
| response = self._send_single_request(request)
| File "/home/runner/work/eodag/eodag/.tox/py313/lib/python3.13/site-packages/httpx/_client.py", line 1014, in _send_single_request
| response = transport.handle_request(request)
| File "/home/runner/work/eodag/eodag/.tox/py313/lib/python3.13/site-packages/starlette/testclient.py", line 377, in handle_request
| raise exc
| File "/home/runner/work/eodag/eodag/.tox/py313/lib/python3.13/site-packages/starlette/testclient.py", line 374, in handle_request
| portal.call(self.app, scope, receive, send)
| ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| File "/home/runner/work/eodag/eodag/.tox/py313/lib/python3.13/site-packages/anyio/from_thread.py", line 290, in call
| return cast(T_Retval, self.start_task_soon(func, *args).result())
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^
| File "/home/runner/.local/share/uv/python/cpython-3.13.1-linux-x86_64-gnu/lib/python3.13/concurrent/futures/_base.py", line 456, in result
| return self.__get_result()
| ~~~~~~~~~~~~~~~~~^^
| File "/home/runner/.local/share/uv/python/cpython-3.13.1-linux-x86_64-gnu/lib/python3.13/concurrent/futures/_base.py", line 401, in __get_result
| raise self._exception
| File "/home/runner/work/eodag/eodag/.tox/py313/lib/python3.13/site-packages/anyio/from_thread.py", line 221, in _call_func
| retval = await retval_or_awaitable
| ^^^^^^^^^^^^^^^^^^^^^^^^^
| File "/home/runner/work/eodag/eodag/.tox/py313/lib/python3.13/site-packages/fastapi/applications.py", line 1054, in __call__
| await super().__call__(scope, receive, send)
| File "/home/runner/work/eodag/eodag/.tox/py313/lib/python3.13/site-packages/starlette/applications.py", line 113, in __call__
| await self.middleware_stack(scope, receive, send)
| File "/home/runner/work/eodag/eodag/.tox/py313/lib/python3.13/site-packages/starlette/middleware/errors.py", line 187, in __call__
| raise exc
| File "/home/runner/work/eodag/eodag/.tox/py313/lib/python3.13/site-packages/starlette/middleware/errors.py", line 165, in __call__
| await self.app(scope, receive, _send)
| File "/home/runner/work/eodag/eodag/.tox/py313/lib/python3.13/site-packages/starlette/middleware/base.py", line 185, in __call__
| with collapse_excgroups():
| ~~~~~~~~~~~~~~~~~~^^
| File "/home/runner/.local/share/uv/python/cpython-3.13.1-linux-x86_64-gnu/lib/python3.13/contextlib.py", line 162, in __exit__
| self.gen.throw(value)
| ~~~~~~~~~~~~~~^^^^^^^
| File "/home/runner/work/eodag/eodag/.tox/py313/lib/python3.13/site-packages/starlette/_utils.py", line 82, in collapse_excgroups
| raise exc
| File "/home/runner/work/eodag/eodag/.tox/py313/lib/python3.13/site-packages/starlette/middleware/base.py", line 187, in __call__
| response = await self.dispatch_func(request, call_next)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| File "/home/runner/work/eodag/eodag/eodag/rest/server.py", line 219, in forward_middleware
| response = await call_next(request)
| ^^^^^^^^^^^^^^^^^^^^^^^^
| File "/home/runner/work/eodag/eodag/.tox/py313/lib/python3.13/site-packages/starlette/middleware/base.py", line 163, in call_next
| raise app_exc
| File "/home/runner/work/eodag/eodag/.tox/py313/lib/python3.13/site-packages/starlette/middleware/base.py", line 149, in coro
| await self.app(scope, receive_or_disconnect, send_no_error)
| File "/home/runner/work/eodag/eodag/.tox/py313/lib/python3.13/site-packages/starlette/middleware/cors.py", line 85, in __call__
| await self.app(scope, receive, send)
| File "/home/runner/work/eodag/eodag/.tox/py313/lib/python3.13/site-packages/starlette/middleware/exceptions.py", line 62, in __call__
| await wrap_app_handling_exceptions(self.app, conn)(scope, receive, send)
| File "/home/runner/work/eodag/eodag/.tox/py313/lib/python3.13/site-packages/starlette/_exception_handler.py", line 53, in wrapped_app
| raise exc
| File "/home/runner/work/eodag/eodag/.tox/py313/lib/python3.13/site-packages/starlette/_exception_handler.py", line 42, in wrapped_app
| await app(scope, receive, sender)
| File "/home/runner/work/eodag/eodag/.tox/py313/lib/python3.13/site-packages/starlette/routing.py", line 715, in __call__
| await self.middleware_stack(scope, receive, send)
| File "/home/runner/work/eodag/eodag/.tox/py313/lib/python3.13/site-packages/starlette/routing.py", line 735, in app
| await route.handle(scope, receive, send)
| File "/home/runner/work/eodag/eodag/.tox/py313/lib/python3.13/site-packages/starlette/routing.py", line 288, in handle
| await self.app(scope, receive, send)
| File "/home/runner/work/eodag/eodag/.tox/py313/lib/python3.13/site-packages/starlette/routing.py", line 76, in app
| await wrap_app_handling_exceptions(app, request)(scope, receive, send)
| File "/home/runner/work/eodag/eodag/.tox/py313/lib/python3.13/site-packages/starlette/_exception_handler.py", line 53, in wrapped_app
| raise exc
| File "/home/runner/work/eodag/eodag/.tox/py313/lib/python3.13/site-packages/starlette/_exception_handler.py", line 42, in wrapped_app
| await app(scope, receive, sender)
| File "/home/runner/work/eodag/eodag/.tox/py313/lib/python3.13/site-packages/starlette/routing.py", line 73, in app
| response = await f(request)
| ^^^^^^^^^^^^^^^^
| File "/home/runner/work/eodag/eodag/.tox/py313/lib/python3.13/site-packages/fastapi/routing.py", line 301, in app
| raw_response = await run_endpoint_function(
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| ...<3 lines>...
| )
| ^
| File "/home/runner/work/eodag/eodag/.tox/py313/lib/python3.13/site-packages/fastapi/routing.py", line 212, in run_endpoint_function
| return await dependant.call(**values)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| File "/home/runner/work/eodag/eodag/eodag/rest/server.py", line 400, in list_collection_queryables
| queryables = await get_queryables(
| ^^^^^^^^^^^^^^^^^^^^^
| ...<11 lines>...
| )
| ^
| File "/home/runner/work/eodag/eodag/eodag/rest/core.py", line 666, in get_queryables
| return await cached(
| ^^^^^^^^^^^^^
| _fetch, f"{CACHE_KEY_QUERYABLES}:{provider}:{hashed_queryables}", request
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| )
| ^
| File "/home/runner/work/eodag/eodag/eodag/rest/cache.py", line 61, in cached
| result = await fn()
| ^^^^^^^^^^
| File "/home/runner/work/eodag/eodag/eodag/rest/core.py", line 582, in _fetch
| python_queryables = eodag_api.list_queryables(
| provider=provider,
| fetch_providers=False,
| **params.model_dump(exclude_none=True, by_alias=True),
| )
| File "/home/runner/work/eodag/eodag/eodag/api/core.py", line 2334, in list_queryables
| plugin_queryables = plugin.list_queryables(
| kwargs,
| ...<3 lines>...
| pt_alias,
| )
| File "/home/runner/work/eodag/eodag/eodag/plugins/search/base.py", line 373, in list_queryables
| queryables = self._get_product_type_queryables(product_type, alias, filters)
| File "/home/runner/work/eodag/eodag/eodag/plugins/search/build_search_result.py", line 483, in _get_product_type_queryables
| queryables = self.discover_queryables(**filters) or {}
| ~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^
| File "/home/runner/work/eodag/eodag/eodag/plugins/search/build_search_result.py", line 527, in discover_queryables
| formated_filters = self.format_as_provider_keyword(
| product_type, processed_filters
| )
| File "/home/runner/work/eodag/eodag/eodag/plugins/search/build_search_result.py", line 895, in format_as_provider_keyword
| product_type_def_params = self.get_product_type_def_params(
| product_type, **properties
| )
| TypeError: Search.get_product_type_def_params() got multiple values for argument 'product_type'
+------------------------------------
During handling of the above exception, another exception occurred:
self = <tests.units.test_http_server.RequestTestCase testMethod=test_product_type_queryables_from_constraints>
mock_requests_get = <function get at 0x7fe8a722a8e0>
@mock.patch("eodag.utils.requests.requests.sessions.Session.get", autospec=True)
def test_product_type_queryables_from_constraints(self, mock_requests_get: Mock):
"""Request a collection-specific list of queryables for a given provider
using a constraints file should return a valid response."""
constraints_path = os.path.join(TEST_RESOURCES_PATH, "constraints.json")
with open(constraints_path) as f:
constraints = json.load(f)
for const in constraints:
const["variable"].append("10m_u_component_of_wind")
form_path = os.path.join(TEST_RESOURCES_PATH, "form.json")
with open(form_path) as f:
form = json.load(f)
mock_requests_get.return_value.json.side_effect = [constraints, form]
provider_queryables_from_constraints_file = [
"year",
"month",
"day",
"time",
"variable",
"leadtime_hour",
"type",
"product_type",
]
# queryables properties not shared by all constraints must be removed
not_shared_properties = ["leadtime_hour", "type"]
provider_queryables_from_constraints_file = [
f"ecmwf:{properties}"
for properties in provider_queryables_from_constraints_file
if properties not in not_shared_properties
]
default_provider_stac_properties = ["ecmwf:product_type", "ecmwf:data_format"]
> res = self._request_valid(
"collections/ERA5_SL/queryables?provider=cop_cds",
check_links=False,
)
tests/units/test_http_server.py:1626:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
tests/units/test_http_server.py:379: in _request_valid
response = self._request_valid_raw(
../../../.local/share/uv/python/cpython-3.13.1-linux-x86_64-gnu/lib/python3.13/unittest/mock.py:1424: in patched
return func(*newargs, **newkeywargs)
tests/units/test_http_server.py:337: in _request_valid_raw
response = self.app.request(
.tox/py313/lib/python3.13/site-packages/starlette/testclient.py:484: in request
return super().request(
.tox/py313/lib/python3.13/site-packages/httpx/_client.py:825: in request
return self.send(request, auth=auth, follow_redirects=follow_redirects)
.tox/py313/lib/python3.13/site-packages/httpx/_client.py:914: in send
response = self._send_handling_auth(
.tox/py313/lib/python3.13/site-packages/httpx/_client.py:942: in _send_handling_auth
response = self._send_handling_redirects(
.tox/py313/lib/python3.13/site-packages/httpx/_client.py:979: in _send_handling_redirects
response = self._send_single_request(request)
.tox/py313/lib/python3.13/site-packages/httpx/_client.py:1014: in _send_single_request
response = transport.handle_request(request)
.tox/py313/lib/python3.13/site-packages/starlette/testclient.py:377: in handle_request
raise exc
.tox/py313/lib/python3.13/site-packages/starlette/testclient.py:374: in handle_request
portal.call(self.app, scope, receive, send)
.tox/py313/lib/python3.13/site-packages/anyio/from_thread.py:290: in call
return cast(T_Retval, self.start_task_soon(func, *args).result())
../../../.local/share/uv/python/cpython-3.13.1-linux-x86_64-gnu/lib/python3.13/concurrent/futures/_base.py:456: in result
return self.__get_result()
../../../.local/share/uv/python/cpython-3.13.1-linux-x86_64-gnu/lib/python3.13/concurrent/futures/_base.py:401: in __get_result
raise self._exception
.tox/py313/lib/python3.13/site-packages/anyio/from_thread.py:221: in _call_func
retval = await retval_or_awaitable
.tox/py313/lib/python3.13/site-packages/fastapi/applications.py:1054: in __call__
await super().__call__(scope, receive, send)
.tox/py313/lib/python3.13/site-packages/starlette/applications.py:113: in __call__
await self.middleware_stack(scope, receive, send)
.tox/py313/lib/python3.13/site-packages/starlette/middleware/errors.py:187: in __call__
raise exc
.tox/py313/lib/python3.13/site-packages/starlette/middleware/errors.py:165: in __call__
await self.app(scope, receive, _send)
.tox/py313/lib/python3.13/site-packages/starlette/middleware/base.py:185: in __call__
with collapse_excgroups():
../../../.local/share/uv/python/cpython-3.13.1-linux-x86_64-gnu/lib/python3.13/contextlib.py:162: in __exit__
self.gen.throw(value)
.tox/py313/lib/python3.13/site-packages/starlette/_utils.py:82: in collapse_excgroups
raise exc
.tox/py313/lib/python3.13/site-packages/starlette/middleware/base.py:187: in __call__
response = await self.dispatch_func(request, call_next)
eodag/rest/server.py:219: in forward_middleware
response = await call_next(request)
.tox/py313/lib/python3.13/site-packages/starlette/middleware/base.py:163: in call_next
raise app_exc
.tox/py313/lib/python3.13/site-packages/starlette/middleware/base.py:149: in coro
await self.app(scope, receive_or_disconnect, send_no_error)
.tox/py313/lib/python3.13/site-packages/starlette/middleware/cors.py:85: in __call__
await self.app(scope, receive, send)
.tox/py313/lib/python3.13/site-packages/starlette/middleware/exceptions.py:62: in __call__
await wrap_app_handling_exceptions(self.app, conn)(scope, receive, send)
.tox/py313/lib/python3.13/site-packages/starlette/_exception_handler.py:53: in wrapped_app
raise exc
.tox/py313/lib/python3.13/site-packages/starlette/_exception_handler.py:42: in wrapped_app
await app(scope, receive, sender)
.tox/py313/lib/python3.13/site-packages/starlette/routing.py:715: in __call__
await self.middleware_stack(scope, receive, send)
.tox/py313/lib/python3.13/site-packages/starlette/routing.py:735: in app
await route.handle(scope, receive, send)
.tox/py313/lib/python3.13/site-packages/starlette/routing.py:288: in handle
await self.app(scope, receive, send)
.tox/py313/lib/python3.13/site-packages/starlette/routing.py:76: in app
await wrap_app_handling_exceptions(app, request)(scope, receive, send)
.tox/py313/lib/python3.13/site-packages/starlette/_exception_handler.py:53: in wrapped_app
raise exc
.tox/py313/lib/python3.13/site-packages/starlette/_exception_handler.py:42: in wrapped_app
await app(scope, receive, sender)
.tox/py313/lib/python3.13/site-packages/starlette/routing.py:73: in app
response = await f(request)
.tox/py313/lib/python3.13/site-packages/fastapi/routing.py:301: in app
raw_response = await run_endpoint_function(
.tox/py313/lib/python3.13/site-packages/fastapi/routing.py:212: in run_endpoint_function
return await dependant.call(**values)
eodag/rest/server.py:400: in list_collection_queryables
queryables = await get_queryables(
eodag/rest/core.py:666: in get_queryables
return await cached(
eodag/rest/cache.py:61: in cached
result = await fn()
eodag/rest/core.py:582: in _fetch
python_queryables = eodag_api.list_queryables(
eodag/api/core.py:2334: in list_queryables
plugin_queryables = plugin.list_queryables(
eodag/plugins/search/base.py:373: in list_queryables
queryables = self._get_product_type_queryables(product_type, alias, filters)
eodag/plugins/search/build_search_result.py:483: in _get_product_type_queryables
queryables = self.discover_queryables(**filters) or {}
eodag/plugins/search/build_search_result.py:527: in discover_queryables
formated_filters = self.format_as_provider_keyword(
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = ECMWFSearch(provider=cop_cds, priority=0, topic=Search)
product_type = 'ERA5_SL'
properties = {'completionTimeFromAscendingNode': '1940-01-01T09:00:00+00:00', 'data_format': 'grib', 'dataset': 'reanalysis-era5-single-levels', 'download_format': 'zip', ...}
def format_as_provider_keyword(
self, product_type: str, properties: Dict[str, Any]
) -> Dict[str, Any]:
"""Return provider equivalent keyword names from EODAG keywords.
:param product_type: product type id
:param properties: dict of properties to be formatted
:return: dict of formatted properties
"""
properties["productType"] = product_type
# provider product type specific conf
> product_type_def_params = self.get_product_type_def_params(
product_type, **properties
)
E TypeError: Search.get_product_type_def_params() got multiple values for argument 'product_type'
eodag/plugins/search/build_search_result.py:895: TypeError
Check warning on line 0 in tests.units.test_eoproduct.TestEOProduct
github-actions / Test Results
All 2 runs failed: test_eoproduct_default_geom (tests.units.test_eoproduct.TestEOProduct)
artifacts/unit-test-results-python3.13-ubuntu-latest/junit-report.xml [took 0s]
artifacts/unit-test-results-python3.9-ubuntu-latest/junit-report.xml [took 0s]
Raw output
AssertionError: MisconfiguredError not raised
self = <tests.units.test_eoproduct.TestEOProduct testMethod=test_eoproduct_default_geom>
def test_eoproduct_default_geom(self):
"""EOProduct needs a geometry or can use confired defaultGeometry by default"""
> with self.assertRaisesRegex(MisconfiguredError, "No geometry available"):
E AssertionError: MisconfiguredError not raised
tests/units/test_eoproduct.py:68: AssertionError
Check warning on line 0 in tests.units.test_core.TestCore
github-actions / Test Results
All 2 runs failed: test_list_queryables_with_constraints (tests.units.test_core.TestCore)
artifacts/unit-test-results-python3.13-ubuntu-latest/junit-report.xml [took 0s]
artifacts/unit-test-results-python3.9-ubuntu-latest/junit-report.xml [took 0s]
Raw output
AssertionError: expected call not found.
Expected: discover_queryables(ECMWFSearch(provider=cop_cds, priority=0, topic=Search), productType='ERA5_SL', ecmwf:product_type='reanalysis', ecmwf:dataset='reanalysis-era5-single-levels', ecmwf:data_format='grib', ecmwf:download_format='zip', ecmwf:variable='10m_u_component_of_wind')
Actual: discover_queryables(ECMWFSearch(provider=cop_cds, priority=0, topic=Search), productType='ERA5_SL')
self = <tests.units.test_core.TestCore testMethod=test_list_queryables_with_constraints>
mock_discover_queryables = <function discover_queryables at 0x7f48e216df80>
@mock.patch(
"eodag.plugins.search.build_search_result.ECMWFSearch.discover_queryables",
autospec=True,
)
def test_list_queryables_with_constraints(
self, mock_discover_queryables: mock.Mock
):
plugin = next(
self.dag._plugins_manager.get_search_plugins(
provider="cop_cds", product_type="ERA5_SL"
)
)
# default values should be added to params
self.dag.list_queryables(provider="cop_cds", productType="ERA5_SL")
defaults = {
"productType": "ERA5_SL",
"ecmwf:product_type": "reanalysis",
"ecmwf:dataset": "reanalysis-era5-single-levels",
"ecmwf:data_format": "grib",
"ecmwf:download_format": "zip",
"ecmwf:variable": "10m_u_component_of_wind",
}
> mock_discover_queryables.assert_called_once_with(plugin, **defaults)
tests/units/test_core.py:1530:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
../../../.local/share/uv/python/cpython-3.13.1-linux-x86_64-gnu/lib/python3.13/unittest/mock.py:244: in assert_called_once_with
return mock.assert_called_once_with(*args, **kwargs)
../../../.local/share/uv/python/cpython-3.13.1-linux-x86_64-gnu/lib/python3.13/unittest/mock.py:989: in assert_called_once_with
return self.assert_called_with(*args, **kwargs)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <MagicMock name='discover_queryables' spec='function' id='139951021718368'>
args = (ECMWFSearch(provider=cop_cds, priority=0, topic=Search),)
kwargs = {'ecmwf:data_format': 'grib', 'ecmwf:dataset': 'reanalysis-era5-single-levels', 'ecmwf:download_format': 'zip', 'ecmwf:product_type': 'reanalysis', ...}
expected = call('', (ECMWFSearch(provider=cop_cds, priority=0, topic=Search),), {'productType': 'ERA5_SL', 'ecmwf:product_type': ...gle-levels', 'ecmwf:data_format': 'grib', 'ecmwf:download_format': 'zip', 'ecmwf:variable': '10m_u_component_of_wind'})
actual = call('', (ECMWFSearch(provider=cop_cds, priority=0, topic=Search),), {'productType': 'ERA5_SL'})
_error_message = <function NonCallableMock.assert_called_with.<locals>._error_message at 0x7f48e216dbc0>
cause = None
def assert_called_with(self, /, *args, **kwargs):
"""assert that the last call was made with the specified arguments.
Raises an AssertionError if the args and keyword args passed in are
different to the last call to the mock."""
if self.call_args is None:
expected = self._format_mock_call_signature(args, kwargs)
actual = 'not called.'
error_message = ('expected call not found.\nExpected: %s\n Actual: %s'
% (expected, actual))
raise AssertionError(error_message)
def _error_message():
msg = self._format_mock_failure_message(args, kwargs)
return msg
expected = self._call_matcher(_Call((args, kwargs), two=True))
actual = self._call_matcher(self.call_args)
if actual != expected:
cause = expected if isinstance(expected, Exception) else None
> raise AssertionError(_error_message()) from cause
E AssertionError: expected call not found.
E Expected: discover_queryables(ECMWFSearch(provider=cop_cds, priority=0, topic=Search), productType='ERA5_SL', ecmwf:product_type='reanalysis', ecmwf:dataset='reanalysis-era5-single-levels', ecmwf:data_format='grib', ecmwf:download_format='zip', ecmwf:variable='10m_u_component_of_wind')
E Actual: discover_queryables(ECMWFSearch(provider=cop_cds, priority=0, topic=Search), productType='ERA5_SL')
../../../.local/share/uv/python/cpython-3.13.1-linux-x86_64-gnu/lib/python3.13/unittest/mock.py:977: AssertionError
Check warning on line 0 in tests.units.test_apis_plugins.TestApisPluginEcmwfApi
github-actions / Test Results
All 2 runs failed: test_plugins_apis_ecmwf_download (tests.units.test_apis_plugins.TestApisPluginEcmwfApi)
artifacts/unit-test-results-python3.13-ubuntu-latest/junit-report.xml [took 2s]
artifacts/unit-test-results-python3.9-ubuntu-latest/junit-report.xml [took 3s]
Raw output
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
self = <tests.units.test_apis_plugins.TestApisPluginEcmwfApi testMethod=test_plugins_apis_ecmwf_download>
mock_connection_call = <function wrapped at 0x7fe8a61702c0>
mock_ecmwfdataserver_retrieve = <function retrieve at 0x7fe8a6170900>
mock_ecmwfservice_execute = <function execute at 0x7fe8a6170f40>
mock_fetch_product_types_list = <function fetch_product_types_list at 0x7fe8a6171620>
@mock.patch(
"eodag.api.core.EODataAccessGateway.fetch_product_types_list", autospec=True
)
@mock.patch("ecmwfapi.api.ECMWFService.execute", autospec=True)
@mock.patch("ecmwfapi.api.ECMWFDataServer.retrieve", autospec=True)
@mock.patch("ecmwfapi.api.Connection.call", autospec=True)
def test_plugins_apis_ecmwf_download(
self,
mock_connection_call,
mock_ecmwfdataserver_retrieve,
mock_ecmwfservice_execute,
mock_fetch_product_types_list,
):
"""EcmwfApi.download must call the appriate ecmwf api service"""
dag = EODataAccessGateway()
dag.set_preferred_provider("ecmwf")
output_data_path = os.path.join(os.path.expanduser("~"), "data")
# public dataset request
def create_empty_file_for_public_dataset(*args, **kwargs):
with open(args[1]["target"], "x"):
pass
mock_ecmwfdataserver_retrieve.side_effect = create_empty_file_for_public_dataset
results = dag.search(
**self.query_dates,
**self.custom_query_params,
)
eoproduct = results[0]
expected_path = os.path.join(
output_data_path, "%s" % eoproduct.properties["title"]
)
arg_path = os.path.join(
output_data_path,
"%s" % eoproduct.properties["title"],
"%s.grib" % eoproduct.properties["title"],
)
> path = eoproduct.download(output_dir=output_data_path)
tests/units/test_apis_plugins.py:297:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
eodag/api/product/_product.py:323: in download
fs_path = self.downloader.download(
eodag/plugins/apis/ecmwf.py:209: in download
download_request = geojson.loads(urlsplit(product.location).query)
.tox/py313/lib/python3.13/site-packages/geojson/codec.py:51: in loads
return json.loads(s,
../../../.local/share/uv/python/cpython-3.13.1-linux-x86_64-gnu/lib/python3.13/json/__init__.py:359: in loads
return cls(**kw).decode(s)
../../../.local/share/uv/python/cpython-3.13.1-linux-x86_64-gnu/lib/python3.13/json/decoder.py:345: in decode
obj, end = self.raw_decode(s, idx=_w(s, 0).end())
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <json.decoder.JSONDecoder object at 0x7fe8a5fc6620>, s = '', idx = 0
def raw_decode(self, s, idx=0):
"""Decode a JSON document from ``s`` (a ``str`` beginning with
a JSON document) and return a 2-tuple of the Python
representation and the index in ``s`` where the document ended.
This can be used to decode a JSON document from a string that may
have extraneous data at the end.
"""
try:
obj, end = self.scan_once(s, idx)
except StopIteration as err:
> raise JSONDecodeError("Expecting value", s, err.value) from None
E json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
../../../.local/share/uv/python/cpython-3.13.1-linux-x86_64-gnu/lib/python3.13/json/decoder.py:363: JSONDecodeError
Check warning on line 0 in tests.units.test_search_plugins.TestSearchPluginPostJsonSearch
github-actions / Test Results
All 2 runs failed: test_plugins_search_postjsonsearch_default_dates (tests.units.test_search_plugins.TestSearchPluginPostJsonSearch)
artifacts/unit-test-results-python3.13-ubuntu-latest/junit-report.xml [took 0s]
artifacts/unit-test-results-python3.9-ubuntu-latest/junit-report.xml [took 0s]
Raw output
AssertionError: expected call not found.
Expected: post('https://gateway.prod.wekeo2.eu/hda-broker/api/v1/dataaccess/search', json={'year': ['2021'], 'month': ['02'], 'day': ['01'], 'time': ['03:00'], 'dataset_id': 'EO:ECMWF:DAT:REANALYSIS_ERA5_SINGLE_LEVELS', 'product_type': 'ensemble_mean', 'variable': '10m_u_component_of_wind', 'download_format': 'unarchived', 'data_format': 'grib', 'itemsPerPage': 20, 'startIndex': 0}, headers={'User-Agent': 'eodag/3.1.0b2.dev11+g6c18ad89'}, timeout=60, verify=True)
Actual: post('https://gateway.prod.wekeo2.eu/hda-broker/api/v1/dataaccess/search', json={'year': ['2021'], 'month': ['02'], 'day': ['01', '02'], 'time': ['03:00'], 'dataset_id': 'EO:ECMWF:DAT:REANALYSIS_ERA5_SINGLE_LEVELS', 'product_type': 'ensemble_mean', 'variable': '10m_u_component_of_wind', 'download_format': 'unarchived', 'data_format': 'grib', 'itemsPerPage': 20, 'startIndex': 0}, headers={'User-Agent': 'eodag/3.1.0b2.dev11+g6c18ad89'}, timeout=60, verify=True)
self = <tests.units.test_search_plugins.TestSearchPluginPostJsonSearch testMethod=test_plugins_search_postjsonsearch_default_dates>
mock_normalize = <function normalize_results at 0x7f219fa61800>
mock_request = <function post at 0x7f219fa61300>
@mock.patch("eodag.plugins.search.qssearch.requests.post", autospec=True)
@mock.patch(
"eodag.plugins.search.qssearch.PostJsonSearch.normalize_results", autospec=True
)
def test_plugins_search_postjsonsearch_default_dates(
self, mock_normalize, mock_request
):
provider = "wekeo_ecmwf"
search_plugins = self.plugins_manager.get_search_plugins(provider=provider)
search_plugin = next(search_plugins)
mock_request.return_value = MockResponse({"features": []}, 200)
# year, month, day, time given -> don't use default dates
search_plugin.query(
prep=PreparedSearch(),
productType="ERA5_SL",
**{
"ecmwf:year": "2020",
"ecmwf:month": ["02"],
"ecmwf:day": ["20", "21"],
"ecmwf:time": ["01:00"],
},
)
mock_request.assert_called_with(
"https://gateway.prod.wekeo2.eu/hda-broker/api/v1/dataaccess/search",
json={
"year": "2020",
"month": ["02"],
"day": ["20", "21"],
"time": ["01:00"],
"dataset_id": "EO:ECMWF:DAT:REANALYSIS_ERA5_SINGLE_LEVELS",
"product_type": "ensemble_mean",
"variable": "10m_u_component_of_wind",
"download_format": "unarchived",
"data_format": "grib",
"itemsPerPage": 20,
"startIndex": 0,
},
headers=USER_AGENT,
timeout=60,
verify=True,
)
# start date given and converted to year, month, day, time
search_plugin.query(
prep=PreparedSearch(),
productType="ERA5_SL",
startTimeFromAscendingNode="2021-02-01T03:00:00Z",
)
> mock_request.assert_called_with(
"https://gateway.prod.wekeo2.eu/hda-broker/api/v1/dataaccess/search",
json={
"year": ["2021"],
"month": ["02"],
"day": ["01"],
"time": ["03:00"],
"dataset_id": "EO:ECMWF:DAT:REANALYSIS_ERA5_SINGLE_LEVELS",
"product_type": "ensemble_mean",
"variable": "10m_u_component_of_wind",
"download_format": "unarchived",
"data_format": "grib",
"itemsPerPage": 20,
"startIndex": 0,
},
headers=USER_AGENT,
timeout=60,
verify=True,
)
tests/units/test_search_plugins.py:967:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
../../../.local/share/uv/python/cpython-3.13.1-linux-x86_64-gnu/lib/python3.13/unittest/mock.py:236: in assert_called_with
return mock.assert_called_with(*args, **kwargs)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <MagicMock name='post' spec='function' id='139782389023808'>
args = ('https://gateway.prod.wekeo2.eu/hda-broker/api/v1/dataaccess/search',)
kwargs = {'headers': {'User-Agent': 'eodag/3.1.0b2.dev11+g6c18ad89'}, 'json': {'data_format': 'grib', 'dataset_id': 'EO:ECMWF:DAT:REANALYSIS_ERA5_SINGLE_LEVELS', 'day': ['01'], 'download_format': 'unarchived', ...}, 'timeout': 60, 'verify': True}
expected = call('', ('https://gateway.prod.wekeo2.eu/hda-broker/api/v1/dataaccess/search',), {'json': {'year': ['2021'], 'month':...age': 20, 'startIndex': 0}, 'headers': {'User-Agent': 'eodag/3.1.0b2.dev11+g6c18ad89'}, 'timeout': 60, 'verify': True})
actual = call('', ('https://gateway.prod.wekeo2.eu/hda-broker/api/v1/dataaccess/search',), {'json': {'year': ['2021'], 'month':...age': 20, 'startIndex': 0}, 'headers': {'User-Agent': 'eodag/3.1.0b2.dev11+g6c18ad89'}, 'timeout': 60, 'verify': True})
_error_message = <function NonCallableMock.assert_called_with.<locals>._error_message at 0x7f219fa60680>
cause = None
def assert_called_with(self, /, *args, **kwargs):
"""assert that the last call was made with the specified arguments.
Raises an AssertionError if the args and keyword args passed in are
different to the last call to the mock."""
if self.call_args is None:
expected = self._format_mock_call_signature(args, kwargs)
actual = 'not called.'
error_message = ('expected call not found.\nExpected: %s\n Actual: %s'
% (expected, actual))
raise AssertionError(error_message)
def _error_message():
msg = self._format_mock_failure_message(args, kwargs)
return msg
expected = self._call_matcher(_Call((args, kwargs), two=True))
actual = self._call_matcher(self.call_args)
if actual != expected:
cause = expected if isinstance(expected, Exception) else None
> raise AssertionError(_error_message()) from cause
E AssertionError: expected call not found.
E Expected: post('https://gateway.prod.wekeo2.eu/hda-broker/api/v1/dataaccess/search', json={'year': ['2021'], 'month': ['02'], 'day': ['01'], 'time': ['03:00'], 'dataset_id': 'EO:ECMWF:DAT:REANALYSIS_ERA5_SINGLE_LEVELS', 'product_type': 'ensemble_mean', 'variable': '10m_u_component_of_wind', 'download_format': 'unarchived', 'data_format': 'grib', 'itemsPerPage': 20, 'startIndex': 0}, headers={'User-Agent': 'eodag/3.1.0b2.dev11+g6c18ad89'}, timeout=60, verify=True)
E Actual: post('https://gateway.prod.wekeo2.eu/hda-broker/api/v1/dataaccess/search', json={'year': ['2021'], 'month': ['02'], 'day': ['01', '02'], 'time': ['03:00'], 'dataset_id': 'EO:ECMWF:DAT:REANALYSIS_ERA5_SINGLE_LEVELS', 'product_type': 'ensemble_mean', 'variable': '10m_u_component_of_wind', 'download_format': 'unarchived', 'data_format': 'grib', 'itemsPerPage': 20, 'startIndex': 0}, headers={'User-Agent': 'eodag/3.1.0b2.dev11+g6c18ad89'}, timeout=60, verify=True)
../../../.local/share/uv/python/cpython-3.13.1-linux-x86_64-gnu/lib/python3.13/unittest/mock.py:977: AssertionError
Check warning on line 0 in tests.units.test_apis_plugins.TestApisPluginEcmwfApi
github-actions / Test Results
All 2 runs failed: test_plugins_apis_ecmwf_download_all (tests.units.test_apis_plugins.TestApisPluginEcmwfApi)
artifacts/unit-test-results-python3.13-ubuntu-latest/junit-report.xml [took 0s]
artifacts/unit-test-results-python3.9-ubuntu-latest/junit-report.xml [took 0s]
Raw output
assert 0 == 2
+ where 0 = <function retrieve at 0x7fe8a71da0c0>.call_count
self = <tests.units.test_apis_plugins.TestApisPluginEcmwfApi testMethod=test_plugins_apis_ecmwf_download_all>
mock_connection_call = <function wrapped at 0x7fe8a71da3e0>
mock_ecmwfdataserver_retrieve = <function retrieve at 0x7fe8a71da0c0>
mock_fetch_product_types_list = <function fetch_product_types_list at 0x7fe8a71dbba0>
@mock.patch(
"eodag.api.core.EODataAccessGateway.fetch_product_types_list", autospec=True
)
@mock.patch("ecmwfapi.api.ECMWFDataServer.retrieve", autospec=True)
@mock.patch("ecmwfapi.api.Connection.call", autospec=True)
def test_plugins_apis_ecmwf_download_all(
self,
mock_connection_call,
mock_ecmwfdataserver_retrieve,
mock_fetch_product_types_list,
):
"""EcmwfApi.download_all must call the appropriate ecmwf api service"""
dag = EODataAccessGateway()
dag.set_preferred_provider("ecmwf")
eoproducts = SearchResult([])
# public dataset request
params = deepcopy(self.query_dates)
params.update(self.custom_query_params)
params["ecmwf:accuracy"] = "bar"
results = dag.search(**params)
eoproducts.extend(results)
params["ecmwf:accuracy"] = "baz"
results = dag.search(**params)
eoproducts.extend(results)
assert len(eoproducts) == 2
paths = dag.download_all(
eoproducts, output_dir=os.path.join(os.path.expanduser("~"), "data")
)
> assert mock_ecmwfdataserver_retrieve.call_count == 2
E assert 0 == 2
E + where 0 = <function retrieve at 0x7fe8a71da0c0>.call_count
tests/units/test_apis_plugins.py:387: AssertionError
Check warning on line 0 in tests.units.test_search_plugins.TestSearchPluginECMWFSearch
github-actions / Test Results
All 2 runs failed: test_plugins_search_ecmwf_search_wekeo_discover_queryables (tests.units.test_search_plugins.TestSearchPluginECMWFSearch)
artifacts/unit-test-results-python3.13-ubuntu-latest/junit-report.xml [took 0s]
artifacts/unit-test-results-python3.9-ubuntu-latest/junit-report.xml [took 0s]
Raw output
TypeError: Search.get_product_type_def_params() got multiple values for argument 'product_type'
self = <tests.units.test_search_plugins.TestSearchPluginECMWFSearch testMethod=test_plugins_search_ecmwf_search_wekeo_discover_queryables>
mock_requests_get = <function get at 0x7fe8a5e134c0>
@mock.patch("eodag.utils.requests.requests.sessions.Session.get", autospec=True)
def test_plugins_search_ecmwf_search_wekeo_discover_queryables(
self, mock_requests_get
):
# One of the providers that has discover_queryables() configured with QueryStringSearch
search_plugin = self.get_search_plugin(provider="wekeo_ecmwf")
self.assertEqual("WekeoECMWFSearch", search_plugin.__class__.__name__)
self.assertEqual(
"ECMWFSearch",
search_plugin.discover_queryables.__func__.__qualname__.split(".")[0],
)
constraints_path = os.path.join(TEST_RESOURCES_PATH, "constraints.json")
with open(constraints_path) as f:
constraints = json.load(f)
wekeo_ecmwf_constraints = {"constraints": constraints[0]}
mock_requests_get.return_value = MockResponse(
wekeo_ecmwf_constraints, status_code=200
)
provider_queryables_from_constraints_file = [
"ecmwf:year",
"ecmwf:month",
"ecmwf:day",
"ecmwf:time",
"ecmwf:variable",
"ecmwf:leadtime_hour",
"ecmwf:type",
"ecmwf:product_type",
]
> queryables = search_plugin._get_product_type_queryables(
product_type="ERA5_SL_MONTHLY", alias=None, filters={}
)
tests/units/test_search_plugins.py:2493:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
eodag/plugins/search/build_search_result.py:483: in _get_product_type_queryables
queryables = self.discover_queryables(**filters) or {}
eodag/plugins/search/build_search_result.py:527: in discover_queryables
formated_filters = self.format_as_provider_keyword(
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = WekeoECMWFSearch(provider=wekeo_ecmwf, priority=0, topic=Search)
product_type = 'ERA5_SL_MONTHLY'
properties = {'completionTimeFromAscendingNode': '2015-01-02T00:00:00+00:00', 'data_format': 'grib', 'dataset': 'EO:ECMWF:DAT:REANALYSIS_ERA5_SINGLE_LEVELS_MONTHLY_MEANS', 'download_format': 'unarchived', ...}
def format_as_provider_keyword(
self, product_type: str, properties: Dict[str, Any]
) -> Dict[str, Any]:
"""Return provider equivalent keyword names from EODAG keywords.
:param product_type: product type id
:param properties: dict of properties to be formatted
:return: dict of formatted properties
"""
properties["productType"] = product_type
# provider product type specific conf
> product_type_def_params = self.get_product_type_def_params(
product_type, **properties
)
E TypeError: Search.get_product_type_def_params() got multiple values for argument 'product_type'
eodag/plugins/search/build_search_result.py:895: TypeError
Check warning on line 0 in tests.units.test_search_plugins.TestSearchPluginECMWFSearch
github-actions / Test Results
All 2 runs failed: test_plugins_search_ecmwfsearch_discover_queryables (tests.units.test_search_plugins.TestSearchPluginECMWFSearch)
artifacts/unit-test-results-python3.13-ubuntu-latest/junit-report.xml [took 0s]
artifacts/unit-test-results-python3.9-ubuntu-latest/junit-report.xml [took 0s]
Raw output
eodag.utils.exceptions.ValidationError: dataset is not a queryable parameter for cop_ads
self = <tests.units.test_search_plugins.TestSearchPluginECMWFSearch testMethod=test_plugins_search_ecmwfsearch_discover_queryables>
mock_requests_get = <function get at 0x7fe8a763f1a0>
@mock.patch("eodag.utils.requests.requests.sessions.Session.get", autospec=True)
def test_plugins_search_ecmwfsearch_discover_queryables(self, mock_requests_get):
constraints_path = os.path.join(TEST_RESOURCES_PATH, "constraints.json")
with open(constraints_path) as f:
constraints = json.load(f)
constraints[0]["variable"].append("nitrogen_dioxide")
constraints[0]["type"].append("validated_reanalysis")
form_path = os.path.join(TEST_RESOURCES_PATH, "form.json")
with open(form_path) as f:
form = json.load(f)
mock_requests_get.return_value.json.side_effect = [constraints, form]
product_type_config = {"missionStartDate": "2001-01-01T00:00:00Z"}
setattr(self.search_plugin.config, "product_type_config", product_type_config)
provider_queryables_from_constraints_file = [
"ecmwf:year",
"ecmwf:month",
"ecmwf:day",
"ecmwf:time",
"ecmwf:variable",
"ecmwf:leadtime_hour",
"ecmwf:type",
"ecmwf:product_type",
]
default_values = deepcopy(
getattr(self.search_plugin.config, "products", {}).get(
"CAMS_EU_AIR_QUALITY_RE", {}
)
)
default_values.pop("metadata_mapping", None)
params = deepcopy(default_values)
params["productType"] = "CAMS_EU_AIR_QUALITY_RE"
> queryables = self.search_plugin.discover_queryables(**params)
tests/units/test_search_plugins.py:2378:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = ECMWFSearch(provider=cop_ads, priority=0, topic=Search)
kwargs = {'data_format': 'zip', 'dataset': 'cams-europe-air-quality-reanalyses', 'level': 0, 'model': 'ensemble', ...}
product_type = 'CAMS_EU_AIR_QUALITY_RE'
pt_config = {'data_format': 'zip', 'dataset': 'cams-europe-air-quality-reanalyses', 'level': 0, 'metadata_mapping': {'abstract': (...cy', (['to_geojson', None], Child(Root(), Fields('accuracy')))], 'acquisitionStation': (None, 'Not Mapped'), ...}, ...}
default_values = {'data_format': 'zip', 'dataset': 'cams-europe-air-quality-reanalyses', 'level': 0, 'model': 'ensemble', ...}
filters = {'data_format': 'zip', 'dataset': 'cams-europe-air-quality-reanalyses', 'level': 0, 'model': 'ensemble', ...}
processed_filters = {'_date': '2001-01-01T00:00:00Z/2001-01-01T00:00:00+00:00', 'completionTimeFromAscendingNode': '2001-01-01T00:00:00+00:00', 'data_format': 'zip', 'dataset': 'cams-europe-air-quality-reanalyses', ...}
constraints_url = 'https://ads.atmosphere.copernicus.eu/api/catalogue/v1/collections/cams-europe-air-quality-reanalyses/constraints.json'
constraints = [{'day': ['01', '02', '10', '20'], 'leadtime_hour': ['24', '48', '72'], 'month': ['01', '02', '03'], 'product_type': [...th': ['06', '07'], 'product_type': ['ensemble_mean', 'reanalysis'], 'time': ['01:00', '12:00', '18:00', '22:00'], ...}]
def discover_queryables(
self, **kwargs: Any
) -> Optional[Dict[str, Annotated[Any, FieldInfo]]]:
"""Fetch queryables list from provider using its constraints file
:param kwargs: additional filters for queryables (`productType` and other search
arguments)
:returns: fetched queryable parameters dict
"""
product_type = kwargs.pop("productType")
pt_config = self.get_product_type_def_params(product_type)
default_values = deepcopy(pt_config)
default_values.pop("metadata_mapping", None)
filters = {**default_values, **kwargs}
if "start" in filters:
filters["startTimeFromAscendingNode"] = filters.pop("start")
if "end" in filters:
filters["completionTimeFromAscendingNode"] = filters.pop("end")
# extract default datetime
processed_filters = self._preprocess_search_params(
deepcopy(filters), product_type
)
constraints_url = format_metadata(
getattr(self.config, "discover_queryables", {}).get("constraints_url", ""),
**filters,
)
constraints: List[Dict[str, Any]] = self.fetch_data(constraints_url)
form_url = format_metadata(
getattr(self.config, "discover_queryables", {}).get("form_url", ""),
**filters,
)
form = self.fetch_data(form_url)
# formated_filters = format_query_params(product_type, self.config, processed_filters)
formated_filters = self.format_as_provider_keyword(
product_type, processed_filters
)
# we re-apply kwargs input to consider override of year, month, day and time.
for key, value in {
**{ecmwf_format(k): v for k, v in default_values.items()},
**kwargs,
}.items():
if key.startswith("ecmwf:"):
formated_filters[key.replace("ecmwf:", "")] = value
elif key in (
"startTimeFromAscendingNode",
"completionTimeFromAscendingNode",
"geom",
):
formated_filters[key] = value
else:
> raise ValidationError(
f"{key} is not a queryable parameter for {self.provider}"
)
E eodag.utils.exceptions.ValidationError: dataset is not a queryable parameter for cop_ads
eodag/plugins/search/build_search_result.py:544: ValidationError
Check warning on line 0 in tests.units.test_search_plugins.TestSearchPluginECMWFSearch
github-actions / Test Results
All 2 runs failed: test_plugins_search_ecmwfsearch_with_custom_producttype (tests.units.test_search_plugins.TestSearchPluginECMWFSearch)
artifacts/unit-test-results-python3.13-ubuntu-latest/junit-report.xml [took 0s]
artifacts/unit-test-results-python3.9-ubuntu-latest/junit-report.xml [took 0s]
Raw output
AssertionError: assert False
+ where False = <built-in method startswith of str object at 0x7fe8a622f3d0>('CAMS-GLOBAL-GHG-REANALYSIS-EGG4')
+ where <built-in method startswith of str object at 0x7fe8a622f3d0> = 'COP_ADS_20200101_20200102_732bbb8a4e587a8b3aece9fab2063a8818af6710'.startswith
+ and 'CAMS-GLOBAL-GHG-REANALYSIS-EGG4' = <built-in method upper of str object at 0x7fe8a7f33730>()
+ where <built-in method upper of str object at 0x7fe8a7f33730> = 'cams-global-ghg-reanalysis-egg4'.upper
self = <tests.units.test_search_plugins.TestSearchPluginECMWFSearch testMethod=test_plugins_search_ecmwfsearch_with_custom_producttype>
def test_plugins_search_ecmwfsearch_with_custom_producttype(self):
"""ECMWFSearch.query must build a EOProduct from input parameters with custom product type"""
results, _ = self.search_plugin.query(
**self.query_dates,
**self.custom_query_params,
)
eoproduct = results[0]
> assert eoproduct.properties["title"].startswith(
self.custom_query_params["ecmwf:dataset"].upper()
)
E AssertionError: assert False
E + where False = <built-in method startswith of str object at 0x7fe8a622f3d0>('CAMS-GLOBAL-GHG-REANALYSIS-EGG4')
E + where <built-in method startswith of str object at 0x7fe8a622f3d0> = 'COP_ADS_20200101_20200102_732bbb8a4e587a8b3aece9fab2063a8818af6710'.startswith
E + and 'CAMS-GLOBAL-GHG-REANALYSIS-EGG4' = <built-in method upper of str object at 0x7fe8a7f33730>()
E + where <built-in method upper of str object at 0x7fe8a7f33730> = 'cams-global-ghg-reanalysis-egg4'.upper
tests/units/test_search_plugins.py:2332: AssertionError
Check warning on line 0 in tests.units.test_search_plugins.TestSearchPluginECMWFSearch
github-actions / Test Results
All 2 runs failed: test_plugins_search_ecmwfsearch_without_producttype (tests.units.test_search_plugins.TestSearchPluginECMWFSearch)
artifacts/unit-test-results-python3.13-ubuntu-latest/junit-report.xml [took 0s]
artifacts/unit-test-results-python3.9-ubuntu-latest/junit-report.xml [took 0s]
Raw output
AssertionError: assert False
+ where False = <built-in method startswith of str object at 0x7fe8a8062b80>('CAMS-GLOBAL-REANALYSIS-EAC4')
+ where <built-in method startswith of str object at 0x7fe8a8062b80> = 'COP_ADS_20200101_20200102_c06a5b0f4d5a7288357bd4e1dc63dee472eb1f62'.startswith
self = <tests.units.test_search_plugins.TestSearchPluginECMWFSearch testMethod=test_plugins_search_ecmwfsearch_without_producttype>
def test_plugins_search_ecmwfsearch_without_producttype(self):
"""
ECMWFSearch.query must build a EOProduct from input parameters without product type.
For test only, result cannot be downloaded.
"""
results, count = self.search_plugin.query(
PreparedSearch(count=True),
**{
"ecmwf:dataset": self.product_dataset,
"startTimeFromAscendingNode": "2020-01-01",
"completionTimeFromAscendingNode": "2020-01-02",
},
)
assert count == 1
eoproduct = results[0]
assert eoproduct.geometry.bounds == (-180.0, -90.0, 180.0, 90.0)
assert eoproduct.properties["startTimeFromAscendingNode"] == "2020-01-01"
assert eoproduct.properties["completionTimeFromAscendingNode"] == "2020-01-02"
assert eoproduct.properties["title"] == eoproduct.properties["id"]
> assert eoproduct.properties["title"].startswith(
f"{self.product_dataset.upper()}"
)
E AssertionError: assert False
E + where False = <built-in method startswith of str object at 0x7fe8a8062b80>('CAMS-GLOBAL-REANALYSIS-EAC4')
E + where <built-in method startswith of str object at 0x7fe8a8062b80> = 'COP_ADS_20200101_20200102_c06a5b0f4d5a7288357bd4e1dc63dee472eb1f62'.startswith
tests/units/test_search_plugins.py:2300: AssertionError
Check warning on line 0 in tests.units.test_search_plugins.TestSearchPluginMeteoblueSearch
github-actions / Test Results
All 2 runs failed: test_plugins_search_buildpostsearchresult_count_and_search (tests.units.test_search_plugins.TestSearchPluginMeteoblueSearch)
artifacts/unit-test-results-python3.13-ubuntu-latest/junit-report.xml [took 0s]
artifacts/unit-test-results-python3.9-ubuntu-latest/junit-report.xml [took 0s]
Raw output
AssertionError: 'http[29 chars]query' != 'http[29 chars]query?{"geometry": {"coordinates": [[[180, -90[95 chars]r"}}'
- https://my.meteoblue.com/dataset/query
+ https://my.meteoblue.com/dataset/query?{"geometry": {"coordinates": [[[180, -90], [180, 90], [-180, 90], [-180, -90], [180, -90]]], "type": "Polygon"}, "queries": {"foo": "bar"}}
self = <tests.units.test_search_plugins.TestSearchPluginMeteoblueSearch testMethod=test_plugins_search_buildpostsearchresult_count_and_search>
mock_requests_post = <function post at 0x7f6159ad7380>
@mock.patch("eodag.plugins.search.qssearch.requests.post", autospec=True)
def test_plugins_search_buildpostsearchresult_count_and_search(
self, mock_requests_post
):
"""A query with a MeteoblueSearch must return a single result"""
# custom query for meteoblue
custom_query = {"queries": {"foo": "bar"}}
products, estimate = self.search_plugin.query(
prep=PreparedSearch(auth_plugin=self.auth_plugin, auth=self.auth),
**custom_query,
)
mock_requests_post.assert_called_with(
self.search_plugin.config.api_endpoint,
json=mock.ANY,
headers=USER_AGENT,
timeout=HTTP_REQ_TIMEOUT,
auth=self.auth,
verify=True,
)
self.assertEqual(estimate, 1)
self.assertIsInstance(products[0], EOProduct)
endpoint = "https://my.meteoblue.com/dataset/query"
default_geom = {
"coordinates": [
[[180, -90], [180, 90], [-180, 90], [-180, -90], [180, -90]]
],
"type": "Polygon",
}
# check downloadLink
> self.assertEqual(
products[0].properties["downloadLink"],
f"{endpoint}?" + json.dumps({"geometry": default_geom, **custom_query}),
)
E AssertionError: 'http[29 chars]query' != 'http[29 chars]query?{"geometry": {"coordinates": [[[180, -90[95 chars]r"}}'
E - https://my.meteoblue.com/dataset/query
E + https://my.meteoblue.com/dataset/query?{"geometry": {"coordinates": [[[180, -90], [180, 90], [-180, 90], [-180, -90], [180, -90]]], "type": "Polygon"}, "queries": {"foo": "bar"}}
tests/units/test_search_plugins.py:1784: AssertionError