anemoi-utils 0.4.21__tar.gz → 0.4.23__tar.gz

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.

Files changed (103) hide show
  1. anemoi_utils-0.4.23/.github/CODEOWNERS +8 -0
  2. {anemoi_utils-0.4.21 → anemoi_utils-0.4.23}/.pre-commit-config.yaml +2 -3
  3. anemoi_utils-0.4.23/.release-please-manifest.json +3 -0
  4. {anemoi_utils-0.4.21 → anemoi_utils-0.4.23}/CHANGELOG.md +17 -0
  5. {anemoi_utils-0.4.21 → anemoi_utils-0.4.23}/PKG-INFO +2 -2
  6. {anemoi_utils-0.4.21 → anemoi_utils-0.4.23}/pyproject.toml +1 -1
  7. {anemoi_utils-0.4.21 → anemoi_utils-0.4.23}/src/anemoi/utils/_version.py +2 -2
  8. {anemoi_utils-0.4.21 → anemoi_utils-0.4.23}/src/anemoi/utils/provenance.py +5 -2
  9. {anemoi_utils-0.4.21 → anemoi_utils-0.4.23}/src/anemoi/utils/remote/s3.py +42 -9
  10. {anemoi_utils-0.4.21 → anemoi_utils-0.4.23}/src/anemoi/utils/testing.py +29 -7
  11. {anemoi_utils-0.4.21 → anemoi_utils-0.4.23}/src/anemoi_utils.egg-info/PKG-INFO +2 -2
  12. {anemoi_utils-0.4.21 → anemoi_utils-0.4.23}/src/anemoi_utils.egg-info/requires.txt +1 -1
  13. anemoi_utils-0.4.21/.github/CODEOWNERS +0 -6
  14. anemoi_utils-0.4.21/.release-please-manifest.json +0 -3
  15. {anemoi_utils-0.4.21 → anemoi_utils-0.4.23}/.gitattributes +0 -0
  16. {anemoi_utils-0.4.21 → anemoi_utils-0.4.23}/.github/ci-hpc-config.yml +0 -0
  17. {anemoi_utils-0.4.21 → anemoi_utils-0.4.23}/.github/dependabot.yml +0 -0
  18. {anemoi_utils-0.4.21 → anemoi_utils-0.4.23}/.github/labeler.yml +0 -0
  19. {anemoi_utils-0.4.21 → anemoi_utils-0.4.23}/.github/pull_request_template.md +0 -0
  20. {anemoi_utils-0.4.21 → anemoi_utils-0.4.23}/.github/release.yml +0 -0
  21. {anemoi_utils-0.4.21 → anemoi_utils-0.4.23}/.github/workflows/downstream-ci-hpc.yml +0 -0
  22. {anemoi_utils-0.4.21 → anemoi_utils-0.4.23}/.github/workflows/pr-conventional-commit.yml +0 -0
  23. {anemoi_utils-0.4.21 → anemoi_utils-0.4.23}/.github/workflows/pr-label-conventional-commits.yml +0 -0
  24. {anemoi_utils-0.4.21 → anemoi_utils-0.4.23}/.github/workflows/pr-label-file-based.yml +0 -0
  25. {anemoi_utils-0.4.21 → anemoi_utils-0.4.23}/.github/workflows/pr-label-public.yml +0 -0
  26. {anemoi_utils-0.4.21 → anemoi_utils-0.4.23}/.github/workflows/python-publish.yml +0 -0
  27. {anemoi_utils-0.4.21 → anemoi_utils-0.4.23}/.github/workflows/python-pull-request.yml +0 -0
  28. {anemoi_utils-0.4.21 → anemoi_utils-0.4.23}/.github/workflows/readthedocs-pr-update.yml +0 -0
  29. {anemoi_utils-0.4.21 → anemoi_utils-0.4.23}/.github/workflows/release-please.yml +0 -0
  30. {anemoi_utils-0.4.21 → anemoi_utils-0.4.23}/.gitignore +0 -0
  31. {anemoi_utils-0.4.21 → anemoi_utils-0.4.23}/.readthedocs.yaml +0 -0
  32. {anemoi_utils-0.4.21 → anemoi_utils-0.4.23}/.release-please-config.json +0 -0
  33. {anemoi_utils-0.4.21 → anemoi_utils-0.4.23}/CONTRIBUTORS.md +0 -0
  34. {anemoi_utils-0.4.21 → anemoi_utils-0.4.23}/LICENSE +0 -0
  35. {anemoi_utils-0.4.21 → anemoi_utils-0.4.23}/README.md +0 -0
  36. {anemoi_utils-0.4.21 → anemoi_utils-0.4.23}/docs/Makefile +0 -0
  37. {anemoi_utils-0.4.21 → anemoi_utils-0.4.23}/docs/_static/logo.png +0 -0
  38. {anemoi_utils-0.4.21 → anemoi_utils-0.4.23}/docs/_static/style.css +0 -0
  39. {anemoi_utils-0.4.21 → anemoi_utils-0.4.23}/docs/_templates/.gitkeep +0 -0
  40. {anemoi_utils-0.4.21 → anemoi_utils-0.4.23}/docs/_templates/apidoc/package.rst.jinja +0 -0
  41. {anemoi_utils-0.4.21 → anemoi_utils-0.4.23}/docs/conf.py +0 -0
  42. {anemoi_utils-0.4.21 → anemoi_utils-0.4.23}/docs/index.rst +0 -0
  43. {anemoi_utils-0.4.21 → anemoi_utils-0.4.23}/docs/installing.rst +0 -0
  44. {anemoi_utils-0.4.21 → anemoi_utils-0.4.23}/docs/modules/checkpoints.rst +0 -0
  45. {anemoi_utils-0.4.21 → anemoi_utils-0.4.23}/docs/modules/config.rst +0 -0
  46. {anemoi_utils-0.4.21 → anemoi_utils-0.4.23}/docs/modules/dates.rst +0 -0
  47. {anemoi_utils-0.4.21 → anemoi_utils-0.4.23}/docs/modules/grib.rst +0 -0
  48. {anemoi_utils-0.4.21 → anemoi_utils-0.4.23}/docs/modules/humanize.rst +0 -0
  49. {anemoi_utils-0.4.21 → anemoi_utils-0.4.23}/docs/modules/provenance.rst +0 -0
  50. {anemoi_utils-0.4.21 → anemoi_utils-0.4.23}/docs/modules/s3.rst +0 -0
  51. {anemoi_utils-0.4.21 → anemoi_utils-0.4.23}/docs/modules/testing.rst +0 -0
  52. {anemoi_utils-0.4.21 → anemoi_utils-0.4.23}/docs/modules/text.rst +0 -0
  53. {anemoi_utils-0.4.21 → anemoi_utils-0.4.23}/docs/scripts/api_build.sh +0 -0
  54. {anemoi_utils-0.4.21 → anemoi_utils-0.4.23}/setup.cfg +0 -0
  55. {anemoi_utils-0.4.21 → anemoi_utils-0.4.23}/src/anemoi/utils/__init__.py +0 -0
  56. {anemoi_utils-0.4.21 → anemoi_utils-0.4.23}/src/anemoi/utils/__main__.py +0 -0
  57. {anemoi_utils-0.4.21 → anemoi_utils-0.4.23}/src/anemoi/utils/caching.py +0 -0
  58. {anemoi_utils-0.4.21 → anemoi_utils-0.4.23}/src/anemoi/utils/checkpoints.py +0 -0
  59. {anemoi_utils-0.4.21 → anemoi_utils-0.4.23}/src/anemoi/utils/cli.py +0 -0
  60. {anemoi_utils-0.4.21 → anemoi_utils-0.4.23}/src/anemoi/utils/commands/__init__.py +0 -0
  61. {anemoi_utils-0.4.21 → anemoi_utils-0.4.23}/src/anemoi/utils/commands/config.py +0 -0
  62. {anemoi_utils-0.4.21 → anemoi_utils-0.4.23}/src/anemoi/utils/commands/requests.py +0 -0
  63. {anemoi_utils-0.4.21 → anemoi_utils-0.4.23}/src/anemoi/utils/compatibility.py +0 -0
  64. {anemoi_utils-0.4.21 → anemoi_utils-0.4.23}/src/anemoi/utils/config.py +0 -0
  65. {anemoi_utils-0.4.21 → anemoi_utils-0.4.23}/src/anemoi/utils/dates.py +0 -0
  66. {anemoi_utils-0.4.21 → anemoi_utils-0.4.23}/src/anemoi/utils/devtools.py +0 -0
  67. {anemoi_utils-0.4.21 → anemoi_utils-0.4.23}/src/anemoi/utils/grib.py +0 -0
  68. {anemoi_utils-0.4.21 → anemoi_utils-0.4.23}/src/anemoi/utils/grids.py +0 -0
  69. {anemoi_utils-0.4.21 → anemoi_utils-0.4.23}/src/anemoi/utils/hindcasts.py +0 -0
  70. {anemoi_utils-0.4.21 → anemoi_utils-0.4.23}/src/anemoi/utils/humanize.py +0 -0
  71. {anemoi_utils-0.4.21 → anemoi_utils-0.4.23}/src/anemoi/utils/logs.py +0 -0
  72. {anemoi_utils-0.4.21 → anemoi_utils-0.4.23}/src/anemoi/utils/mars/__init__.py +0 -0
  73. {anemoi_utils-0.4.21 → anemoi_utils-0.4.23}/src/anemoi/utils/mars/mars.yaml +0 -0
  74. {anemoi_utils-0.4.21 → anemoi_utils-0.4.23}/src/anemoi/utils/mars/requests.py +0 -0
  75. {anemoi_utils-0.4.21 → anemoi_utils-0.4.23}/src/anemoi/utils/registry.py +0 -0
  76. {anemoi_utils-0.4.21 → anemoi_utils-0.4.23}/src/anemoi/utils/remote/__init__.py +0 -0
  77. {anemoi_utils-0.4.21 → anemoi_utils-0.4.23}/src/anemoi/utils/remote/ssh.py +0 -0
  78. {anemoi_utils-0.4.21 → anemoi_utils-0.4.23}/src/anemoi/utils/rules.py +0 -0
  79. {anemoi_utils-0.4.21 → anemoi_utils-0.4.23}/src/anemoi/utils/s3.py +0 -0
  80. {anemoi_utils-0.4.21 → anemoi_utils-0.4.23}/src/anemoi/utils/sanitise.py +0 -0
  81. {anemoi_utils-0.4.21 → anemoi_utils-0.4.23}/src/anemoi/utils/sanitize.py +0 -0
  82. {anemoi_utils-0.4.21 → anemoi_utils-0.4.23}/src/anemoi/utils/schemas/__init__.py +0 -0
  83. {anemoi_utils-0.4.21 → anemoi_utils-0.4.23}/src/anemoi/utils/schemas/errors.py +0 -0
  84. {anemoi_utils-0.4.21 → anemoi_utils-0.4.23}/src/anemoi/utils/text.py +0 -0
  85. {anemoi_utils-0.4.21 → anemoi_utils-0.4.23}/src/anemoi/utils/timer.py +0 -0
  86. {anemoi_utils-0.4.21 → anemoi_utils-0.4.23}/src/anemoi_utils.egg-info/SOURCES.txt +0 -0
  87. {anemoi_utils-0.4.21 → anemoi_utils-0.4.23}/src/anemoi_utils.egg-info/dependency_links.txt +0 -0
  88. {anemoi_utils-0.4.21 → anemoi_utils-0.4.23}/src/anemoi_utils.egg-info/entry_points.txt +0 -0
  89. {anemoi_utils-0.4.21 → anemoi_utils-0.4.23}/src/anemoi_utils.egg-info/top_level.txt +0 -0
  90. {anemoi_utils-0.4.21 → anemoi_utils-0.4.23}/tests/test-transfer-data/directory/b/c/x +0 -0
  91. {anemoi_utils-0.4.21 → anemoi_utils-0.4.23}/tests/test-transfer-data/directory/b/y +0 -0
  92. {anemoi_utils-0.4.21 → anemoi_utils-0.4.23}/tests/test-transfer-data/directory/exotic filename ;^/"'[=.,#]()/303/252/303/274/303/247/303/262/342/234/205.txt" +0 -0
  93. {anemoi_utils-0.4.21 → anemoi_utils-0.4.23}/tests/test-transfer-data/directory/z +0 -0
  94. {anemoi_utils-0.4.21 → anemoi_utils-0.4.23}/tests/test-transfer-data/file +0 -0
  95. {anemoi_utils-0.4.21 → anemoi_utils-0.4.23}/tests/test_caching.py +0 -0
  96. {anemoi_utils-0.4.21 → anemoi_utils-0.4.23}/tests/test_compatibility.py +0 -0
  97. {anemoi_utils-0.4.21 → anemoi_utils-0.4.23}/tests/test_dates.py +0 -0
  98. {anemoi_utils-0.4.21 → anemoi_utils-0.4.23}/tests/test_frequency.py +0 -0
  99. {anemoi_utils-0.4.21 → anemoi_utils-0.4.23}/tests/test_grids.py +0 -0
  100. {anemoi_utils-0.4.21 → anemoi_utils-0.4.23}/tests/test_provenance.py +0 -0
  101. {anemoi_utils-0.4.21 → anemoi_utils-0.4.23}/tests/test_remote.py +0 -0
  102. {anemoi_utils-0.4.21 → anemoi_utils-0.4.23}/tests/test_sanetise.py +0 -0
  103. {anemoi_utils-0.4.21 → anemoi_utils-0.4.23}/tests/test_utils.py +0 -0
@@ -0,0 +1,8 @@
1
+
2
+ # Workflows
3
+ /.github/ @ecmwf/AnemoiSecurity
4
+
5
+ # Project configs
6
+ /pyproject.toml @ecmwf/AnemoiSecurity
7
+ /.pre-commit-config.yaml @ecmwf/AnemoiSecurity
8
+ /.release-please-config.json @ecmwf/AnemoiSecurity
@@ -40,14 +40,13 @@ repos:
40
40
  - --force-single-line-imports
41
41
  - --profile black
42
42
  - repo: https://github.com/astral-sh/ruff-pre-commit
43
- rev: v0.9.9
43
+ rev: v0.11.8
44
44
  hooks:
45
45
  - id: ruff
46
46
  args:
47
47
  - --line-length=120
48
48
  - --fix
49
49
  - --exit-non-zero-on-fix
50
- - --preview
51
50
  - --exclude=docs/**/*_.py
52
51
  - repo: https://github.com/sphinx-contrib/sphinx-lint
53
52
  rev: v1.0.0
@@ -69,7 +68,7 @@ repos:
69
68
  hooks:
70
69
  - id: pyproject-fmt
71
70
  - repo: https://github.com/jshwi/docsig # Check docstrings against function sig
72
- rev: v0.69.1
71
+ rev: v0.69.3
73
72
  hooks:
74
73
  - id: docsig
75
74
  args:
@@ -0,0 +1,3 @@
1
+ {
2
+ ".": "0.4.23"
3
+ }
@@ -8,6 +8,23 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
8
8
  Please add your functional changes to the appropriate section in the PR.
9
9
  Keep it human-readable, your future self will thank you!
10
10
 
11
+ ## [0.4.23](https://github.com/ecmwf/anemoi-utils/compare/0.4.22...0.4.23) (2025-05-20)
12
+
13
+
14
+ ### Bug Fixes
15
+
16
+ * fix list_folder on s3 ([#154](https://github.com/ecmwf/anemoi-utils/issues/154)) ([3ceb42c](https://github.com/ecmwf/anemoi-utils/commit/3ceb42c5185290d4c12e3fe90c3c331e3d8c7a5f))
17
+ * Remove the requirment to have git installed ([#149](https://github.com/ecmwf/anemoi-utils/issues/149)) ([88846e8](https://github.com/ecmwf/anemoi-utils/commit/88846e80be2927050a879ff953a78aecf39c3ac5))
18
+ * Use urllib to make _offline() aware of HTTP(s) proxies. ([#150](https://github.com/ecmwf/anemoi-utils/issues/150)) ([5c4d06f](https://github.com/ecmwf/anemoi-utils/commit/5c4d06f931590cc360eb4ffeeb8753a5d3d72bcb))
19
+
20
+ ## [0.4.22](https://github.com/ecmwf/anemoi-utils/compare/0.4.21...0.4.22) (2025-04-10)
21
+
22
+
23
+ ### Bug Fixes
24
+
25
+ * do not write to existing dir ([#148](https://github.com/ecmwf/anemoi-utils/issues/148)) ([38c6db6](https://github.com/ecmwf/anemoi-utils/commit/38c6db62c113e093d11c49b0fc398587ee89946c))
26
+ * remove archive file after unpacking ([#145](https://github.com/ecmwf/anemoi-utils/issues/145)) ([790e2a3](https://github.com/ecmwf/anemoi-utils/commit/790e2a3370db3d5c275f95b920926d5a01f894a7))
27
+
11
28
  ## [0.4.21](https://github.com/ecmwf/anemoi-utils/compare/0.4.20...0.4.21) (2025-04-07)
12
29
 
13
30
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: anemoi-utils
3
- Version: 0.4.21
3
+ Version: 0.4.23
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
@@ -252,7 +252,7 @@ Provides-Extra: provenance
252
252
  Requires-Dist: gitpython; extra == "provenance"
253
253
  Requires-Dist: nvsmi; extra == "provenance"
254
254
  Provides-Extra: s3
255
- Requires-Dist: boto3<1.36; extra == "s3"
255
+ Requires-Dist: boto3>1.36; extra == "s3"
256
256
  Provides-Extra: tests
257
257
  Requires-Dist: pytest; extra == "tests"
258
258
  Provides-Extra: text
@@ -70,7 +70,7 @@ optional-dependencies.grib = [ "requests" ]
70
70
  optional-dependencies.provenance = [ "gitpython", "nvsmi" ]
71
71
 
72
72
  optional-dependencies.s3 = [
73
- "boto3<1.36",
73
+ "boto3>1.36",
74
74
  ]
75
75
 
76
76
  optional-dependencies.tests = [ "pytest" ]
@@ -17,5 +17,5 @@ __version__: str
17
17
  __version_tuple__: VERSION_TUPLE
18
18
  version_tuple: VERSION_TUPLE
19
19
 
20
- __version__ = version = '0.4.21'
21
- __version_tuple__ = version_tuple = (0, 4, 21)
20
+ __version__ = version = '0.4.23'
21
+ __version_tuple__ = version_tuple = (0, 4, 23)
@@ -47,8 +47,11 @@ def lookup_git_repo(path: str) -> Optional[Any]:
47
47
  Repo, optional
48
48
  The git repository if found, otherwise None.
49
49
  """
50
- from git import InvalidGitRepositoryError
51
- from git import Repo
50
+ try:
51
+ from git import InvalidGitRepositoryError
52
+ from git import Repo
53
+ except ImportError:
54
+ return None
52
55
 
53
56
  while path != "/":
54
57
  try:
@@ -1,10 +1,13 @@
1
- # (C) Copyright 2024 European Centre for Medium-Range Weather Forecasts.
1
+ # (C) Copyright 2024-2025 Anemoi contributors.
2
+ #
2
3
  # This software is licensed under the terms of the Apache Licence Version 2.0
3
4
  # which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
5
+ #
4
6
  # In applying this licence, ECMWF does not waive the privileges and immunities
5
7
  # granted to it by virtue of its status as an intergovernmental organisation
6
8
  # nor does it submit to any jurisdiction.
7
9
 
10
+
8
11
  """This module provides functions to upload, download, list and delete files and folders on S3.
9
12
  The functions of this package expect that the AWS credentials are set up in the environment
10
13
  typicaly by setting the `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` environment variables or
@@ -67,12 +70,14 @@ def s3_client(bucket: str, region: str = None) -> Any:
67
70
 
68
71
  key = f"{bucket}-{region}"
69
72
 
70
- boto3_config = dict(max_pool_connections=25)
71
-
72
73
  if key in thread_local.s3_clients:
73
74
  return thread_local.s3_clients[key]
74
75
 
75
- boto3_config = dict(max_pool_connections=25)
76
+ boto3_config = dict(
77
+ max_pool_connections=25,
78
+ request_checksum_calculation="when_required",
79
+ response_checksum_validation="when_required",
80
+ )
76
81
 
77
82
  if region:
78
83
  # This is using AWS
@@ -162,7 +167,14 @@ class S3Upload(BaseUpload):
162
167
  # delete(target)
163
168
 
164
169
  def _transfer_file(
165
- self, source: str, target: str, overwrite: bool, resume: bool, verbosity: int, threads: int, config: dict = None
170
+ self,
171
+ source: str,
172
+ target: str,
173
+ overwrite: bool,
174
+ resume: bool,
175
+ verbosity: int,
176
+ threads: int,
177
+ config: dict = None,
166
178
  ) -> int:
167
179
  """Transfer a file to S3.
168
180
 
@@ -227,7 +239,13 @@ class S3Upload(BaseUpload):
227
239
 
228
240
  if verbosity > 0:
229
241
  with tqdm.tqdm(total=size, unit="B", unit_scale=True, unit_divisor=1024, leave=False) as pbar:
230
- s3.upload_file(source, bucket, key, Callback=lambda x: pbar.update(x), Config=config)
242
+ s3.upload_file(
243
+ source,
244
+ bucket,
245
+ key,
246
+ Callback=lambda x: pbar.update(x),
247
+ Config=config,
248
+ )
231
249
  else:
232
250
  s3.upload_file(source, bucket, key, Config=config)
233
251
 
@@ -326,7 +344,14 @@ class S3Download(BaseDownload):
326
344
  return s3_object["Size"]
327
345
 
328
346
  def _transfer_file(
329
- self, source: str, target: str, overwrite: bool, resume: bool, verbosity: int, threads: int, config: dict = None
347
+ self,
348
+ source: str,
349
+ target: str,
350
+ overwrite: bool,
351
+ resume: bool,
352
+ verbosity: int,
353
+ threads: int,
354
+ config: dict = None,
330
355
  ) -> int:
331
356
  """Transfer a file from S3 to the local filesystem.
332
357
 
@@ -397,7 +422,13 @@ class S3Download(BaseDownload):
397
422
 
398
423
  if verbosity > 0:
399
424
  with tqdm.tqdm(total=size, unit="B", unit_scale=True, unit_divisor=1024, leave=False) as pbar:
400
- s3.download_file(bucket, key, target, Callback=lambda x: pbar.update(x), Config=config)
425
+ s3.download_file(
426
+ bucket,
427
+ key,
428
+ target,
429
+ Callback=lambda x: pbar.update(x),
430
+ Config=config,
431
+ )
401
432
  else:
402
433
  s3.download_file(bucket, key, target, Config=config)
403
434
 
@@ -524,7 +555,9 @@ def list_folder(folder: str) -> Iterable:
524
555
 
525
556
  for page in paginator.paginate(Bucket=bucket, Prefix=prefix, Delimiter="/"):
526
557
  if "CommonPrefixes" in page:
527
- yield from [folder + _["Prefix"] for _ in page.get("CommonPrefixes")]
558
+ yield from [folder + _["Prefix"] for _ in page.get("CommonPrefixes") if _["Prefix"] != "/"]
559
+ if "Contents" in page:
560
+ yield from [folder + _["Key"] for _ in page.get("Contents")]
528
561
 
529
562
 
530
563
  def object_info(target: str) -> dict:
@@ -68,6 +68,23 @@ def _check_path(path: str) -> None:
68
68
  assert not path.startswith("."), f"Path '{path}' should not start with '.'"
69
69
 
70
70
 
71
+ def _temporary_directory_for_test_data(path: str) -> str:
72
+ """Get the temporary directory for a test dataset.
73
+
74
+ Parameters
75
+ ----------
76
+ path : str
77
+ The relative path to the test data in the object store.
78
+
79
+ Returns
80
+ -------
81
+ str
82
+ The path to the temporary directory.
83
+ """
84
+ _check_path(path)
85
+ return os.path.normpath(os.path.join(_temporary_directory(), path))
86
+
87
+
71
88
  def url_for_test_data(path: str) -> str:
72
89
  """Generate the URL for the test data based on the given path.
73
90
 
@@ -101,12 +118,11 @@ def get_test_data(path: str, gzipped=False) -> str:
101
118
  str
102
119
  The local path to the downloaded test data.
103
120
  """
104
- _check_path(path)
105
121
 
106
122
  if _offline():
107
123
  raise RuntimeError("Offline mode: cannot download test data, add @pytest.mark.skipif(not offline(),...)")
108
124
 
109
- target = os.path.normpath(os.path.join(_temporary_directory(), path))
125
+ target = _temporary_directory_for_test_data(path)
110
126
  with lock:
111
127
  if os.path.exists(target):
112
128
  return target
@@ -153,12 +169,18 @@ def get_test_archive(path: str, extension=".extracted") -> str:
153
169
 
154
170
  with lock:
155
171
 
172
+ target = _temporary_directory_for_test_data(path) + extension
173
+
174
+ if os.path.exists(target):
175
+ return target
176
+
156
177
  archive = get_test_data(path)
157
- target = archive + extension
158
178
 
159
179
  shutil.unpack_archive(archive, os.path.dirname(target) + ".tmp")
160
180
  os.rename(os.path.dirname(target) + ".tmp", target)
161
181
 
182
+ os.remove(archive)
183
+
162
184
  return target
163
185
 
164
186
 
@@ -239,12 +261,12 @@ def _run_slow_tests() -> bool:
239
261
  @lru_cache(maxsize=None)
240
262
  def _offline() -> bool:
241
263
  """Check if we are offline."""
242
-
243
- import socket
264
+ from urllib import request
244
265
 
245
266
  try:
246
- socket.create_connection(("anemoi.ecmwf.int", 443), timeout=5)
247
- except OSError:
267
+ request.urlopen("https://anemoi.ecmwf.int", timeout=1)
268
+ return False
269
+ except request.URLError:
248
270
  return True
249
271
 
250
272
  return False
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: anemoi-utils
3
- Version: 0.4.21
3
+ Version: 0.4.23
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
@@ -252,7 +252,7 @@ Provides-Extra: provenance
252
252
  Requires-Dist: gitpython; extra == "provenance"
253
253
  Requires-Dist: nvsmi; extra == "provenance"
254
254
  Provides-Extra: s3
255
- Requires-Dist: boto3<1.36; extra == "s3"
255
+ Requires-Dist: boto3>1.36; extra == "s3"
256
256
  Provides-Extra: tests
257
257
  Requires-Dist: pytest; extra == "tests"
258
258
  Provides-Extra: text
@@ -36,7 +36,7 @@ gitpython
36
36
  nvsmi
37
37
 
38
38
  [s3]
39
- boto3<1.36
39
+ boto3>1.36
40
40
 
41
41
  [tests]
42
42
  pytest
@@ -1,6 +0,0 @@
1
- # CODEOWNERS file
2
-
3
- # Protect workflow files
4
- /.github/ @theissenhelen @jesperdramsch @gmertes @b8raoult @floriankrb @anaprietonem @HCookie @JPXKQX @mchantry
5
- /.pre-commit-config.yaml @theissenhelen @jesperdramsch @gmertes @b8raoult @floriankrb @anaprietonem @HCookie @JPXKQX @mchantry
6
- /pyproject.toml @theissenhelen @jesperdramsch @gmertes @b8raoult @floriankrb @anaprietonem @HCookie @JPXKQX @mchantry
@@ -1,3 +0,0 @@
1
- {
2
- ".": "0.4.21"
3
- }
File without changes
File without changes
File without changes
File without changes