anemoi-utils 0.4.31__py3-none-any.whl → 0.4.32__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 anemoi-utils might be problematic. Click here for more details.

anemoi/utils/_version.py CHANGED
@@ -1,14 +1,7 @@
1
1
  # file generated by setuptools-scm
2
2
  # don't change, don't track in version control
3
3
 
4
- __all__ = [
5
- "__version__",
6
- "__version_tuple__",
7
- "version",
8
- "version_tuple",
9
- "__commit_id__",
10
- "commit_id",
11
- ]
4
+ __all__ = ["__version__", "__version_tuple__", "version", "version_tuple"]
12
5
 
13
6
  TYPE_CHECKING = False
14
7
  if TYPE_CHECKING:
@@ -16,19 +9,13 @@ if TYPE_CHECKING:
16
9
  from typing import Union
17
10
 
18
11
  VERSION_TUPLE = Tuple[Union[int, str], ...]
19
- COMMIT_ID = Union[str, None]
20
12
  else:
21
13
  VERSION_TUPLE = object
22
- COMMIT_ID = object
23
14
 
24
15
  version: str
25
16
  __version__: str
26
17
  __version_tuple__: VERSION_TUPLE
27
18
  version_tuple: VERSION_TUPLE
28
- commit_id: COMMIT_ID
29
- __commit_id__: COMMIT_ID
30
19
 
31
- __version__ = version = '0.4.31'
32
- __version_tuple__ = version_tuple = (0, 4, 31)
33
-
34
- __commit_id__ = commit_id = None
20
+ __version__ = version = '0.4.32'
21
+ __version_tuple__ = version_tuple = (0, 4, 32)
anemoi/utils/testing.py CHANGED
@@ -11,6 +11,7 @@ import logging
11
11
  import os
12
12
  import shutil
13
13
  import warnings
14
+ from collections.abc import Callable
14
15
  from functools import lru_cache
15
16
  from pathlib import Path
16
17
 
@@ -42,17 +43,21 @@ def _check_path(path: str) -> None:
42
43
  assert not path.startswith("."), f"Path '{path}' should not start with '.'"
43
44
 
44
45
 
45
- @pytest.fixture(scope="session")
46
- def temporary_directory_for_test_data(tmp_path_factory) -> callable:
47
- base_dir = tmp_path_factory.mktemp("test_data_base")
46
+ class TemporaryDirectoryForTestData:
47
+ def __init__(self, base_dir: Path) -> None:
48
+ self.base_dir = base_dir
48
49
 
49
- def _temporary_directory_for_test_data(path: str = "", archive: bool = False) -> str:
50
+ def __call__(self, path: str = "", archive: bool = False) -> str:
50
51
  if path == "":
51
- return str(base_dir)
52
+ return str(self.base_dir)
52
53
  _check_path(path)
53
- return str(base_dir.joinpath(*Path(path).parts)) + (".extracted" if archive else "")
54
+ return str(self.base_dir.joinpath(*Path(path).parts)) + (".extracted" if archive else "")
55
+
54
56
 
55
- return _temporary_directory_for_test_data
57
+ @pytest.fixture(scope="session")
58
+ def temporary_directory_for_test_data(tmp_path_factory: pytest.TempPathFactory) -> TemporaryDirectoryForTestData:
59
+ base_dir = tmp_path_factory.mktemp("test_data_base")
60
+ return TemporaryDirectoryForTestData(base_dir)
56
61
 
57
62
 
58
63
  def url_for_test_data(path: str) -> str:
@@ -73,11 +78,12 @@ def url_for_test_data(path: str) -> str:
73
78
  return f"{TEST_DATA_URL}{path}"
74
79
 
75
80
 
76
- @pytest.fixture()
77
- def get_test_data(temporary_directory_for_test_data):
78
- def _get_test_data(path: str, gzipped=False) -> callable:
79
- """Download the test data to a temporary directory and return the local path.
81
+ class GetTestData:
82
+ def __init__(self, temporary_directory_for_test_data: TemporaryDirectoryForTestData) -> None:
83
+ self.temporary_directory_for_test_data = temporary_directory_for_test_data
80
84
 
85
+ def __call__(self, path: str, gzipped: bool = False) -> str:
86
+ """Download the test data to a temporary directory and return the local path.
81
87
  Parameters
82
88
  ----------
83
89
  path : str
@@ -94,7 +100,7 @@ def get_test_data(temporary_directory_for_test_data):
94
100
  if _offline():
95
101
  raise RuntimeError("Offline mode: cannot download test data, add @pytest.mark.skipif(not offline(),...)")
96
102
 
97
- target = temporary_directory_for_test_data(path)
103
+ target = self.temporary_directory_for_test_data(path)
98
104
 
99
105
  if os.path.exists(target):
100
106
  return target
@@ -121,12 +127,20 @@ def get_test_data(temporary_directory_for_test_data):
121
127
 
122
128
  return target
123
129
 
124
- return _get_test_data
125
-
126
130
 
127
131
  @pytest.fixture()
128
- def get_test_archive(temporary_directory_for_test_data, get_test_data) -> callable:
129
- def _get_test_archive(path: str) -> str:
132
+ def get_test_data(temporary_directory_for_test_data: TemporaryDirectoryForTestData) -> GetTestData:
133
+ return GetTestData(temporary_directory_for_test_data)
134
+
135
+
136
+ class GetTestArchive:
137
+ def __init__(
138
+ self, temporary_directory_for_test_data: TemporaryDirectoryForTestData, get_test_data: GetTestData
139
+ ) -> None:
140
+ self.temporary_directory_for_test_data = temporary_directory_for_test_data
141
+ self.get_test_data = get_test_data
142
+
143
+ def __call__(self, path: str) -> Path:
130
144
  """Download an archive file (.zip, .tar, .tar.gz, .tar.bz2, .tar.xz) to a temporary directory
131
145
  unpack it, and return the local path to the directory containing the extracted files.
132
146
 
@@ -134,8 +148,6 @@ def get_test_archive(temporary_directory_for_test_data, get_test_data) -> callab
134
148
  ----------
135
149
  path : str
136
150
  The relative path to the test data.
137
- extension : str, optional
138
- The extension to add to the extracted directory, by default '.extracted'
139
151
 
140
152
  Returns
141
153
  -------
@@ -143,12 +155,12 @@ def get_test_archive(temporary_directory_for_test_data, get_test_data) -> callab
143
155
  The local path to the downloaded test data.
144
156
  """
145
157
 
146
- target = Path(temporary_directory_for_test_data(path, archive=True))
158
+ target = Path(self.temporary_directory_for_test_data(path, archive=True))
147
159
 
148
160
  if os.path.exists(target):
149
161
  return target
150
162
 
151
- archive = get_test_data(path)
163
+ archive = self.get_test_data(path)
152
164
 
153
165
  shutil.unpack_archive(archive, os.path.dirname(target) + ".tmp")
154
166
  os.rename(os.path.dirname(target) + ".tmp", target)
@@ -157,7 +169,12 @@ def get_test_archive(temporary_directory_for_test_data, get_test_data) -> callab
157
169
 
158
170
  return target
159
171
 
160
- return _get_test_archive
172
+
173
+ @pytest.fixture()
174
+ def get_test_archive(
175
+ temporary_directory_for_test_data: TemporaryDirectoryForTestData, get_test_data: GetTestData
176
+ ) -> GetTestArchive:
177
+ return GetTestArchive(temporary_directory_for_test_data, get_test_data)
161
178
 
162
179
 
163
180
  def packages_installed(*names: str) -> bool:
@@ -231,28 +248,27 @@ def _run_slow_tests() -> bool:
231
248
  bool
232
249
  True if the SLOW_TESTS environment variable is set, False otherwise.
233
250
  """
234
- return int(os.environ.get("SLOW_TESTS", 0))
251
+ return bool(int(os.environ.get("SLOW_TESTS", 0)))
235
252
 
236
253
 
237
254
  @lru_cache(maxsize=None)
238
255
  def _offline() -> bool:
239
256
  """Check if we are offline."""
240
257
  from urllib import request
258
+ from urllib.error import URLError
241
259
 
242
260
  try:
243
261
  request.urlopen("https://anemoi.ecmwf.int", timeout=1)
244
262
  return False
245
- except request.URLError:
263
+ except URLError:
246
264
  return True
247
265
 
248
- return False
249
-
250
266
 
251
267
  skip_if_offline = pytest.mark.skipif(_offline(), reason="No internet connection")
252
268
  skip_slow_tests = pytest.mark.skipif(not _run_slow_tests(), reason="Skipping slow tests")
253
269
 
254
270
 
255
- def skip_missing_packages(*names: str) -> callable:
271
+ def skip_missing_packages(*names: str) -> pytest.MarkDecorator:
256
272
  """Skip a test if any of the specified packages are missing.
257
273
 
258
274
  Parameters
@@ -268,16 +284,17 @@ def skip_missing_packages(*names: str) -> callable:
268
284
 
269
285
  missing = [f"'{p}'" for p in _missing_packages(*names)]
270
286
 
271
- if len(missing) == 0:
272
- return lambda f: f
287
+ reason = ""
273
288
 
274
289
  if len(missing) == 1:
275
- return pytest.mark.skipif(True, reason=f"Package {missing[0]} is not installed")
290
+ reason = f"Package {missing[0]} is not installed"
291
+ elif len(missing):
292
+ reason = f"Packages {list_to_human(missing)} are not installed"
276
293
 
277
- return pytest.mark.skipif(True, reason=f"Packages {list_to_human(missing)} are not installed")
294
+ return pytest.mark.skipif(len(missing) > 0, reason=reason)
278
295
 
279
296
 
280
- def skip_if_missing_command(cmd: str) -> callable:
297
+ def skip_if_missing_command(cmd: str) -> pytest.MarkDecorator:
281
298
  """Skip a test if the specified command is not available.
282
299
 
283
300
  Parameters
@@ -293,13 +310,10 @@ def skip_if_missing_command(cmd: str) -> callable:
293
310
 
294
311
  import shutil
295
312
 
296
- if shutil.which(cmd):
297
- return lambda f: f
313
+ return pytest.mark.skipif(not shutil.which(cmd), reason=f"Command '{cmd}' is not available")
298
314
 
299
- return pytest.mark.skipif(True, reason=f"Command '{cmd}' is not available")
300
315
 
301
-
302
- def cli_testing(package: str, cmd: str, *args: list[str]) -> None:
316
+ def cli_testing(package: str, cmd: str, *args: str) -> None:
303
317
  """Run a CLI command for testing purposes.
304
318
 
305
319
  Parameters
@@ -309,7 +323,7 @@ def cli_testing(package: str, cmd: str, *args: list[str]) -> None:
309
323
  Can be 'anemoi-datasets' or 'anemoi.datasets'.
310
324
  cmd : str
311
325
  The command to run.
312
- *args : list[str]
326
+ *args : str
313
327
  Additional arguments to pass to the command.
314
328
  """
315
329
 
@@ -323,16 +337,16 @@ def cli_testing(package: str, cmd: str, *args: list[str]) -> None:
323
337
  version=version,
324
338
  description=f"Testing the '{cmd}' CLI command from the '{package}' package.",
325
339
  commands=COMMANDS,
326
- test_arguments=(cmd,) + args,
340
+ test_arguments=[cmd] + list(args),
327
341
  )
328
342
 
329
343
 
330
- def run_tests(globals: dict[str, callable]) -> None:
344
+ def run_tests(globals: dict[str, Callable[[], None]]) -> None:
331
345
  """Run all test functions that start with 'test_'.
332
346
 
333
347
  Parameters
334
348
  ----------
335
- globals : dict[str, callable]
349
+ globals : dict[str, Callable[[], None]]
336
350
  The global namespace containing the test functions.
337
351
 
338
352
  Example
@@ -357,7 +371,6 @@ def run_tests(globals: dict[str, callable]) -> None:
357
371
 
358
372
  for name, obj in list(globals.items()):
359
373
  if name.startswith("test_") and callable(obj):
360
-
361
374
  pytestmark = getattr(obj, "pytestmark", None)
362
375
  if pytestmark is not None:
363
376
  if not isinstance(pytestmark, list):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: anemoi-utils
3
- Version: 0.4.31
3
+ Version: 0.4.32
4
4
  Summary: A package to hold various functions to support training of ML models on ECMWF data.
5
5
  Author-email: "European Centre for Medium-Range Weather Forecasts (ECMWF)" <software.support@ecmwf.int>
6
6
  License: Apache License
@@ -1,6 +1,6 @@
1
1
  anemoi/utils/__init__.py,sha256=uVhpF-VjIl_4mMywOVtgTutgsdIsqz-xdkwxeMhzuag,730
2
2
  anemoi/utils/__main__.py,sha256=6LlE4MYrPvqqrykxXh7XMi50UZteUY59NeM8P9Zs2dU,910
3
- anemoi/utils/_version.py,sha256=bvzZRPAHPCx967KBj1M9nnZf0LAd256lffiAVfk3-ok,706
3
+ anemoi/utils/_version.py,sha256=oAm79fUiHcXTCTEkFD4DV2bxk8dDUofRGFcRzCcXEdU,513
4
4
  anemoi/utils/caching.py,sha256=wKkpsACniNCFK1nc5Tw18EAv9FJGYdhs5p8qsr8i_FI,6153
5
5
  anemoi/utils/checkpoints.py,sha256=U197rvPUD1_XBA-VphgA0staFkgx2TzDoBdbnch-I7Y,9550
6
6
  anemoi/utils/cli.py,sha256=p4sup42X7JW47AKM3IQn4_0-KUAlc5ceBMj8FYmSdlc,6500
@@ -19,7 +19,7 @@ anemoi/utils/rules.py,sha256=YtJcwkyBJwPjHlM4ZM6icGJXLCRZmcuHCXc-SSR8wgw,6856
19
19
  anemoi/utils/s3.py,sha256=bBVlfg3R4sJYOfgrSkhX7MxSVUQEur4LjE86ug8vkNw,4052
20
20
  anemoi/utils/sanitise.py,sha256=XkQzibDbu-VFJkJC4WcB9ovkcTkVAynXtkn1Tlc2CC4,4019
21
21
  anemoi/utils/sanitize.py,sha256=43ZKDcfVpeXSsJ9TFEc9aZnD6oe2cUh151XnDspM98M,462
22
- anemoi/utils/testing.py,sha256=DeTAkmg-RCMPXBBRUy_Gti5UJriUPRKT6ruE3JL2GVc,10372
22
+ anemoi/utils/testing.py,sha256=MKKX43mDwLhEeuMaTt05TFvXvSq6j8yW5jWENKoSiBY,11145
23
23
  anemoi/utils/text.py,sha256=9M7VepzZLL-jGfFGXDqNxjwpNl7tiU8arkkOqhT9iSE,14361
24
24
  anemoi/utils/timer.py,sha256=_leKMYza2faM7JKlGE7LCNy13rbdPnwaCF7PSrI_NmI,3895
25
25
  anemoi/utils/commands/__init__.py,sha256=5u_6EwdqYczIAgJfCwRSyQAYFEqh2ZuHHT57g9g7sdI,808
@@ -39,9 +39,9 @@ anemoi/utils/remote/s3.py,sha256=BWI4bUmZHBvvqU6idewyg4ApxTlhCtX3cpwjeheCSo4,213
39
39
  anemoi/utils/remote/ssh.py,sha256=xNtsawh8okytCKRehkRCVExbHZj-CRUQNormEHglfuw,8088
40
40
  anemoi/utils/schemas/__init__.py,sha256=nkinKlsPLPXEjfTYQT1mpKC4cvs-14w_zBkDRxakwxw,698
41
41
  anemoi/utils/schemas/errors.py,sha256=lgOXzVTYzAE0qWQf3OZ42vCWixv8lilSqLLhzARBmvI,1831
42
- anemoi_utils-0.4.31.dist-info/licenses/LICENSE,sha256=8HznKF1Vi2IvfLsKNE5A2iVyiri3pRjRPvPC9kxs6qk,11354
43
- anemoi_utils-0.4.31.dist-info/METADATA,sha256=EcYf4exSKrdV2BR1W4xJ3sH6e5FMn8L2KOCnL-4fmrI,15668
44
- anemoi_utils-0.4.31.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
45
- anemoi_utils-0.4.31.dist-info/entry_points.txt,sha256=LENOkn88xzFQo-V59AKoA_F_cfYQTJYtrNTtf37YgHY,60
46
- anemoi_utils-0.4.31.dist-info/top_level.txt,sha256=DYn8VPs-fNwr7fNH9XIBqeXIwiYYd2E2k5-dUFFqUz0,7
47
- anemoi_utils-0.4.31.dist-info/RECORD,,
42
+ anemoi_utils-0.4.32.dist-info/licenses/LICENSE,sha256=8HznKF1Vi2IvfLsKNE5A2iVyiri3pRjRPvPC9kxs6qk,11354
43
+ anemoi_utils-0.4.32.dist-info/METADATA,sha256=WyYYg-sVWEvRSZH9-uyqAdP3oemUq4DI97sZExxibD8,15668
44
+ anemoi_utils-0.4.32.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
45
+ anemoi_utils-0.4.32.dist-info/entry_points.txt,sha256=LENOkn88xzFQo-V59AKoA_F_cfYQTJYtrNTtf37YgHY,60
46
+ anemoi_utils-0.4.32.dist-info/top_level.txt,sha256=DYn8VPs-fNwr7fNH9XIBqeXIwiYYd2E2k5-dUFFqUz0,7
47
+ anemoi_utils-0.4.32.dist-info/RECORD,,