zenml-nightly 0.82.0.dev20250504__py3-none-any.whl → 0.82.0.dev20250506__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.
- zenml/VERSION +1 -1
- zenml/config/build_configuration.py +21 -0
- zenml/config/server_config.py +2 -0
- zenml/container_registries/base_container_registry.py +39 -1
- zenml/zen_server/cloud_utils.py +90 -43
- {zenml_nightly-0.82.0.dev20250504.dist-info → zenml_nightly-0.82.0.dev20250506.dist-info}/METADATA +2 -2
- {zenml_nightly-0.82.0.dev20250504.dist-info → zenml_nightly-0.82.0.dev20250506.dist-info}/RECORD +10 -10
- {zenml_nightly-0.82.0.dev20250504.dist-info → zenml_nightly-0.82.0.dev20250506.dist-info}/WHEEL +1 -1
- {zenml_nightly-0.82.0.dev20250504.dist-info → zenml_nightly-0.82.0.dev20250506.dist-info}/LICENSE +0 -0
- {zenml_nightly-0.82.0.dev20250504.dist-info → zenml_nightly-0.82.0.dev20250506.dist-info}/entry_points.txt +0 -0
zenml/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.82.0.
|
1
|
+
0.82.0.dev20250506
|
@@ -20,12 +20,15 @@ from typing import TYPE_CHECKING, Dict, Optional
|
|
20
20
|
from pydantic import BaseModel
|
21
21
|
|
22
22
|
from zenml.config.docker_settings import DockerSettings
|
23
|
+
from zenml.logger import get_logger
|
23
24
|
from zenml.utils import json_utils
|
24
25
|
|
25
26
|
if TYPE_CHECKING:
|
26
27
|
from zenml.code_repositories import BaseCodeRepository
|
27
28
|
from zenml.stack import Stack
|
28
29
|
|
30
|
+
logger = get_logger(__name__)
|
31
|
+
|
29
32
|
|
30
33
|
class BuildConfiguration(BaseModel):
|
31
34
|
"""Configuration of Docker builds.
|
@@ -99,6 +102,24 @@ class BuildConfiguration(BaseModel):
|
|
99
102
|
with open(self.settings.dockerfile, "rb") as f:
|
100
103
|
hash_.update(f.read())
|
101
104
|
|
105
|
+
if self.settings.parent_image and stack.container_registry:
|
106
|
+
digest = stack.container_registry.get_image_repo_digest(
|
107
|
+
self.settings.parent_image
|
108
|
+
)
|
109
|
+
if digest:
|
110
|
+
hash_.update(digest.encode())
|
111
|
+
else:
|
112
|
+
logger.warning(
|
113
|
+
"Unable to fetch parent image digest for image `%s`. "
|
114
|
+
"This may lead to ZenML reusing existing builds even "
|
115
|
+
"though a new version of the parent image has been "
|
116
|
+
"pushed. Most likely you can fix this error by making sure "
|
117
|
+
"the parent image is pushed to the container registry of "
|
118
|
+
"your active stack `%s`.",
|
119
|
+
self.settings.parent_image,
|
120
|
+
stack.name,
|
121
|
+
)
|
122
|
+
|
102
123
|
return hash_.hexdigest()
|
103
124
|
|
104
125
|
def should_include_files(
|
zenml/config/server_config.py
CHANGED
@@ -29,6 +29,7 @@ from pydantic import (
|
|
29
29
|
)
|
30
30
|
|
31
31
|
from zenml.constants import (
|
32
|
+
DEFAULT_HTTP_TIMEOUT,
|
32
33
|
DEFAULT_REPORTABLE_RESOURCES,
|
33
34
|
DEFAULT_ZENML_JWT_TOKEN_ALGORITHM,
|
34
35
|
DEFAULT_ZENML_JWT_TOKEN_LEEWAY,
|
@@ -679,6 +680,7 @@ class ServerProConfiguration(BaseModel):
|
|
679
680
|
organization_name: Optional[str] = None
|
680
681
|
workspace_id: UUID
|
681
682
|
workspace_name: Optional[str] = None
|
683
|
+
http_timeout: int = DEFAULT_HTTP_TIMEOUT
|
682
684
|
|
683
685
|
@field_validator("api_url", "dashboard_url")
|
684
686
|
@classmethod
|
@@ -160,6 +160,25 @@ class BaseContainerRegistry(AuthenticationMixin):
|
|
160
160
|
|
161
161
|
return self._docker_client
|
162
162
|
|
163
|
+
def is_valid_image_name_for_registry(self, image_name: str) -> bool:
|
164
|
+
"""Check if the image name is valid for the container registry.
|
165
|
+
|
166
|
+
Args:
|
167
|
+
image_name: The name of the image.
|
168
|
+
|
169
|
+
Returns:
|
170
|
+
`True` if the image name is valid for the container registry,
|
171
|
+
`False` otherwise.
|
172
|
+
"""
|
173
|
+
# Remove prefixes to make sure this logic also works for DockerHub
|
174
|
+
image_name = image_name.removeprefix("index.docker.io/")
|
175
|
+
image_name = image_name.removeprefix("docker.io/")
|
176
|
+
|
177
|
+
registry_uri = self.config.uri.removeprefix("index.docker.io/")
|
178
|
+
registry_uri = registry_uri.removeprefix("docker.io/")
|
179
|
+
|
180
|
+
return image_name.startswith(registry_uri)
|
181
|
+
|
163
182
|
def prepare_image_push(self, image_name: str) -> None:
|
164
183
|
"""Preparation before an image gets pushed.
|
165
184
|
|
@@ -183,7 +202,7 @@ class BaseContainerRegistry(AuthenticationMixin):
|
|
183
202
|
ValueError: If the image name is not associated with this
|
184
203
|
container registry.
|
185
204
|
"""
|
186
|
-
if not
|
205
|
+
if not self.is_valid_image_name_for_registry(image_name):
|
187
206
|
raise ValueError(
|
188
207
|
f"Docker image `{image_name}` does not belong to container "
|
189
208
|
f"registry `{self.config.uri}`."
|
@@ -194,6 +213,25 @@ class BaseContainerRegistry(AuthenticationMixin):
|
|
194
213
|
image_name, docker_client=self.docker_client
|
195
214
|
)
|
196
215
|
|
216
|
+
def get_image_repo_digest(self, image_name: str) -> Optional[str]:
|
217
|
+
"""Get the repository digest of an image.
|
218
|
+
|
219
|
+
Args:
|
220
|
+
image_name: The name of the image.
|
221
|
+
|
222
|
+
Returns:
|
223
|
+
The repository digest of the image.
|
224
|
+
"""
|
225
|
+
if not self.is_valid_image_name_for_registry(image_name):
|
226
|
+
return None
|
227
|
+
|
228
|
+
try:
|
229
|
+
metadata = self.docker_client.images.get_registry_data(image_name)
|
230
|
+
except Exception:
|
231
|
+
return None
|
232
|
+
|
233
|
+
return cast(str, metadata.id.split(":")[-1])
|
234
|
+
|
197
235
|
|
198
236
|
class BaseContainerRegistryFlavor(Flavor):
|
199
237
|
"""Base flavor for container registries."""
|
zenml/zen_server/cloud_utils.py
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
"""Utils concerning anything concerning the cloud control plane backend."""
|
2
2
|
|
3
3
|
from datetime import datetime, timedelta
|
4
|
+
from threading import RLock
|
4
5
|
from typing import Any, Dict, Optional
|
5
6
|
|
6
7
|
import requests
|
@@ -26,6 +27,7 @@ class ZenMLCloudConnection:
|
|
26
27
|
self._session: Optional[requests.Session] = None
|
27
28
|
self._token: Optional[str] = None
|
28
29
|
self._token_expires_at: Optional[datetime] = None
|
30
|
+
self._lock = RLock()
|
29
31
|
|
30
32
|
def request(
|
31
33
|
self,
|
@@ -55,13 +57,21 @@ class ZenMLCloudConnection:
|
|
55
57
|
url = self._config.api_url + endpoint
|
56
58
|
|
57
59
|
response = self.session.request(
|
58
|
-
method=method,
|
60
|
+
method=method,
|
61
|
+
url=url,
|
62
|
+
params=params,
|
63
|
+
json=data,
|
64
|
+
timeout=self._config.http_timeout,
|
59
65
|
)
|
60
66
|
if response.status_code == 401:
|
61
67
|
# Refresh the auth token and try again
|
62
|
-
self.
|
68
|
+
self._reset_login()
|
63
69
|
response = self.session.request(
|
64
|
-
method=method,
|
70
|
+
method=method,
|
71
|
+
url=url,
|
72
|
+
params=params,
|
73
|
+
json=data,
|
74
|
+
timeout=self._config.http_timeout,
|
65
75
|
)
|
66
76
|
|
67
77
|
try:
|
@@ -164,57 +174,90 @@ class ZenMLCloudConnection:
|
|
164
174
|
Returns:
|
165
175
|
A requests session with the authentication token.
|
166
176
|
"""
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
177
|
+
with self._lock:
|
178
|
+
if self._session is None:
|
179
|
+
# Set up the session's connection pool size to match the server's
|
180
|
+
# thread pool size. This allows the server to cache one connection
|
181
|
+
# per thread, which means we can keep connections open for longer
|
182
|
+
# and avoid the overhead of setting up a new connection for each
|
183
|
+
# request.
|
184
|
+
conn_pool_size = server_config().thread_pool_size
|
185
|
+
|
186
|
+
self._session = requests.Session()
|
187
|
+
# Add the ZenML specific headers
|
188
|
+
self._session.headers.update(get_zenml_headers())
|
189
|
+
|
190
|
+
retries = Retry(
|
191
|
+
connect=5,
|
192
|
+
read=8,
|
193
|
+
redirect=3,
|
194
|
+
status=10,
|
195
|
+
allowed_methods=[
|
196
|
+
"HEAD",
|
197
|
+
"GET",
|
198
|
+
"PUT",
|
199
|
+
"PATCH",
|
200
|
+
"POST",
|
201
|
+
"DELETE",
|
202
|
+
"OPTIONS",
|
203
|
+
],
|
204
|
+
status_forcelist=[
|
205
|
+
408, # Request Timeout
|
206
|
+
429, # Too Many Requests
|
207
|
+
502, # Bad Gateway
|
208
|
+
503, # Service Unavailable
|
209
|
+
504, # Gateway Timeout
|
210
|
+
],
|
211
|
+
other=3,
|
212
|
+
backoff_factor=0.5,
|
213
|
+
)
|
214
|
+
|
215
|
+
self._session.mount(
|
216
|
+
"https://",
|
217
|
+
HTTPAdapter(
|
218
|
+
max_retries=retries,
|
219
|
+
# We only use one connection pool to be cached because we
|
220
|
+
# only communicate with one remote server (the control
|
221
|
+
# plane)
|
222
|
+
pool_connections=1,
|
223
|
+
pool_maxsize=conn_pool_size,
|
224
|
+
),
|
225
|
+
)
|
226
|
+
|
227
|
+
# Login to the ZenML Pro Management Plane. Calling this will fetch
|
228
|
+
# the active session token. It will also refresh the token if it is
|
229
|
+
# going to expire soon or if it is already expired.
|
230
|
+
access_token = self._fetch_auth_token(session=self._session)
|
231
|
+
self._session.headers.update(
|
232
|
+
{"Authorization": "Bearer " + access_token}
|
194
233
|
)
|
195
234
|
|
196
|
-
|
235
|
+
return self._session
|
197
236
|
|
198
|
-
def
|
199
|
-
"""
|
200
|
-
self.
|
201
|
-
|
202
|
-
|
237
|
+
def _reset_login(self) -> None:
|
238
|
+
"""Force a new login to the ZenML Pro Management Plane."""
|
239
|
+
with self._lock:
|
240
|
+
self._token = None
|
241
|
+
self._token_expires_at = None
|
203
242
|
|
204
|
-
def _fetch_auth_token(self) -> str:
|
243
|
+
def _fetch_auth_token(self, session: requests.Session) -> str:
|
205
244
|
"""Fetch an auth token from the Cloud API.
|
206
245
|
|
207
|
-
|
208
|
-
|
246
|
+
Args:
|
247
|
+
session: The session to use to fetch the auth token.
|
209
248
|
|
210
249
|
Returns:
|
211
|
-
|
250
|
+
The auth token.
|
251
|
+
|
252
|
+
Raises:
|
253
|
+
RuntimeError: If the auth token can't be fetched.
|
212
254
|
"""
|
213
255
|
if (
|
214
256
|
self._token is not None
|
215
257
|
and self._token_expires_at is not None
|
216
258
|
and utc_now() + timedelta(minutes=5) < self._token_expires_at
|
217
259
|
):
|
260
|
+
# Already logged in and token is still valid
|
218
261
|
return self._token
|
219
262
|
|
220
263
|
# Get an auth token from the Cloud API
|
@@ -229,9 +272,13 @@ class ZenMLCloudConnection:
|
|
229
272
|
"audience": self._config.oauth2_audience,
|
230
273
|
"grant_type": "client_credentials",
|
231
274
|
}
|
275
|
+
|
232
276
|
try:
|
233
|
-
response =
|
234
|
-
login_url,
|
277
|
+
response = session.post(
|
278
|
+
login_url,
|
279
|
+
headers=headers,
|
280
|
+
data=payload,
|
281
|
+
timeout=self._config.http_timeout,
|
235
282
|
)
|
236
283
|
response.raise_for_status()
|
237
284
|
except Exception as e:
|
@@ -253,8 +300,8 @@ class ZenMLCloudConnection:
|
|
253
300
|
"Could not fetch auth token from the Cloud API."
|
254
301
|
)
|
255
302
|
|
256
|
-
self._token = access_token
|
257
303
|
self._token_expires_at = utc_now() + timedelta(seconds=expires_in)
|
304
|
+
self._token = access_token
|
258
305
|
|
259
306
|
assert self._token is not None
|
260
307
|
return self._token
|
{zenml_nightly-0.82.0.dev20250504.dist-info → zenml_nightly-0.82.0.dev20250506.dist-info}/METADATA
RENAMED
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.3
|
2
2
|
Name: zenml-nightly
|
3
|
-
Version: 0.82.0.
|
3
|
+
Version: 0.82.0.dev20250506
|
4
4
|
Summary: ZenML: Write production-ready ML code.
|
5
5
|
License: Apache-2.0
|
6
6
|
Keywords: machine learning,production,pipeline,mlops,devops
|
@@ -112,7 +112,7 @@ Requires-Dist: ruff (>=0.1.7) ; extra == "templates" or extra == "dev"
|
|
112
112
|
Requires-Dist: s3fs (>=2022.11.0,!=2025.3.1) ; extra == "s3fs"
|
113
113
|
Requires-Dist: sagemaker (>=2.237.3) ; extra == "sagemaker"
|
114
114
|
Requires-Dist: secure (>=0.3.0,<0.4.0) ; extra == "server"
|
115
|
-
Requires-Dist: setuptools
|
115
|
+
Requires-Dist: setuptools (>=70.0.0)
|
116
116
|
Requires-Dist: sqlalchemy (>=2.0.0,<3.0.0)
|
117
117
|
Requires-Dist: sqlalchemy_utils
|
118
118
|
Requires-Dist: sqlmodel (==0.0.18)
|
{zenml_nightly-0.82.0.dev20250504.dist-info → zenml_nightly-0.82.0.dev20250506.dist-info}/RECORD
RENAMED
@@ -1,5 +1,5 @@
|
|
1
1
|
zenml/README.md,sha256=827dekbOWAs1BpW7VF1a4d7EbwPbjwccX-2zdXBENZo,1777
|
2
|
-
zenml/VERSION,sha256=
|
2
|
+
zenml/VERSION,sha256=ppUfeGUhs-NasvRcl6HFrQq-3Bkc5Mvd-jli7V03Ufs,19
|
3
3
|
zenml/__init__.py,sha256=CKEyepFK-7akXYiMrNVh92Nb01Cjs23w4_YyI6sgdc8,2242
|
4
4
|
zenml/actions/__init__.py,sha256=mrt6wPo73iKRxK754_NqsGyJ3buW7RnVeIGXr1xEw8Y,681
|
5
5
|
zenml/actions/base_action.py,sha256=UcaHev6BTuLDwuswnyaPjdA8AgUqB5xPZ-lRtuvf2FU,25553
|
@@ -64,7 +64,7 @@ zenml/code_repositories/git/local_git_repository_context.py,sha256=hfX7zVDQ27Le0
|
|
64
64
|
zenml/code_repositories/local_repository_context.py,sha256=1VyiYkJBDVg0iGusgRQDToGRPJuu9lx7jTBDpplukDg,2816
|
65
65
|
zenml/config/__init__.py,sha256=DZEic7euSbwI9Yb3FMRQhTgfhqz-C6OdAiYmOb0-opI,1519
|
66
66
|
zenml/config/base_settings.py,sha256=itoLqc1cOwEYhgSGdZmSKSaBevQkvYH7NQh7PUamazc,1700
|
67
|
-
zenml/config/build_configuration.py,sha256=
|
67
|
+
zenml/config/build_configuration.py,sha256=tEAIXwAGS8Flxo4mK5BGHsBk7LPWW16MOa6oRDymZ7k,6172
|
68
68
|
zenml/config/compiler.py,sha256=jzyyTmM8nTxtpIVTSjZ-jrVOBJ1roVoJ3fs1A1nwv9M,24130
|
69
69
|
zenml/config/constants.py,sha256=QvSgMwXWxtspcJ45CrFDP1ZY3w6gS3bIhXLOtIDAbZA,713
|
70
70
|
zenml/config/docker_settings.py,sha256=w62SDW2Qo5jFxcikHr8p-Lk6ymC2ieh3MnEfkte9Lf0,13322
|
@@ -77,7 +77,7 @@ zenml/config/retry_config.py,sha256=4UH1xqw0G6fSEbXSNKfmiFEkwadxQef9BGMe3JBm6NI,
|
|
77
77
|
zenml/config/schedule.py,sha256=qtMWa-mEo7jIKvDzQUstMwe57gdbvyWAQ7ggsoddbCA,5349
|
78
78
|
zenml/config/secret_reference_mixin.py,sha256=YvY68MTd1gE23IVprf0BLkNn62hoxcvb5nqGgc8jMkU,5871
|
79
79
|
zenml/config/secrets_store_config.py,sha256=y05zqyQhr_DGrs3IfBGa_FRoZ043hSYRT5wzrx-zHTU,2818
|
80
|
-
zenml/config/server_config.py,sha256=
|
80
|
+
zenml/config/server_config.py,sha256=xLBOs_fWUM_Imk2IDzLPC1aVUSpwYYRobYAYC9hd2qE,31558
|
81
81
|
zenml/config/settings_resolver.py,sha256=PR9BRm_x1dy7nVKa9UqpeFdck8IEATSW6aWT8FKd-DI,4278
|
82
82
|
zenml/config/source.py,sha256=RzUw8lin8QztUjz-AdoCzVM5Om_cSSPuroaPx-qAO4w,8226
|
83
83
|
zenml/config/step_configurations.py,sha256=mngjobhHRj88f3klMdz6iw2mOj9wzYUPIV8Rp_2hV3g,10433
|
@@ -88,7 +88,7 @@ zenml/console.py,sha256=hj_KerPQKwnyKACj0ehSqUQX0mGVCJBKE1QvCt6ik3A,1160
|
|
88
88
|
zenml/constants.py,sha256=ZVwWVxE2h54cNbJDyujJmhAc8w3J7I9MkWHOfP4HN9A,16431
|
89
89
|
zenml/container_registries/__init__.py,sha256=ZSPbBIOnzhg88kQSpYgKe_POLuru14m629665-kAVAA,2200
|
90
90
|
zenml/container_registries/azure_container_registry.py,sha256=t1sfDa94Vzbyqtb1iPFNutJ2EXV5_p9CUNITasoiQ70,2667
|
91
|
-
zenml/container_registries/base_container_registry.py,sha256
|
91
|
+
zenml/container_registries/base_container_registry.py,sha256=-9RIkD6oXNPaU59R3PB_PtyCqsFoLPLSn5xYZmEmzbc,8915
|
92
92
|
zenml/container_registries/default_container_registry.py,sha256=_7lh2tQvoRgbQlSATc87Wzzl9dQzdTj8XvaTByTWKD4,1890
|
93
93
|
zenml/container_registries/dockerhub_container_registry.py,sha256=RtdP-xqqTCX5-s9g3bYI_asTqs6BHBsTWeg3tS_Rg00,2684
|
94
94
|
zenml/container_registries/gcp_container_registry.py,sha256=PNypXzqQ6RWDYP9_cPQUZDTf3NP6fxlsZWFD1Xu3jt4,2654
|
@@ -805,7 +805,7 @@ zenml/utils/yaml_utils.py,sha256=747M_BTf3lcHFgJDF8RJxnnGIbCU8e9YxBBMmoQ5O_U,583
|
|
805
805
|
zenml/zen_server/__init__.py,sha256=WyltI9TzFW2mEHZVOs6alLWMCQrrZaFALtrQXs83STA,1355
|
806
806
|
zenml/zen_server/auth.py,sha256=5EDqBb0HZJ8zr6OhwiTUcWkqoBFIEl3vfyit232UoOo,40259
|
807
807
|
zenml/zen_server/cache.py,sha256=Tc4TSugmsU1bhThxlYfE8rv0KmltIX1CcVHgzrJ0Eus,6633
|
808
|
-
zenml/zen_server/cloud_utils.py,sha256=
|
808
|
+
zenml/zen_server/cloud_utils.py,sha256=qKMtHjnkVfAk_yxF2K9iC0TkMCjp8s0gdz_cEsbB4DE,10908
|
809
809
|
zenml/zen_server/csrf.py,sha256=Jsbi_IKriWCOuquSYTOEWqSXiGORJATIhR5Wrkm4XzQ,2684
|
810
810
|
zenml/zen_server/dashboard/assets/404-D4aYbspS.js,sha256=w7_KToWud6ST-NPC7zVqs4lFHLr8_q95w3pUYc-W0xo,1033
|
811
811
|
zenml/zen_server/dashboard/assets/@radix-C7hRs6Kx.js,sha256=cNA9UX8LGrKUQubGrls3E3Wq1fCrlK51W14yh22FE_U,296700
|
@@ -1318,8 +1318,8 @@ zenml/zen_stores/secrets_stores/sql_secrets_store.py,sha256=LPFW757WCJLP1S8vrvjs
|
|
1318
1318
|
zenml/zen_stores/sql_zen_store.py,sha256=biOoDb2_zYmpsN-J-FSlKICYdwM9KDIe-_KN_yDf_mA,441414
|
1319
1319
|
zenml/zen_stores/template_utils.py,sha256=GWBP5QEOyvhzndS_MLPmvh28sQaOPpPoZFXCIX9CRL4,9065
|
1320
1320
|
zenml/zen_stores/zen_store_interface.py,sha256=fF_uL_FplnvGvM5o3jOQ8i1zHXhuhKLL2n4nvIKSR7E,92090
|
1321
|
-
zenml_nightly-0.82.0.
|
1322
|
-
zenml_nightly-0.82.0.
|
1323
|
-
zenml_nightly-0.82.0.
|
1324
|
-
zenml_nightly-0.82.0.
|
1325
|
-
zenml_nightly-0.82.0.
|
1321
|
+
zenml_nightly-0.82.0.dev20250506.dist-info/LICENSE,sha256=wbnfEnXnafPbqwANHkV6LUsPKOtdpsd-SNw37rogLtc,11359
|
1322
|
+
zenml_nightly-0.82.0.dev20250506.dist-info/METADATA,sha256=_sWp9WjyqeWPdnHJ3RUVzjNOID0vYkZhrN-yKVh7tuM,24315
|
1323
|
+
zenml_nightly-0.82.0.dev20250506.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
|
1324
|
+
zenml_nightly-0.82.0.dev20250506.dist-info/entry_points.txt,sha256=QK3ETQE0YswAM2mWypNMOv8TLtr7EjnqAFq1br_jEFE,43
|
1325
|
+
zenml_nightly-0.82.0.dev20250506.dist-info/RECORD,,
|
{zenml_nightly-0.82.0.dev20250504.dist-info → zenml_nightly-0.82.0.dev20250506.dist-info}/LICENSE
RENAMED
File without changes
|
File without changes
|