anemoi-utils 0.4.28__py3-none-any.whl → 0.4.30__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/rules.py CHANGED
@@ -7,17 +7,13 @@
7
7
  # granted to it by virtue of its status as an intergovernmental organisation
8
8
  # nor does it submit to any jurisdiction.
9
9
 
10
+ from collections.abc import Mapping
10
11
  from typing import Any
11
- from typing import Dict
12
- from typing import List
13
- from typing import Mapping
14
- from typing import Optional
15
- from typing import Union
16
12
 
17
13
 
18
14
  class Rule:
19
15
 
20
- def __init__(self, match: Dict[str, Any], result: Any):
16
+ def __init__(self, match: dict[str, Any], result: Any):
21
17
  """Initialize a Rule object.
22
18
 
23
19
  Parameters
@@ -55,14 +51,14 @@ class Rule:
55
51
  return self._result
56
52
 
57
53
  @property
58
- def condition(self) -> Dict[str, Any]:
54
+ def condition(self) -> dict[str, Any]:
59
55
  """The conditions that define the rule."""
60
56
  return self._match
61
57
 
62
58
 
63
59
  class RuleSet:
64
60
 
65
- def __init__(self, rules: List[Union[Rule, Dict[str, Any], List[Any]]]):
61
+ def __init__(self, rules: list[Rule | dict[str, Any] | list[Any]]):
66
62
  """Initialize a RuleSet object.
67
63
 
68
64
  Parameters
@@ -73,7 +69,7 @@ class RuleSet:
73
69
  """
74
70
  assert isinstance(rules, list), "rules must be a list"
75
71
 
76
- self.rules: List[Rule] = []
72
+ self.rules: list[Rule] = []
77
73
 
78
74
  for rule in rules:
79
75
  if isinstance(rule, Rule):
@@ -107,7 +103,7 @@ class RuleSet:
107
103
  )
108
104
 
109
105
  @classmethod
110
- def from_list(cls, rules: List[Any]) -> "RuleSet":
106
+ def from_list(cls, rules: list[Any]) -> "RuleSet":
111
107
  """Create a RuleSet from a list of rules.
112
108
 
113
109
  Parameters
@@ -144,19 +140,19 @@ class RuleSet:
144
140
  if path.endswith(".json"):
145
141
  import json
146
142
 
147
- with open(path, "r") as f:
143
+ with open(path) as f:
148
144
  return cls.from_list(json.load(f))
149
145
 
150
146
  if path.endswith(".yaml") or path.endswith(".yml"):
151
147
  import yaml
152
148
 
153
- with open(path, "r") as f:
149
+ with open(path) as f:
154
150
  return cls.from_list(yaml.safe_load(f))
155
151
 
156
152
  raise ValueError("Unsupported file format. Supported formats are .json and .yaml/.yml.")
157
153
 
158
154
  @classmethod
159
- def from_any(cls, rules: Union[str, List[Any]]) -> "RuleSet":
155
+ def from_any(cls, rules: str | list[Any]) -> "RuleSet":
160
156
  """Create a RuleSet from a list or a file path.
161
157
 
162
158
  Parameters
@@ -182,7 +178,7 @@ class RuleSet:
182
178
 
183
179
  raise ValueError("Unsupported rules format. Must be a list or a file path.")
184
180
 
185
- def match(self, obj: Mapping[str, Any], strategy: str = "first-match") -> Optional[Rule]:
181
+ def match(self, obj: Mapping[str, Any], strategy: str = "first-match") -> Rule | None:
186
182
  """Match an object against the rules in the RuleSet.
187
183
 
188
184
  Parameters
anemoi/utils/s3.py CHANGED
@@ -8,9 +8,8 @@
8
8
  # nor does it submit to any jurisdiction.
9
9
 
10
10
  import warnings
11
+ from collections.abc import Callable
11
12
  from typing import Any
12
- from typing import Callable
13
- from typing import Optional
14
13
 
15
14
  from .remote import transfer
16
15
  from .remote.s3 import delete as delete_
@@ -55,7 +54,7 @@ def upload(
55
54
  overwrite: bool = False,
56
55
  resume: bool = False,
57
56
  verbosity: int = 1,
58
- progress: Optional[Callable] = None,
57
+ progress: Callable | None = None,
59
58
  threads: int = 1,
60
59
  ) -> None:
61
60
  """Upload a file to S3.
anemoi/utils/sanitise.py CHANGED
@@ -17,19 +17,24 @@ from urllib.parse import urlencode
17
17
  from urllib.parse import urlparse
18
18
  from urllib.parse import urlunparse
19
19
 
20
- # Patterns used but earthkit-data for url-patterns and path-patterns
20
+ # Patterns used by earthkit-data for url-patterns and path-patterns
21
21
 
22
- RE1 = re.compile(r"{([^}]*)}")
23
- RE2 = re.compile(r"\(([^}]*)\)")
22
+ RE1 = re.compile(r"{([^}]*)}") # {*}
23
+ RE2 = re.compile(r"\(([^}]*)\)") # (*)
24
24
 
25
25
 
26
- def sanitise(obj: Any) -> Any:
27
- """Sanitise an object by replacing all full paths with shortened versions and URL passwords with '***'.
26
+ def sanitise(obj: Any, level=1) -> Any:
27
+ """Sanitise an object by replacing all full paths with shortened versions and URL credentials with '***'.
28
28
 
29
29
  Parameters
30
30
  ----------
31
31
  obj : Any
32
32
  The object to sanitise.
33
+ level : int, optional
34
+ The level of sanitation. The higher levels will also apply the levels below it.
35
+ - 1: Shorten file paths to file name and hide credentials in URLs (default).
36
+ - 2: Hide hostnames in URLs.
37
+ - 3: Hide full file paths and URLs.
33
38
 
34
39
  Returns
35
40
  -------
@@ -37,6 +42,8 @@ def sanitise(obj: Any) -> Any:
37
42
  The sanitised object.
38
43
  """
39
44
 
45
+ assert level in (1, 2, 3), "level must be 1, 2 or 3"
46
+
40
47
  if isinstance(obj, dict):
41
48
  return {sanitise(k): sanitise(v) for k, v in obj.items()}
42
49
 
@@ -47,29 +54,21 @@ def sanitise(obj: Any) -> Any:
47
54
  return tuple(sanitise(v) for v in obj)
48
55
 
49
56
  if isinstance(obj, str):
50
- return _sanitise_string(obj)
57
+ return _sanitise_string(obj, level)
51
58
 
52
59
  return obj
53
60
 
54
61
 
55
- def _sanitise_string(obj: str) -> str:
56
- """Sanitise a string by replacing full paths and URL passwords.
57
-
58
- Parameters
59
- ----------
60
- obj : str
61
- The string to sanitise.
62
-
63
- Returns
64
- -------
65
- str
66
- The sanitised string.
67
- """
62
+ def _sanitise_string(obj: str, level=1) -> str:
63
+ """Sanitise a string by replacing full paths and URL passwords."""
68
64
 
69
65
  parsed = urlparse(obj, allow_fragments=True)
70
66
 
71
67
  if parsed.scheme and parsed.scheme[0].isalpha():
72
- return _sanitise_url(parsed)
68
+ return _sanitise_url(parsed, level)
69
+
70
+ if level > 2:
71
+ return "hidden"
73
72
 
74
73
  if obj.startswith("/") or obj.startswith("~"):
75
74
  return _sanitise_path(obj)
@@ -77,19 +76,8 @@ def _sanitise_string(obj: str) -> str:
77
76
  return obj
78
77
 
79
78
 
80
- def _sanitise_url(parsed: Any) -> str:
81
- """Sanitise a URL by replacing passwords with '***'.
82
-
83
- Parameters
84
- ----------
85
- parsed : Any
86
- The parsed URL.
87
-
88
- Returns
89
- -------
90
- str
91
- The sanitised URL.
92
- """
79
+ def _sanitise_url(parsed: Any, level=1) -> str:
80
+ """Sanitise a URL by replacing passwords with '***'."""
93
81
 
94
82
  LIST = [
95
83
  "pass",
@@ -107,6 +95,9 @@ def _sanitise_url(parsed: Any) -> str:
107
95
  "_api_key",
108
96
  "username",
109
97
  "login",
98
+ "auth",
99
+ "auth_token",
100
+ "auth_key",
110
101
  ]
111
102
 
112
103
  scheme, netloc, path, params, query, fragment = parsed
@@ -130,26 +121,25 @@ def _sanitise_url(parsed: Any) -> str:
130
121
  qs[k] = "hidden"
131
122
  params = urlencode(qs, doseq=True)
132
123
 
133
- return urlunparse([scheme, netloc, path, params, query, fragment])
124
+ if level > 1:
125
+ if (bits := netloc.split("@")) and len(bits) > 1:
126
+ netloc = f"{bits[0]}@hidden"
127
+ else:
128
+ netloc = "hidden"
134
129
 
130
+ if level > 2:
131
+ return urlunparse([scheme, netloc, "", "", "", ""])
135
132
 
136
- def _sanitise_path(path: str) -> str:
137
- """Sanitise a file path by shortening it.
133
+ return urlunparse([scheme, netloc, path, params, query, fragment])
138
134
 
139
- Parameters
140
- ----------
141
- path : str
142
- The file path to sanitise.
143
135
 
144
- Returns
145
- -------
146
- str
147
- The sanitised file path.
148
- """
136
+ def _sanitise_path(path: str) -> str:
137
+ """Sanitise a file path by shortening it."""
149
138
  bits = list(reversed(Path(path).parts))
150
139
  result = [bits.pop(0)]
151
140
  for bit in bits:
152
141
  if RE1.match(bit) or RE2.match(bit):
142
+ # keep earthkit-data folder patterns
153
143
  result.append(bit)
154
144
  continue
155
145
  if result[-1] == "...":
anemoi/utils/text.py CHANGED
@@ -13,10 +13,7 @@
13
13
  import re
14
14
  from collections import defaultdict
15
15
  from typing import Any
16
- from typing import List
17
16
  from typing import Optional
18
- from typing import Tuple
19
- from typing import Union
20
17
 
21
18
  # https://en.wikipedia.org/wiki/Box-drawing_character
22
19
 
@@ -61,7 +58,7 @@ def _has_ansi_escape(s: str) -> bool:
61
58
  return _ansi_escape.search(s) is not None
62
59
 
63
60
 
64
- def _split_tokens(s: str) -> List[Tuple[str, int]]:
61
+ def _split_tokens(s: str) -> list[tuple[str, int]]:
65
62
  """Split a string into a list of visual characters with their lengths.
66
63
 
67
64
  Parameters
@@ -104,7 +101,7 @@ def _split_tokens(s: str) -> List[Tuple[str, int]]:
104
101
  return out
105
102
 
106
103
 
107
- def visual_len(s: Union[str, List[Tuple[str, int]]]) -> int:
104
+ def visual_len(s: str | list[tuple[str, int]]) -> int:
108
105
  """Compute the length of a string as it appears on the terminal.
109
106
 
110
107
  Parameters
@@ -308,7 +305,7 @@ class Tree:
308
305
  return len(self._kids) == 0
309
306
 
310
307
  @property
311
- def key(self) -> Tuple:
308
+ def key(self) -> tuple:
312
309
  """Tuple: The key of the tree node."""
313
310
  return tuple(sorted(self._actor.as_dict().items()))
314
311
 
@@ -363,7 +360,7 @@ class Tree:
363
360
 
364
361
  self._print(padding)
365
362
 
366
- def _leaves(self, result: List["Tree"]) -> None:
363
+ def _leaves(self, result: list["Tree"]) -> None:
367
364
  """Collect all leaf nodes.
368
365
 
369
366
  Parameters
@@ -432,7 +429,7 @@ class Tree:
432
429
 
433
430
  return result
434
431
 
435
- def _print(self, padding: List[str]) -> None:
432
+ def _print(self, padding: list[str]) -> None:
436
433
  """Print the tree with padding.
437
434
 
438
435
  Parameters
@@ -480,7 +477,7 @@ class Tree:
480
477
  }
481
478
 
482
479
 
483
- def table(rows: List[List[Any]], header: List[str], align: List[str], margin: int = 0) -> str:
480
+ def table(rows: list[list[Any]], header: list[str], align: list[str], margin: int = 0) -> str:
484
481
  """Format a table.
485
482
 
486
483
  >>> table([['Aa', 12, 5],
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: anemoi-utils
3
- Version: 0.4.28
3
+ Version: 0.4.30
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
@@ -215,14 +215,13 @@ Classifier: Intended Audience :: Developers
215
215
  Classifier: License :: OSI Approved :: Apache Software License
216
216
  Classifier: Operating System :: OS Independent
217
217
  Classifier: Programming Language :: Python :: 3 :: Only
218
- Classifier: Programming Language :: Python :: 3.9
219
218
  Classifier: Programming Language :: Python :: 3.10
220
219
  Classifier: Programming Language :: Python :: 3.11
221
220
  Classifier: Programming Language :: Python :: 3.12
222
221
  Classifier: Programming Language :: Python :: 3.13
223
222
  Classifier: Programming Language :: Python :: Implementation :: CPython
224
223
  Classifier: Programming Language :: Python :: Implementation :: PyPy
225
- Requires-Python: >=3.9
224
+ Requires-Python: >=3.10
226
225
  License-File: LICENSE
227
226
  Requires-Dist: aniso8601
228
227
  Requires-Dist: deprecation
@@ -251,7 +250,7 @@ Requires-Dist: termcolor; extra == "docs"
251
250
  Provides-Extra: grib
252
251
  Requires-Dist: requests; extra == "grib"
253
252
  Provides-Extra: mlflow
254
- Requires-Dist: mlflow>=2.11.1; extra == "mlflow"
253
+ Requires-Dist: mlflow-skinny>=2.11.1; extra == "mlflow"
255
254
  Requires-Dist: requests; extra == "mlflow"
256
255
  Provides-Extra: provenance
257
256
  Requires-Dist: gitpython; extra == "provenance"
@@ -259,6 +258,7 @@ Requires-Dist: nvsmi; extra == "provenance"
259
258
  Provides-Extra: s3
260
259
  Requires-Dist: boto3>1.36; extra == "s3"
261
260
  Provides-Extra: tests
261
+ Requires-Dist: anemoi-utils[mlflow]; extra == "tests"
262
262
  Requires-Dist: pytest; extra == "tests"
263
263
  Requires-Dist: pytest-mock>=3; extra == "tests"
264
264
  Provides-Extra: text
@@ -0,0 +1,47 @@
1
+ anemoi/utils/__init__.py,sha256=uVhpF-VjIl_4mMywOVtgTutgsdIsqz-xdkwxeMhzuag,730
2
+ anemoi/utils/__main__.py,sha256=6LlE4MYrPvqqrykxXh7XMi50UZteUY59NeM8P9Zs2dU,910
3
+ anemoi/utils/_version.py,sha256=48EOYakuSM69Aw_44I37F3bLAF_L6h50Dt8aIet8_CE,513
4
+ anemoi/utils/caching.py,sha256=wKkpsACniNCFK1nc5Tw18EAv9FJGYdhs5p8qsr8i_FI,6153
5
+ anemoi/utils/checkpoints.py,sha256=U197rvPUD1_XBA-VphgA0staFkgx2TzDoBdbnch-I7Y,9550
6
+ anemoi/utils/cli.py,sha256=p4sup42X7JW47AKM3IQn4_0-KUAlc5ceBMj8FYmSdlc,6500
7
+ anemoi/utils/compatibility.py,sha256=Yx4Yj3xL5q0PxYccM3N5qGeQxTtEPfaCz4EqjrS7CUc,2175
8
+ anemoi/utils/config.py,sha256=dK-0KeE6WyiTprtSO54tYgQSr0lIf4iVZmGcMF04eZs,17983
9
+ anemoi/utils/dates.py,sha256=35KyiyFW8SeWLIm7VeMKBJvNvl2nVu-edRWLX-04uT4,17307
10
+ anemoi/utils/devtools.py,sha256=W3OBu96MkXRIl7Qh1SE5Zd6aB1R0QlnmlrlpBYM0fVY,3527
11
+ anemoi/utils/grib.py,sha256=eHz3BVoSB4O-3RARxXFcKRSWtYVbt6lqoLBcssHOp70,3543
12
+ anemoi/utils/grids.py,sha256=l09Hkvq8pZoh5XE8Cy29584-b1GouQSh_WqZks8uuEs,5963
13
+ anemoi/utils/hindcasts.py,sha256=WhYXqA6kw-vY9RUoQtsJZy0-Bb7mpPnHbGdfu0XmLWM,2104
14
+ anemoi/utils/humanize.py,sha256=OM2LIXYl9I-voBCKoENWxW6JY-9NlUOo183n8dzcICs,24892
15
+ anemoi/utils/logs.py,sha256=naTgrmPwWHD4eekFttXftS4gtcAGYHpCqG4iwYprNDA,1804
16
+ anemoi/utils/provenance.py,sha256=eKGXS0Ddd4G4vokAIr5m7d-fytno8omgFJdmxg8hAFk,14552
17
+ anemoi/utils/registry.py,sha256=DmBr9mMhe1ltRPsbnmhQ1TluMZshYEF3frBbVpFAQiI,9621
18
+ anemoi/utils/rules.py,sha256=YtJcwkyBJwPjHlM4ZM6icGJXLCRZmcuHCXc-SSR8wgw,6856
19
+ anemoi/utils/s3.py,sha256=bBVlfg3R4sJYOfgrSkhX7MxSVUQEur4LjE86ug8vkNw,4052
20
+ anemoi/utils/sanitise.py,sha256=XkQzibDbu-VFJkJC4WcB9ovkcTkVAynXtkn1Tlc2CC4,4019
21
+ anemoi/utils/sanitize.py,sha256=43ZKDcfVpeXSsJ9TFEc9aZnD6oe2cUh151XnDspM98M,462
22
+ anemoi/utils/testing.py,sha256=DeTAkmg-RCMPXBBRUy_Gti5UJriUPRKT6ruE3JL2GVc,10372
23
+ anemoi/utils/text.py,sha256=9M7VepzZLL-jGfFGXDqNxjwpNl7tiU8arkkOqhT9iSE,14361
24
+ anemoi/utils/timer.py,sha256=_leKMYza2faM7JKlGE7LCNy13rbdPnwaCF7PSrI_NmI,3895
25
+ anemoi/utils/commands/__init__.py,sha256=5u_6EwdqYczIAgJfCwRSyQAYFEqh2ZuHHT57g9g7sdI,808
26
+ anemoi/utils/commands/config.py,sha256=nYvYbjcum9uumRa3gzPfmQCjNZKURXMA2XOUwz9b7ls,1369
27
+ anemoi/utils/commands/metadata.py,sha256=wxHm0Hm4ss7QEtlqbXUOwQ5F_P9-uQ6iNaoDxPjSxII,11949
28
+ anemoi/utils/commands/requests.py,sha256=AEbssF1OlpbmSwrV5Lj6amCCn0w_-nbajBWTwYV15vA,2059
29
+ anemoi/utils/commands/transfer.py,sha256=29o1RQ46dCJ6kTD1sbxp8XFgB-Qx3RceMccypBMRxeQ,2627
30
+ anemoi/utils/mars/__init__.py,sha256=7T9fHpVcTZss14zdFSIzm8wzX-thrAnbWcHaEqLaMTY,2638
31
+ anemoi/utils/mars/mars.yaml,sha256=R0dujp75lLA4wCWhPeOQnzJ45WZAYLT8gpx509cBFlc,66
32
+ anemoi/utils/mars/requests.py,sha256=dxJy6su9xVLWRhTFeFmdhHROQRG4PiTTVFKUuEN6O9M,1118
33
+ anemoi/utils/mlflow/__init__.py,sha256=hCW0QcLHJmE-C1r38P27_ZOvCLNewex5iQEtZqx2ckI,393
34
+ anemoi/utils/mlflow/auth.py,sha256=Zgn2Ru7GE99_ZTBeskl5M1WnrlEGNU9XxsRVgVoUwmM,8376
35
+ anemoi/utils/mlflow/client.py,sha256=Y34ceLcp1-H0XTt8h8-IhHKX9bApc_QJcgVrzZKtabY,2752
36
+ anemoi/utils/mlflow/utils.py,sha256=0d-dp7YmDLJ59ikJWUcZooqBIdrNDxPShDQubcX-a3k,1310
37
+ anemoi/utils/remote/__init__.py,sha256=24t7cqhdxTLUbmYUgEFmY1rnbAeS_5ST3W6Z9ifimvg,20973
38
+ anemoi/utils/remote/s3.py,sha256=BWI4bUmZHBvvqU6idewyg4ApxTlhCtX3cpwjeheCSo4,21388
39
+ anemoi/utils/remote/ssh.py,sha256=xNtsawh8okytCKRehkRCVExbHZj-CRUQNormEHglfuw,8088
40
+ anemoi/utils/schemas/__init__.py,sha256=nkinKlsPLPXEjfTYQT1mpKC4cvs-14w_zBkDRxakwxw,698
41
+ anemoi/utils/schemas/errors.py,sha256=lgOXzVTYzAE0qWQf3OZ42vCWixv8lilSqLLhzARBmvI,1831
42
+ anemoi_utils-0.4.30.dist-info/licenses/LICENSE,sha256=8HznKF1Vi2IvfLsKNE5A2iVyiri3pRjRPvPC9kxs6qk,11354
43
+ anemoi_utils-0.4.30.dist-info/METADATA,sha256=TRjHcsvEyIrMtKjaCo-pWrPVomcneIy0yexXXKzsj70,15668
44
+ anemoi_utils-0.4.30.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
45
+ anemoi_utils-0.4.30.dist-info/entry_points.txt,sha256=LENOkn88xzFQo-V59AKoA_F_cfYQTJYtrNTtf37YgHY,60
46
+ anemoi_utils-0.4.30.dist-info/top_level.txt,sha256=DYn8VPs-fNwr7fNH9XIBqeXIwiYYd2E2k5-dUFFqUz0,7
47
+ anemoi_utils-0.4.30.dist-info/RECORD,,
@@ -1,47 +0,0 @@
1
- anemoi/utils/__init__.py,sha256=uVhpF-VjIl_4mMywOVtgTutgsdIsqz-xdkwxeMhzuag,730
2
- anemoi/utils/__main__.py,sha256=6LlE4MYrPvqqrykxXh7XMi50UZteUY59NeM8P9Zs2dU,910
3
- anemoi/utils/_version.py,sha256=B7w9p3e_jRrhCAcRVz7MulIQ9D0PoLvF57YvgUIilfM,513
4
- anemoi/utils/caching.py,sha256=rXbeAmpBcMbbfN4EVblaHWKicsrtx1otER84FEBtz98,6183
5
- anemoi/utils/checkpoints.py,sha256=PydBqA-wI8_05zU-3yT-ZP53GnvuqB7vPXl-w6-9XX8,9541
6
- anemoi/utils/cli.py,sha256=Cd3ESQkNWecbGnJjkR_SKHdFPETJWFrHqg5ovtANDKs,6522
7
- anemoi/utils/compatibility.py,sha256=wRBRMmxQP88rNcWiP5gqXliwYQbBv1iCAsDjcCRi5UY,2234
8
- anemoi/utils/config.py,sha256=EEfcSxW2CD6fFOzDtqz_uYlMKuYq4X5QinJW_8GBYj4,17325
9
- anemoi/utils/dates.py,sha256=CnY6JOdpk0T-waPEowMRTkcMzxcN0GcjPVtLkwH_byw,17196
10
- anemoi/utils/devtools.py,sha256=W3OBu96MkXRIl7Qh1SE5Zd6aB1R0QlnmlrlpBYM0fVY,3527
11
- anemoi/utils/grib.py,sha256=201WcxjjAl92Y2HX2kZ2S8Qr5dN-oG7nV-vQLaybzP4,3610
12
- anemoi/utils/grids.py,sha256=VlhuN8MZDBu-G50QFI1XHV9IXLway2LpvI9X8sDjb5s,6047
13
- anemoi/utils/hindcasts.py,sha256=iYVIxSNFL2HJcc_k1abCFLkpJFGHT8WKRIR4wcAwA3s,2144
14
- anemoi/utils/humanize.py,sha256=pjnFJAKHbEAOfcvn8c48kt-8eFy6FGW_U2ruJvfamrA,25189
15
- anemoi/utils/logs.py,sha256=naTgrmPwWHD4eekFttXftS4gtcAGYHpCqG4iwYprNDA,1804
16
- anemoi/utils/provenance.py,sha256=iTsn4r-VPq2D8tSHPSuAIqG077_opkqMT42G03DRWJg,14690
17
- anemoi/utils/registry.py,sha256=e3nOIRyMYQ-mpEvaHAv5tuvMYNbkJ5yz94ns7BnvkjM,9717
18
- anemoi/utils/rules.py,sha256=VspUoPmw7tijrs6l_wl4vDjr_zVQsFjx9ITiBSvxgc8,6972
19
- anemoi/utils/s3.py,sha256=xMT48kbcelcjjqsaU567WI3oZ5eqo88Rlgyx5ECszAU,4074
20
- anemoi/utils/sanitise.py,sha256=ZYGdSX6qihQANr3pHZjbKnoapnzP1KcrWdW1Ul1mOGk,3668
21
- anemoi/utils/sanitize.py,sha256=43ZKDcfVpeXSsJ9TFEc9aZnD6oe2cUh151XnDspM98M,462
22
- anemoi/utils/testing.py,sha256=DeTAkmg-RCMPXBBRUy_Gti5UJriUPRKT6ruE3JL2GVc,10372
23
- anemoi/utils/text.py,sha256=HkzIvi24obDceFLpJEwBJ9PmPrJUkQN2TrElJ-A87gU,14441
24
- anemoi/utils/timer.py,sha256=_leKMYza2faM7JKlGE7LCNy13rbdPnwaCF7PSrI_NmI,3895
25
- anemoi/utils/commands/__init__.py,sha256=5u_6EwdqYczIAgJfCwRSyQAYFEqh2ZuHHT57g9g7sdI,808
26
- anemoi/utils/commands/config.py,sha256=nYvYbjcum9uumRa3gzPfmQCjNZKURXMA2XOUwz9b7ls,1369
27
- anemoi/utils/commands/metadata.py,sha256=_j1ohUy9tty9KhD0N2zqc7vaOJ3pJFRZUGMGRE0z7Mw,11973
28
- anemoi/utils/commands/requests.py,sha256=AEbssF1OlpbmSwrV5Lj6amCCn0w_-nbajBWTwYV15vA,2059
29
- anemoi/utils/commands/transfer.py,sha256=29o1RQ46dCJ6kTD1sbxp8XFgB-Qx3RceMccypBMRxeQ,2627
30
- anemoi/utils/mars/__init__.py,sha256=b-Lc3L1TAQd9ODs0Z1YSJzgZCO1K_M3DSgx_yd2qXvM,2724
31
- anemoi/utils/mars/mars.yaml,sha256=R0dujp75lLA4wCWhPeOQnzJ45WZAYLT8gpx509cBFlc,66
32
- anemoi/utils/mars/requests.py,sha256=VFMHBVAAl0_2lOcMBa1lvaKHctN0lDJsI6_U4BucGew,1142
33
- anemoi/utils/mlflow/__init__.py,sha256=hCW0QcLHJmE-C1r38P27_ZOvCLNewex5iQEtZqx2ckI,393
34
- anemoi/utils/mlflow/auth.py,sha256=hMuS3vrX4VDfEFiIlRM_7U6XHvYRGU149doi4jlgsW8,8092
35
- anemoi/utils/mlflow/client.py,sha256=Y34ceLcp1-H0XTt8h8-IhHKX9bApc_QJcgVrzZKtabY,2752
36
- anemoi/utils/mlflow/utils.py,sha256=2zwNqkS69TXKz-vUy8cdGckJA7jjtjbUZ6P7cj9U8OM,4940
37
- anemoi/utils/remote/__init__.py,sha256=7nHu-LRspYW2Fx9GNLjsxpytAUIvhIbOjb0Xmxb-33s,20988
38
- anemoi/utils/remote/s3.py,sha256=DxO_TjmetX_r3ZvGaHjpz40oqvcQYP3Vd_A4ojMGlSA,21379
39
- anemoi/utils/remote/ssh.py,sha256=xNtsawh8okytCKRehkRCVExbHZj-CRUQNormEHglfuw,8088
40
- anemoi/utils/schemas/__init__.py,sha256=nkinKlsPLPXEjfTYQT1mpKC4cvs-14w_zBkDRxakwxw,698
41
- anemoi/utils/schemas/errors.py,sha256=lgOXzVTYzAE0qWQf3OZ42vCWixv8lilSqLLhzARBmvI,1831
42
- anemoi_utils-0.4.28.dist-info/licenses/LICENSE,sha256=8HznKF1Vi2IvfLsKNE5A2iVyiri3pRjRPvPC9kxs6qk,11354
43
- anemoi_utils-0.4.28.dist-info/METADATA,sha256=CxRjsdH4Audnqnun7v-FSgCNxxSVFtwIuSQqgnoIHUk,15656
44
- anemoi_utils-0.4.28.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
45
- anemoi_utils-0.4.28.dist-info/entry_points.txt,sha256=LENOkn88xzFQo-V59AKoA_F_cfYQTJYtrNTtf37YgHY,60
46
- anemoi_utils-0.4.28.dist-info/top_level.txt,sha256=DYn8VPs-fNwr7fNH9XIBqeXIwiYYd2E2k5-dUFFqUz0,7
47
- anemoi_utils-0.4.28.dist-info/RECORD,,