Skip to content

Commit 900c281

Browse files
committed
Fix API again, add 3.13 support.
1 parent 8ac52aa commit 900c281

File tree

8 files changed

+66
-34
lines changed

8 files changed

+66
-34
lines changed

.github/workflows/test_and_build.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ jobs:
1212
strategy:
1313
fail-fast: false
1414
matrix:
15-
python-version: ["3.9", "3.10", "3.11", "3.12"]
15+
python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]
1616
name: Run tests for ${{ matrix.python-version }}
1717
steps:
1818
- uses: actions/checkout@v3

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,10 @@
1414
> The old Climate Data Store (CDS) has been shut down. All era5cli versions up to v1.4.2 will no longer work.
1515
>
1616
> For more information see:
17-
> https://forum.ecmwf.int/t/the-new-climate-data-store-beta-cds-beta-is-now-live/3315
17+
> https://forum.ecmwf.int/t/goodbye-legacy-climate-data-store-hello-new-climate-data-store-cds/6380/14
1818
>
1919
> To continue using era5cli, you will need to re-register at ECMWF and get a new API key,
20-
> and transition to the era5cli v2 beta. This can be installed with:
20+
> and transition to era5cli version 2. This can be installed with:
2121
> `pip install era5cli==2.0.0`
2222
2323
> [!WARNING]

docs/CHANGELOG.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,22 +7,22 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## Unreleased
99

10-
# 2.0.0 - 2024-10-23
10+
# 2.0.0 - 2025-02-12
1111

1212
Changes since v1.4.2:
1313

1414
**Added:**
1515

16-
- support for Python 3.12.
16+
- support for Python 3.12, 3.13.
1717

1818
**Changed:**
1919

2020
- The `splitmonths` argument now defaults to `True` for hourly requests. To not split requests by year, add `--splitmonths False`.
21+
- The 'cads-api-client' used in the 2.0 beta versions is already deprecated, the backend now uses the 'cdsapi' again, which uses ["datapi"](https://github.com/ecmwf-projects/datapi).
2122

2223
**Fixed:**
2324

2425
- Added support for the new climate data store.
25-
- For authentication, the new `cads-api-client` is used, instead of a dummy request. This should avoid the dummy requests appearing in the user's queue.
2626

2727
**Removed:**
2828

era5cli/fetch.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import logging
55
import os
66
import sys
7-
from cads_api_client import legacy_api_client
7+
import cdsapi
88
from pathos.threading import ThreadPool as Pool
99
import era5cli.inputref as ref
1010
import era5cli.utils
@@ -499,7 +499,7 @@ def _getdata(self, variables: list, years: list, outputfile: str, months=None):
499499
"please do not kill this process in the meantime.",
500500
os.linesep,
501501
)
502-
connection = legacy_api_client.LegacyApiClient(
502+
connection = cdsapi.Client(
503503
url=self.url,
504504
key=self.key,
505505
verify=True,

era5cli/key_management.py

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,16 @@
22
import sys
33
from pathlib import Path
44
from typing import Tuple
5-
import cads_api_client
5+
import cdsapi
66
from requests.exceptions import ConnectionError # pylint: disable=redefined-builtin
77

88

99
ERA5CLI_CONFIG_PATH = Path.home() / ".config" / "era5cli" / "cds_key.txt"
1010
CDSAPI_CONFIG_PATH = Path.home() / ".cdsapirc"
11-
DEFAULT_CDS_URL = "https://cds-beta.climate.copernicus.eu/api"
11+
DEFAULT_CDS_URL = "https://cds.climate.copernicus.eu/api"
1212

13-
AUTH_ERR_MSG = "401 Client Error"
13+
AUTH_ERR_MSG = "401"
14+
NO_DATA_ERR_MSG = "There is no data matching your request"
1415

1516

1617
class InvalidRequestError(Exception):
@@ -34,9 +35,23 @@ def attempt_cds_login(url: str, key: str) -> True:
3435
InvalidRequestError: If the test request failed, likely due to changes in the
3536
CDS API's variable naming.
3637
"""
37-
client = cads_api_client.ApiClient(key=key, url=url)
38+
client = cdsapi.Client(key=key, url=url, verify=True)
3839
try:
39-
client.check_authentication()
40+
# Check the URL
41+
client.status() # pragma: no cover
42+
43+
# Checks if the authentication works, without downloading data
44+
client.retrieve( # pragma: no cover
45+
"reanalysis-era5-single-levels",
46+
{
47+
"variable": "2t",
48+
"product_type": "reanalysis",
49+
"date": "2012-12-01",
50+
"time": "14:00",
51+
"format": "netcdf",
52+
},
53+
)
54+
return True
4055
except ConnectionError as err:
4156
raise ConnectionError(
4257
f"{os.linesep}Failed to connect to CDS. Please check your internet "
@@ -54,6 +69,11 @@ def attempt_cds_login(url: str, key: str) -> True:
5469
f"{ERA5CLI_CONFIG_PATH.resolve()}{os.linesep}"
5570
"Or redefine your configuration with 'era5cli config'"
5671
) from err
72+
if NO_DATA_ERR_MSG in str(err):
73+
raise InvalidRequestError(
74+
f"{os.linesep}Something changed in the CDS API. Please raise an issue "
75+
"on https://www.github.com/eWaterCycle/era5cli"
76+
) from err
5777
raise err # pragma: no cover
5878

5979

@@ -123,7 +143,7 @@ def load_era5cli_config() -> Tuple[str, str]:
123143
"Old config detected. In the new CDS API only a key is required.\n"
124144
"Please look at the new CDS website, and reconfigure your login in "
125145
"era5cli\n"
126-
" https://cds-beta.climate.copernicus.eu/"
146+
" https://cds.climate.copernicus.eu/"
127147
)
128148
raise InvalidLoginError(msg)
129149

@@ -148,7 +168,7 @@ def load_cdsapi_config() -> Tuple[str, str]:
148168
msg = (
149169
"Your CDS API configuration file contains a UID entry/incorrect URL.\n"
150170
"Please look at the new CDS website, and reconfigure your key:\n"
151-
" https://cds-beta.climate.copernicus.eu/"
171+
" https://cds.climate.copernicus.eu/"
152172
)
153173
raise InvalidLoginError(msg)
154174
return url, key

pyproject.toml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ name = "era5cli"
1313
description = "A command line interface to download ERA5 data from the Copernicus Climate Data Store. https://climate.copernicus.eu/.."
1414
readme = "README.md"
1515
license = { text = "Apache Software License" }
16-
requires-python = ">=3.9, <3.13"
16+
requires-python = ">=3.9"
1717
authors = [
1818
{name = "Ronald van Haren"},
1919
{name = "Jaro Camphuijsen"},
@@ -55,10 +55,10 @@ classifiers = [
5555
"Programming Language :: Python :: 3.10",
5656
"Programming Language :: Python :: 3.11",
5757
"Programming Language :: Python :: 3.12",
58+
"Programming Language :: Python :: 3.13",
5859
]
5960
dependencies = [
60-
"cads-api-client>=1.4.6",
61-
"cdsapi",
61+
"cdsapi>=0.7.4",
6262
"pathos",
6363
"PTable",
6464
"netCDF4"
@@ -111,7 +111,7 @@ serve = ["mkdocs serve",]
111111

112112
[tool.black]
113113
line-length = 88
114-
target-version = ['py39', 'py310', 'py311', 'py312']
114+
target-version = ['py39', 'py310', 'py311', 'py312', 'py313']
115115
include = '\.pyi?$'
116116

117117
[tool.isort]

tests/test_config.py

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -122,29 +122,41 @@ class TestAttemptCdsLogin:
122122
expected.
123123
"""
124124

125-
@pytest.mark.xfail(reason="broken by new cads-client api")
126125
def test_status_fail(self):
127-
with patch(
128-
"cads_api_client.ApiClient.check_authentication",
129-
side_effect=rex.ConnectionError,
130-
):
126+
with patch("cdsapi.Client.status", side_effect=rex.ConnectionError):
131127
with pytest.raises(rex.ConnectionError, match="Failed to connect to CDS"):
132-
key_management.attempt_cds_login(
133-
url="https://www.github.com/", key="def"
134-
)
128+
key_management.attempt_cds_login(url="test", key="abc:def")
135129

136130
def test_connection_fail(self):
137-
mp = patch(
138-
"cads_api_client.ApiClient.check_authentication",
139-
side_effect=Exception("401 Client Error"),
131+
mp1 = patch("cdsapi.Client.status")
132+
mp2 = patch(
133+
"cdsapi.Client.retrieve",
134+
side_effect=Exception("401"),
140135
)
141-
with mp:
136+
with mp1, mp2:
142137
with pytest.raises(
143138
key_management.InvalidLoginError,
144139
match="Authorization with the CDS served failed",
140+
):
141+
key_management.attempt_cds_login(
142+
url="https://www.github.com/", key="abc:def"
143+
)
144+
145+
def test_retrieve_fail(self):
146+
mp1 = patch("cdsapi.Client.status")
147+
mp2 = patch(
148+
"cdsapi.Client.retrieve",
149+
side_effect=Exception("There is no data matching your request"),
150+
)
151+
with mp1, mp2:
152+
with pytest.raises(
153+
key_management.InvalidRequestError,
154+
match="Something changed in the CDS API",
145155
):
146156
key_management.attempt_cds_login(url="test", key="abc:def")
147157

148158
def test_all_pass(self):
149-
with patch("cads_api_client.ApiClient.check_authentication"):
150-
key_management.attempt_cds_login(url="test", key="abc:def")
159+
mp1 = patch("cdsapi.Client.status")
160+
mp2 = patch("cdsapi.Client.retrieve")
161+
with mp1, mp2:
162+
assert key_management.attempt_cds_login(url="test", key="abc:def") is True

tests/test_fetch.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ def test_init(mockpatch):
134134
)
135135

136136

137-
@mock.patch("cads_api_client.legacy_api_client.LegacyApiClient", autospec=True)
137+
@mock.patch("cdsapi.Client", autospec=True)
138138
@mock.patch("era5cli.utils.append_history", autospec=True)
139139
def test_fetch_nodryrun(cds, era5cli_utilsappend_history):
140140
"""Test fetch function of Fetch class."""

0 commit comments

Comments
 (0)