anemoi-utils 0.4.28__py3-none-any.whl → 0.4.29__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.
- anemoi/utils/_version.py +2 -2
- anemoi/utils/dates.py +11 -0
- anemoi/utils/mlflow/auth.py +9 -0
- anemoi/utils/mlflow/utils.py +0 -115
- anemoi/utils/sanitise.py +35 -45
- {anemoi_utils-0.4.28.dist-info → anemoi_utils-0.4.29.dist-info}/METADATA +3 -2
- {anemoi_utils-0.4.28.dist-info → anemoi_utils-0.4.29.dist-info}/RECORD +11 -11
- {anemoi_utils-0.4.28.dist-info → anemoi_utils-0.4.29.dist-info}/WHEEL +0 -0
- {anemoi_utils-0.4.28.dist-info → anemoi_utils-0.4.29.dist-info}/entry_points.txt +0 -0
- {anemoi_utils-0.4.28.dist-info → anemoi_utils-0.4.29.dist-info}/licenses/LICENSE +0 -0
- {anemoi_utils-0.4.28.dist-info → anemoi_utils-0.4.29.dist-info}/top_level.txt +0 -0
anemoi/utils/_version.py
CHANGED
anemoi/utils/dates.py
CHANGED
|
@@ -199,6 +199,15 @@ def as_timedelta(frequency: Union[int, str, datetime.timedelta]) -> datetime.tim
|
|
|
199
199
|
except ValueError:
|
|
200
200
|
pass
|
|
201
201
|
|
|
202
|
+
if frequency.startswith(" ") or frequency.startswith(" "):
|
|
203
|
+
frequency = frequency.strip()
|
|
204
|
+
|
|
205
|
+
if frequency.startswith("-"):
|
|
206
|
+
return -as_timedelta(frequency[1:])
|
|
207
|
+
|
|
208
|
+
if frequency.startswith("+"):
|
|
209
|
+
return as_timedelta(frequency[1:])
|
|
210
|
+
|
|
202
211
|
if re.match(r"^\d+[hdms]$", frequency, re.IGNORECASE):
|
|
203
212
|
unit = frequency[-1].lower()
|
|
204
213
|
v = int(frequency[:-1])
|
|
@@ -261,6 +270,8 @@ def frequency_to_string(frequency: datetime.timedelta) -> str:
|
|
|
261
270
|
frequency = frequency_to_timedelta(frequency)
|
|
262
271
|
|
|
263
272
|
total_seconds = frequency.total_seconds()
|
|
273
|
+
if total_seconds < 0:
|
|
274
|
+
return f"-{frequency_to_string(-frequency)}"
|
|
264
275
|
assert int(total_seconds) == total_seconds, total_seconds
|
|
265
276
|
total_seconds = int(total_seconds)
|
|
266
277
|
|
anemoi/utils/mlflow/auth.py
CHANGED
|
@@ -22,6 +22,7 @@ from typing import TYPE_CHECKING
|
|
|
22
22
|
import requests
|
|
23
23
|
from requests.exceptions import HTTPError
|
|
24
24
|
|
|
25
|
+
from ..config import config_path
|
|
25
26
|
from ..config import load_config
|
|
26
27
|
from ..config import save_config
|
|
27
28
|
from ..remote import robust
|
|
@@ -87,6 +88,14 @@ class TokenAuth:
|
|
|
87
88
|
|
|
88
89
|
@staticmethod
|
|
89
90
|
def load_config() -> dict:
|
|
91
|
+
path = config_path(TokenAuth.config_file)
|
|
92
|
+
|
|
93
|
+
if not os.path.exists(path):
|
|
94
|
+
save_config(TokenAuth.config_file, {})
|
|
95
|
+
|
|
96
|
+
if os.path.exists(path) and os.stat(path).st_mode & 0o777 != 0o600:
|
|
97
|
+
os.chmod(path, 0o600)
|
|
98
|
+
|
|
90
99
|
return load_config(TokenAuth.config_file)
|
|
91
100
|
|
|
92
101
|
def enabled(fn: Callable) -> Callable: # noqa: N805
|
anemoi/utils/mlflow/utils.py
CHANGED
|
@@ -8,9 +8,7 @@
|
|
|
8
8
|
# nor does it submit to any jurisdiction.
|
|
9
9
|
from __future__ import annotations
|
|
10
10
|
|
|
11
|
-
import functools
|
|
12
11
|
import os
|
|
13
|
-
from typing import Any
|
|
14
12
|
|
|
15
13
|
import requests
|
|
16
14
|
|
|
@@ -44,116 +42,3 @@ def health_check(tracking_uri: str) -> None:
|
|
|
44
42
|
if not token:
|
|
45
43
|
error_msg += "The server may require authentication, did you forget to turn it on?"
|
|
46
44
|
raise ConnectionError(error_msg)
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
def expand_iterables(
|
|
50
|
-
params: dict[str, Any],
|
|
51
|
-
*,
|
|
52
|
-
size_threshold: int | None = None,
|
|
53
|
-
recursive: bool = True,
|
|
54
|
-
delimiter: str = ".",
|
|
55
|
-
) -> dict[str, Any]:
|
|
56
|
-
"""Expand any iterable values to the form {key.i: value_i}.
|
|
57
|
-
|
|
58
|
-
If expanded will also add {key.all: [value_0, value_1, ...], key.length: len([value_0, value_1, ...])}.
|
|
59
|
-
|
|
60
|
-
If `size_threshold` is not None, expand the iterable only if the length of str(value) is
|
|
61
|
-
greater than `size_threshold`.
|
|
62
|
-
|
|
63
|
-
Parameters
|
|
64
|
-
----------
|
|
65
|
-
params : dict[str, Any]
|
|
66
|
-
Parameters to be expanded.
|
|
67
|
-
size_threshold : int | None, optional
|
|
68
|
-
Threshold of str(value) to expand iterable at.
|
|
69
|
-
Default is None.
|
|
70
|
-
recursive : bool, optional
|
|
71
|
-
Expand nested dictionaries.
|
|
72
|
-
Default is True.
|
|
73
|
-
delimiter: str, optional
|
|
74
|
-
Delimiter to use for keys.
|
|
75
|
-
Default is ".".
|
|
76
|
-
|
|
77
|
-
Returns
|
|
78
|
-
-------
|
|
79
|
-
dict[str, Any]
|
|
80
|
-
Dictionary with all iterable values expanded.
|
|
81
|
-
|
|
82
|
-
Examples
|
|
83
|
-
--------
|
|
84
|
-
>>> expand_iterables({'a': ['a', 'b', 'c']})
|
|
85
|
-
{'a.0': 'a', 'a.1': 'b', 'a.2': 'c', 'a.all': ['a', 'b', 'c'], 'a.length': 3}
|
|
86
|
-
>>> expand_iterables({'a': {'b': ['a', 'b', 'c']}})
|
|
87
|
-
{'a': {'b.0': 'a', 'b.1': 'b', 'b.2': 'c', 'b.all': ['a', 'b', 'c'], 'b.length': 3}}
|
|
88
|
-
>>> expand_iterables({'a': ['a', 'b', 'c']}, size_threshold=100)
|
|
89
|
-
{'a': ['a', 'b', 'c']}
|
|
90
|
-
>>> expand_iterables({'a': [[0,1,2], 'b', 'c']})
|
|
91
|
-
{'a.0': {0: 0, 1: 1, 2: 2}, 'a.1': 'b', 'a.2': 'c', 'a.all': [[0, 1, 2], 'b', 'c'], 'a.length': 3}
|
|
92
|
-
"""
|
|
93
|
-
|
|
94
|
-
def should_be_expanded(x: Any) -> bool:
|
|
95
|
-
return size_threshold is None or len(str(x)) > size_threshold
|
|
96
|
-
|
|
97
|
-
nested_func = functools.partial(expand_iterables, size_threshold=size_threshold, recursive=recursive)
|
|
98
|
-
|
|
99
|
-
def expand(val: dict | list) -> dict[str, Any]:
|
|
100
|
-
if not recursive:
|
|
101
|
-
return val
|
|
102
|
-
if isinstance(val, dict):
|
|
103
|
-
return nested_func(val)
|
|
104
|
-
if isinstance(val, list):
|
|
105
|
-
return nested_func(dict(enumerate(val)))
|
|
106
|
-
return val
|
|
107
|
-
|
|
108
|
-
expanded_params = {}
|
|
109
|
-
|
|
110
|
-
for key, value in params.items():
|
|
111
|
-
if isinstance(value, (list, tuple)):
|
|
112
|
-
if should_be_expanded(value):
|
|
113
|
-
for i, v in enumerate(value):
|
|
114
|
-
expanded_params[f"{key}{delimiter}{i}"] = expand(v)
|
|
115
|
-
|
|
116
|
-
expanded_params[f"{key}{delimiter}all"] = value
|
|
117
|
-
expanded_params[f"{key}{delimiter}length"] = len(value)
|
|
118
|
-
else:
|
|
119
|
-
expanded_params[key] = value
|
|
120
|
-
else:
|
|
121
|
-
expanded_params[key] = expand(value)
|
|
122
|
-
return expanded_params
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
def clean_config_params(params: dict[str, Any]) -> dict[str, Any]:
|
|
126
|
-
"""Clean up params to avoid issues with mlflow.
|
|
127
|
-
|
|
128
|
-
Too many logged params will make the server take longer to render the
|
|
129
|
-
experiment.
|
|
130
|
-
|
|
131
|
-
Parameters
|
|
132
|
-
----------
|
|
133
|
-
params : dict[str, Any]
|
|
134
|
-
Parameters to clean up.
|
|
135
|
-
|
|
136
|
-
Returns
|
|
137
|
-
-------
|
|
138
|
-
dict[str, Any]
|
|
139
|
-
Cleaned up params ready for MlFlow.
|
|
140
|
-
"""
|
|
141
|
-
prefixes_to_remove = [
|
|
142
|
-
"hardware",
|
|
143
|
-
"data",
|
|
144
|
-
"dataloader",
|
|
145
|
-
"model",
|
|
146
|
-
"training",
|
|
147
|
-
"diagnostics",
|
|
148
|
-
"graph",
|
|
149
|
-
"metadata.config",
|
|
150
|
-
"config.dataset.sourcesmetadata.dataset.variables_metadata",
|
|
151
|
-
"metadata.dataset.sources",
|
|
152
|
-
"metadata.dataset.specific",
|
|
153
|
-
"metadata.dataset.variables_metadata",
|
|
154
|
-
]
|
|
155
|
-
|
|
156
|
-
keys_to_remove = [key for key in params if any(key.startswith(prefix) for prefix in prefixes_to_remove)]
|
|
157
|
-
for key in keys_to_remove:
|
|
158
|
-
del params[key]
|
|
159
|
-
return params
|
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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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] == "...":
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: anemoi-utils
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.29
|
|
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
|
|
@@ -251,7 +251,7 @@ Requires-Dist: termcolor; extra == "docs"
|
|
|
251
251
|
Provides-Extra: grib
|
|
252
252
|
Requires-Dist: requests; extra == "grib"
|
|
253
253
|
Provides-Extra: mlflow
|
|
254
|
-
Requires-Dist: mlflow>=2.11.1; extra == "mlflow"
|
|
254
|
+
Requires-Dist: mlflow-skinny>=2.11.1; extra == "mlflow"
|
|
255
255
|
Requires-Dist: requests; extra == "mlflow"
|
|
256
256
|
Provides-Extra: provenance
|
|
257
257
|
Requires-Dist: gitpython; extra == "provenance"
|
|
@@ -259,6 +259,7 @@ Requires-Dist: nvsmi; extra == "provenance"
|
|
|
259
259
|
Provides-Extra: s3
|
|
260
260
|
Requires-Dist: boto3>1.36; extra == "s3"
|
|
261
261
|
Provides-Extra: tests
|
|
262
|
+
Requires-Dist: anemoi-utils[mlflow]; extra == "tests"
|
|
262
263
|
Requires-Dist: pytest; extra == "tests"
|
|
263
264
|
Requires-Dist: pytest-mock>=3; extra == "tests"
|
|
264
265
|
Provides-Extra: text
|
|
@@ -1,12 +1,12 @@
|
|
|
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=
|
|
3
|
+
anemoi/utils/_version.py,sha256=M33mpOYpqw35qLoEcg5GxMG4YQ25eohx8wEQkM6FTT0,513
|
|
4
4
|
anemoi/utils/caching.py,sha256=rXbeAmpBcMbbfN4EVblaHWKicsrtx1otER84FEBtz98,6183
|
|
5
5
|
anemoi/utils/checkpoints.py,sha256=PydBqA-wI8_05zU-3yT-ZP53GnvuqB7vPXl-w6-9XX8,9541
|
|
6
6
|
anemoi/utils/cli.py,sha256=Cd3ESQkNWecbGnJjkR_SKHdFPETJWFrHqg5ovtANDKs,6522
|
|
7
7
|
anemoi/utils/compatibility.py,sha256=wRBRMmxQP88rNcWiP5gqXliwYQbBv1iCAsDjcCRi5UY,2234
|
|
8
8
|
anemoi/utils/config.py,sha256=EEfcSxW2CD6fFOzDtqz_uYlMKuYq4X5QinJW_8GBYj4,17325
|
|
9
|
-
anemoi/utils/dates.py,sha256=
|
|
9
|
+
anemoi/utils/dates.py,sha256=Ew11G-Upl0VM9R9Sgg3Be6KIkXfpMCD69kgiao7Xv48,17534
|
|
10
10
|
anemoi/utils/devtools.py,sha256=W3OBu96MkXRIl7Qh1SE5Zd6aB1R0QlnmlrlpBYM0fVY,3527
|
|
11
11
|
anemoi/utils/grib.py,sha256=201WcxjjAl92Y2HX2kZ2S8Qr5dN-oG7nV-vQLaybzP4,3610
|
|
12
12
|
anemoi/utils/grids.py,sha256=VlhuN8MZDBu-G50QFI1XHV9IXLway2LpvI9X8sDjb5s,6047
|
|
@@ -17,7 +17,7 @@ anemoi/utils/provenance.py,sha256=iTsn4r-VPq2D8tSHPSuAIqG077_opkqMT42G03DRWJg,14
|
|
|
17
17
|
anemoi/utils/registry.py,sha256=e3nOIRyMYQ-mpEvaHAv5tuvMYNbkJ5yz94ns7BnvkjM,9717
|
|
18
18
|
anemoi/utils/rules.py,sha256=VspUoPmw7tijrs6l_wl4vDjr_zVQsFjx9ITiBSvxgc8,6972
|
|
19
19
|
anemoi/utils/s3.py,sha256=xMT48kbcelcjjqsaU567WI3oZ5eqo88Rlgyx5ECszAU,4074
|
|
20
|
-
anemoi/utils/sanitise.py,sha256=
|
|
20
|
+
anemoi/utils/sanitise.py,sha256=XkQzibDbu-VFJkJC4WcB9ovkcTkVAynXtkn1Tlc2CC4,4019
|
|
21
21
|
anemoi/utils/sanitize.py,sha256=43ZKDcfVpeXSsJ9TFEc9aZnD6oe2cUh151XnDspM98M,462
|
|
22
22
|
anemoi/utils/testing.py,sha256=DeTAkmg-RCMPXBBRUy_Gti5UJriUPRKT6ruE3JL2GVc,10372
|
|
23
23
|
anemoi/utils/text.py,sha256=HkzIvi24obDceFLpJEwBJ9PmPrJUkQN2TrElJ-A87gU,14441
|
|
@@ -31,17 +31,17 @@ anemoi/utils/mars/__init__.py,sha256=b-Lc3L1TAQd9ODs0Z1YSJzgZCO1K_M3DSgx_yd2qXvM
|
|
|
31
31
|
anemoi/utils/mars/mars.yaml,sha256=R0dujp75lLA4wCWhPeOQnzJ45WZAYLT8gpx509cBFlc,66
|
|
32
32
|
anemoi/utils/mars/requests.py,sha256=VFMHBVAAl0_2lOcMBa1lvaKHctN0lDJsI6_U4BucGew,1142
|
|
33
33
|
anemoi/utils/mlflow/__init__.py,sha256=hCW0QcLHJmE-C1r38P27_ZOvCLNewex5iQEtZqx2ckI,393
|
|
34
|
-
anemoi/utils/mlflow/auth.py,sha256=
|
|
34
|
+
anemoi/utils/mlflow/auth.py,sha256=Zgn2Ru7GE99_ZTBeskl5M1WnrlEGNU9XxsRVgVoUwmM,8376
|
|
35
35
|
anemoi/utils/mlflow/client.py,sha256=Y34ceLcp1-H0XTt8h8-IhHKX9bApc_QJcgVrzZKtabY,2752
|
|
36
|
-
anemoi/utils/mlflow/utils.py,sha256=
|
|
36
|
+
anemoi/utils/mlflow/utils.py,sha256=0d-dp7YmDLJ59ikJWUcZooqBIdrNDxPShDQubcX-a3k,1310
|
|
37
37
|
anemoi/utils/remote/__init__.py,sha256=7nHu-LRspYW2Fx9GNLjsxpytAUIvhIbOjb0Xmxb-33s,20988
|
|
38
38
|
anemoi/utils/remote/s3.py,sha256=DxO_TjmetX_r3ZvGaHjpz40oqvcQYP3Vd_A4ojMGlSA,21379
|
|
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.
|
|
43
|
-
anemoi_utils-0.4.
|
|
44
|
-
anemoi_utils-0.4.
|
|
45
|
-
anemoi_utils-0.4.
|
|
46
|
-
anemoi_utils-0.4.
|
|
47
|
-
anemoi_utils-0.4.
|
|
42
|
+
anemoi_utils-0.4.29.dist-info/licenses/LICENSE,sha256=8HznKF1Vi2IvfLsKNE5A2iVyiri3pRjRPvPC9kxs6qk,11354
|
|
43
|
+
anemoi_utils-0.4.29.dist-info/METADATA,sha256=v5sHgt4rZA9mZ2YW1pMO0S76mlvZ09hoB3Q-G7xp6-Y,15717
|
|
44
|
+
anemoi_utils-0.4.29.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
45
|
+
anemoi_utils-0.4.29.dist-info/entry_points.txt,sha256=LENOkn88xzFQo-V59AKoA_F_cfYQTJYtrNTtf37YgHY,60
|
|
46
|
+
anemoi_utils-0.4.29.dist-info/top_level.txt,sha256=DYn8VPs-fNwr7fNH9XIBqeXIwiYYd2E2k5-dUFFqUz0,7
|
|
47
|
+
anemoi_utils-0.4.29.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|