freva-client 2508.0.0__py3-none-any.whl → 2509.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of freva-client might be problematic. Click here for more details.

@@ -40,15 +40,50 @@ class Config:
40
40
  self,
41
41
  host: Optional[str] = None,
42
42
  uniq_key: Literal["file", "uri"] = "file",
43
- flavour: str = "freva",
43
+ flavour: Optional[str] = None,
44
44
  ) -> None:
45
45
  self.databrowser_url = f"{self.get_api_url(host)}/databrowser"
46
46
  self.auth_url = f"{self.get_api_url(host)}/auth/v2"
47
+ self.get_api_main_url = self.get_api_url(host)
47
48
  self.uniq_key = uniq_key
48
- self._flavour = flavour
49
+ self.flavour = self.get_flavour(flavour)
49
50
 
50
- def _read_ini(self, path: Path) -> str:
51
- """Read an ini file."""
51
+ @cached_property
52
+ def validate_server(self) -> bool:
53
+ """Ping the databrowser to check if it is reachable."""
54
+ try:
55
+ res = requests.get(f"{self.get_api_main_url}/ping", timeout=15)
56
+ return res.status_code == 200
57
+ except Exception as e:
58
+ raise ValueError(
59
+ f"Could not connect to {self.databrowser_url}: {e}"
60
+ ) from None
61
+
62
+ def get_flavour(self, flavour: Optional[str]) -> str:
63
+ """Get the current flavour."""
64
+ if flavour:
65
+ return flavour
66
+ else:
67
+ try:
68
+ config_flavour = self._get_databrowser_params_from_config().get(
69
+ "flavour", ""
70
+ )
71
+ return config_flavour or "freva"
72
+ except ValueError:
73
+ return "freva"
74
+
75
+ def _read_ini(self, path: Path) -> Dict[str, str]:
76
+ """Read an ini file.
77
+
78
+ Parameters
79
+ ----------
80
+ path : Path
81
+ Path to the ini configuration file.
82
+ Returns
83
+ -------
84
+ Dict[str, str]
85
+ Dictionary with the configuration.
86
+ """
52
87
  ini_parser = ConfigParser(interpolation=ExtendedInterpolation())
53
88
  ini_parser.read_string(path.read_text())
54
89
  config = ini_parser["evaluation_system"]
@@ -59,41 +94,99 @@ class Config:
59
94
  port = port or config.get("databrowser.port", "")
60
95
  if port:
61
96
  host = f"{host}:{port}"
62
- return f"{scheme}://{host}"
97
+ host = f"{scheme}://{host}"
98
+ flavour = config.get("databrowser.default_flavour", "")
99
+ return {
100
+ "host": host,
101
+ "flavour": flavour,
102
+ }
63
103
 
64
- def _read_toml(self, path: Path) -> str:
65
- """Read a new style toml config file."""
104
+ def _read_toml(self, path: Path) -> Dict[str, str]:
105
+ """Read a new style toml config file.
106
+
107
+ Parameters
108
+ ----------
109
+ path : Path
110
+ Path to the toml configuration file.
111
+ Returns
112
+ -------
113
+ Dict[str, str]
114
+ Dictionary with the configuration.
115
+ """
66
116
  try:
67
117
  config = tomli.loads(path.read_text()).get("freva", {})
68
- scheme, host = self._split_url(cast(str, config["host"]))
118
+ scheme, host = self._split_url(cast(str, config.get("host", "")))
119
+ flavour = config.get("default_flavour", "")
69
120
  except (tomli.TOMLDecodeError, KeyError):
70
- return ""
121
+ return {}
71
122
  host, _, port = host.partition(":")
72
123
  if port:
73
124
  host = f"{host}:{port}"
74
- return f"{scheme}://{host}"
125
+ host = f"{scheme}://{host}"
126
+ return {
127
+ "host": host,
128
+ "flavour": flavour,
129
+ }
75
130
 
76
- def _read_config(self, path: Path, file_type: Literal["toml", "ini"]) -> str:
77
- """Read the configuration."""
131
+ def _read_config(
132
+ self, path: Path, file_type: Literal["toml", "ini"]
133
+ ) -> Dict[str, str]:
134
+ """Read the configuration.
135
+
136
+ Parameters
137
+ ----------
138
+ path : Path
139
+ Path to the configuration file.
140
+ file_type : Literal["toml", "ini"]
141
+ Type of the configuration file.
142
+ Returns
143
+ -------
144
+ Dict[str, str]
145
+ Dictionary with the configuration.
146
+ """
78
147
  data_types = {"toml": self._read_toml, "ini": self._read_ini}
79
148
  try:
80
149
  return data_types[file_type](path)
81
150
  except KeyError:
82
151
  pass
83
- return ""
152
+ return {}
153
+
154
+ @cached_property
155
+ def _get_headers(self) -> Optional[Dict[str, str]]:
156
+ """Get the headers for requests."""
157
+ from freva_client.auth import Auth
158
+
159
+ from .auth_utils import load_token
160
+ auth = Auth()
161
+ token = auth._auth_token or load_token(auth.token_file)
162
+ if token and "access_token" in token:
163
+ return {"Authorization": f"Bearer {token['access_token']}"}
164
+ return None
84
165
 
85
166
  @cached_property
86
167
  def overview(self) -> Dict[str, Any]:
87
- """Get an overview of the all databrowser flavours and search keys."""
168
+ """Get an overview of all databrowser flavours
169
+ and search keys including custom flavours."""
170
+ headers = self._get_headers
88
171
  try:
89
- res = requests.get(f"{self.databrowser_url}/overview", timeout=15)
172
+ res = requests.get(
173
+ f"{self.databrowser_url}/overview",
174
+ headers=headers,
175
+ timeout=15
176
+ )
177
+ data = cast(Dict[str, Any], res.json())
178
+ if not headers:
179
+ data["Note"] = (
180
+ "Displaying only global flavours. "
181
+ "Authenticate to see custom user flavours as well."
182
+ )
183
+ return data
90
184
  except requests.exceptions.ConnectionError:
91
185
  raise ValueError(
92
186
  f"Could not connect to {self.databrowser_url}"
93
187
  ) from None
94
- return cast(Dict[str, Any], res.json())
95
188
 
96
- def _get_databrowser_host_from_config(self) -> str:
189
+ def _get_databrowser_params_from_config(self) -> Dict[str, str]:
97
190
  """Get the config file order."""
98
191
 
99
192
  eval_conf = self.get_dirs(user=False) / "evaluation_system.conf"
@@ -111,26 +204,20 @@ class Config:
111
204
  }
112
205
  for config_path, config_type in paths.items():
113
206
  if config_path.is_file():
114
- host = self._read_config(config_path, config_type)
207
+ config_data = self._read_config(config_path, config_type)
208
+ host = config_data.get("host", "")
209
+ flavour = config_data.get("flavour", "")
115
210
  if host:
116
- return host
211
+ return {
212
+ "host": host,
213
+ "flavour": flavour
214
+ }
117
215
  raise ValueError(
118
216
  "No databrowser host configured, please use a"
119
217
  " configuration defining a databrowser host or"
120
218
  " set a host name using the `host` key"
121
219
  )
122
220
 
123
- @cached_property
124
- def flavour(self) -> str:
125
- """Get the flavour."""
126
- flavours = self.overview.get("flavours", [])
127
- if self._flavour not in flavours:
128
- raise ValueError(
129
- f"Search {self._flavour} not available, select from"
130
- f" {','.join(flavours)}"
131
- )
132
- return self._flavour
133
-
134
221
  @property
135
222
  def search_url(self) -> str:
136
223
  """Define the data search endpoint."""
@@ -172,7 +259,7 @@ class Config:
172
259
 
173
260
  def get_api_url(self, url: Optional[str]) -> str:
174
261
  """Construct the databrowser url from a given hostname."""
175
- url = url or self._get_databrowser_host_from_config()
262
+ url = url or self._get_databrowser_params_from_config().get("host", "")
176
263
  scheme, hostname = self._split_url(url)
177
264
  hostname, _, port = hostname.partition(":")
178
265
  if port:
@@ -207,7 +294,6 @@ class Config:
207
294
 
208
295
  class UserDataHandler:
209
296
  """Class for processing user data.
210
-
211
297
  This class is used for processing user data and extracting metadata
212
298
  from the data files.
213
299
  """
@@ -17,3 +17,8 @@
17
17
  ## You can set a port by separating <hostname:port>
18
18
  ## for example freva.example.org:7777
19
19
  # host = ""
20
+
21
+ ##
22
+ ## The default flavour to use when accessing freva. You can simply list
23
+ ## the flavours you want to use and choose one as default.
24
+ # default_flavour = "cmip6"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: freva-client
3
- Version: 2508.0.0
3
+ Version: 2509.0.0
4
4
  Summary: Search for climate data based on key-value pairs
5
5
  Author-email: "DKRZ, Clint" <freva@dkrz.de>
6
6
  Requires-Python: >=3.8
@@ -0,0 +1,20 @@
1
+ freva_client/__init__.py,sha256=6C-njQv12FgsYk2cWv2y3PPBZYfO99qPPeAFmyQhZyA,916
2
+ freva_client/__main__.py,sha256=JVj12puT4o8JfhKLAggR2-NKCZa3wKwsYGi4HQ61DOQ,149
3
+ freva_client/auth.py,sha256=yq_W8DjYA3W2b5HLKTplg5s_prJR9um9NV4uxHMIS2M,10897
4
+ freva_client/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
+ freva_client/query.py,sha256=Dm6Wy9U8ofzZd4v50Sjhl4Guh7njrClSnNNV5_7UdM0,49433
6
+ freva_client/cli/__init__.py,sha256=NgTqBZGdozmTZtJduJUMrZj-opGw2KoT20tg6sc_xqo,149
7
+ freva_client/cli/auth_cli.py,sha256=lM6QNcewh9Cz7DtHO4Wu6iv7GapwplyjhDRfmIlzyJ0,1950
8
+ freva_client/cli/cli_app.py,sha256=QH6cb9XZTx8S9L0chPWOVd9Jn4GD1hd3sENAhdzmLZU,887
9
+ freva_client/cli/cli_parser.py,sha256=EyzvTr70TBCD0mO2P3mVNtuEeEbNk2OdrhKSEHuu6NE,5101
10
+ freva_client/cli/cli_utils.py,sha256=9h2hlBQA-D3n-JlFIC1DSuzEEv73Bpu8lXLAqZBDaYI,1946
11
+ freva_client/cli/databrowser_cli.py,sha256=LpK6NvHWsbHVeJvOHG_su0dh9FHkLxTmY4K8P75S8A0,39397
12
+ freva_client/utils/__init__.py,sha256=ySHn-3CZBwfZW2s0EpZ3INxUWOw1V4LOlKIxSLYr52U,1000
13
+ freva_client/utils/auth_utils.py,sha256=6didULriVK72D_Ptj8UV5wRrMl_w1C9vIoietpy3cG8,7206
14
+ freva_client/utils/databrowser_utils.py,sha256=Hv39Q8Crd63l2U-lBJfppMn14BUm6ECY0ASsgP_8du8,17801
15
+ freva_client/utils/logger.py,sha256=vjBbNb9KvyMriBPpgIoJjlQFCEj3DLqkJu8tYxfp2xI,2494
16
+ freva_client-2509.0.0.data/data/share/freva/freva.toml,sha256=5xXWBqw0W6JyWfRMaSNnKDOGkDznx6NFaJvggh-cUPU,899
17
+ freva_client-2509.0.0.dist-info/entry_points.txt,sha256=zGyEwHrH_kAGLsCXv00y7Qnp-WjXkUuIomHkfGMCxtA,53
18
+ freva_client-2509.0.0.dist-info/WHEEL,sha256=G2gURzTEtmeR8nrdXUJfNiB3VYVxigPQ-bEQujpNiNs,82
19
+ freva_client-2509.0.0.dist-info/METADATA,sha256=gf2-uq7wTLtweozJYjxkFXkBOh-d8b2s1ys15nYv_rc,2487
20
+ freva_client-2509.0.0.dist-info/RECORD,,
@@ -1,20 +0,0 @@
1
- freva_client/__init__.py,sha256=Yh9B2N-5bZJgwcHOxXDMg5hEOgetBoU3TmbsE6IVLQk,851
2
- freva_client/__main__.py,sha256=JVj12puT4o8JfhKLAggR2-NKCZa3wKwsYGi4HQ61DOQ,149
3
- freva_client/auth.py,sha256=p1itCygbLgEaCFTPWgqoId3S9PteP1lrziULziKzPG4,10453
4
- freva_client/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
- freva_client/query.py,sha256=SQx5c4lNwP7ZiP1u6uN7pbUyvdjv74s2vQ3kRAa_708,41906
6
- freva_client/cli/__init__.py,sha256=NgTqBZGdozmTZtJduJUMrZj-opGw2KoT20tg6sc_xqo,149
7
- freva_client/cli/auth_cli.py,sha256=hCgTxN930uTj5Z0NqItAyejiUI9E-1oSv_lWOVoHNUo,1780
8
- freva_client/cli/cli_app.py,sha256=QH6cb9XZTx8S9L0chPWOVd9Jn4GD1hd3sENAhdzmLZU,887
9
- freva_client/cli/cli_parser.py,sha256=EyzvTr70TBCD0mO2P3mVNtuEeEbNk2OdrhKSEHuu6NE,5101
10
- freva_client/cli/cli_utils.py,sha256=Ev9UxM4S1ZDbZSAGHFe5dMjVGot75w3muNKH3P80bHY,842
11
- freva_client/cli/databrowser_cli.py,sha256=eUd-lbSQaRyczLKQQLY_eKU3VRf6Zg5HaHMQbe2Ib5Q,32242
12
- freva_client/utils/__init__.py,sha256=ySHn-3CZBwfZW2s0EpZ3INxUWOw1V4LOlKIxSLYr52U,1000
13
- freva_client/utils/auth_utils.py,sha256=Tma8aPi32zhJ-z2o6gEe1LvpBFlkn-t__UgZONcuARY,6032
14
- freva_client/utils/databrowser_utils.py,sha256=X9M71mBfc8lauyLh3t1CCxhu_96Ya_NVkMNdxmWTsjE,15109
15
- freva_client/utils/logger.py,sha256=vjBbNb9KvyMriBPpgIoJjlQFCEj3DLqkJu8tYxfp2xI,2494
16
- freva_client-2508.0.0.data/data/share/freva/freva.toml,sha256=64Rh4qvWc9TaGJMXMi8tZW14FnESt5Z24y17BfD2VyM,736
17
- freva_client-2508.0.0.dist-info/entry_points.txt,sha256=zGyEwHrH_kAGLsCXv00y7Qnp-WjXkUuIomHkfGMCxtA,53
18
- freva_client-2508.0.0.dist-info/WHEEL,sha256=G2gURzTEtmeR8nrdXUJfNiB3VYVxigPQ-bEQujpNiNs,82
19
- freva_client-2508.0.0.dist-info/METADATA,sha256=8oAcxK-rhgUnBSSmUUsVcEJTNlzOcnWCkS91UaqhMqk,2487
20
- freva_client-2508.0.0.dist-info/RECORD,,