zenml-nightly 0.80.0.dev20250325__py3-none-any.whl → 0.80.0.dev20250327__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/cli/project.py +36 -3
- zenml/cli/server.py +1 -0
- zenml/client.py +7 -2
- zenml/config/global_config.py +15 -15
- zenml/integrations/kubernetes/orchestrators/kubernetes_orchestrator.py +1 -1
- zenml/models/v2/core/user.py +17 -0
- zenml/service_connectors/service_connector_registry.py +6 -8
- zenml/zen_server/routers/users_endpoints.py +169 -173
- zenml/zen_stores/base_zen_store.py +46 -15
- zenml/zen_stores/migrations/versions/1f1105204aaf_add_user_default_project.py +51 -0
- zenml/zen_stores/schemas/user_schemas.py +11 -0
- {zenml_nightly-0.80.0.dev20250325.dist-info → zenml_nightly-0.80.0.dev20250327.dist-info}/METADATA +1 -1
- {zenml_nightly-0.80.0.dev20250325.dist-info → zenml_nightly-0.80.0.dev20250327.dist-info}/RECORD +17 -16
- {zenml_nightly-0.80.0.dev20250325.dist-info → zenml_nightly-0.80.0.dev20250327.dist-info}/LICENSE +0 -0
- {zenml_nightly-0.80.0.dev20250325.dist-info → zenml_nightly-0.80.0.dev20250327.dist-info}/WHEEL +0 -0
- {zenml_nightly-0.80.0.dev20250325.dist-info → zenml_nightly-0.80.0.dev20250327.dist-info}/entry_points.txt +0 -0
zenml/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.80.0.
|
1
|
+
0.80.0.dev20250327
|
zenml/cli/project.py
CHANGED
@@ -75,11 +75,18 @@ def list_projects(ctx: click.Context, /, **kwargs: Any) -> None:
|
|
75
75
|
required=False,
|
76
76
|
help="The display name of the project.",
|
77
77
|
)
|
78
|
+
@click.option(
|
79
|
+
"--set-default",
|
80
|
+
"set_default",
|
81
|
+
is_flag=True,
|
82
|
+
help="Set this project as the default project.",
|
83
|
+
)
|
78
84
|
@click.argument("project_name", type=str, required=True)
|
79
85
|
def register_project(
|
80
86
|
project_name: str,
|
81
87
|
set_project: bool = False,
|
82
88
|
display_name: Optional[str] = None,
|
89
|
+
set_default: bool = False,
|
83
90
|
) -> None:
|
84
91
|
"""Register a new project.
|
85
92
|
|
@@ -87,12 +94,13 @@ def register_project(
|
|
87
94
|
project_name: The name of the project to register.
|
88
95
|
set_project: Whether to set the project as active.
|
89
96
|
display_name: The display name of the project.
|
97
|
+
set_default: Whether to set the project as the default project.
|
90
98
|
"""
|
91
99
|
check_zenml_pro_project_availability()
|
92
100
|
client = Client()
|
93
101
|
with console.status("Creating project...\n"):
|
94
102
|
try:
|
95
|
-
client.create_project(
|
103
|
+
project = client.create_project(
|
96
104
|
project_name,
|
97
105
|
description="",
|
98
106
|
display_name=display_name,
|
@@ -105,26 +113,51 @@ def register_project(
|
|
105
113
|
client.set_active_project(project_name)
|
106
114
|
cli_utils.declare(f"The active project has been set to {project_name}")
|
107
115
|
|
116
|
+
if set_default:
|
117
|
+
client.update_user(
|
118
|
+
name_id_or_prefix=client.active_user.id,
|
119
|
+
updated_default_project_id=project.id,
|
120
|
+
)
|
121
|
+
cli_utils.declare(
|
122
|
+
f"The default project has been set to {project.name}"
|
123
|
+
)
|
124
|
+
|
108
125
|
|
109
126
|
@project.command("set")
|
110
127
|
@click.argument("project_name_or_id", type=str, required=True)
|
111
|
-
|
128
|
+
@click.option(
|
129
|
+
"--default",
|
130
|
+
"default",
|
131
|
+
is_flag=True,
|
132
|
+
help="Set this project as the default project.",
|
133
|
+
)
|
134
|
+
def set_project(project_name_or_id: str, default: bool = False) -> None:
|
112
135
|
"""Set the active project.
|
113
136
|
|
114
137
|
Args:
|
115
138
|
project_name_or_id: The name or ID of the project to set as active.
|
139
|
+
default: Whether to set the project as the default project.
|
116
140
|
"""
|
117
141
|
check_zenml_pro_project_availability()
|
118
142
|
client = Client()
|
119
143
|
with console.status("Setting project...\n"):
|
120
144
|
try:
|
121
|
-
client.set_active_project(project_name_or_id)
|
145
|
+
project = client.set_active_project(project_name_or_id)
|
122
146
|
cli_utils.declare(
|
123
147
|
f"The active project has been set to {project_name_or_id}"
|
124
148
|
)
|
125
149
|
except Exception as e:
|
126
150
|
cli_utils.error(str(e))
|
127
151
|
|
152
|
+
if default:
|
153
|
+
client.update_user(
|
154
|
+
name_id_or_prefix=client.active_user.id,
|
155
|
+
updated_default_project_id=project.id,
|
156
|
+
)
|
157
|
+
cli_utils.declare(
|
158
|
+
f"The default project has been set to {project.name}"
|
159
|
+
)
|
160
|
+
|
128
161
|
|
129
162
|
@project.command("describe")
|
130
163
|
@click.argument("project_name_or_id", type=str, required=False)
|
zenml/cli/server.py
CHANGED
zenml/client.py
CHANGED
@@ -235,7 +235,7 @@ class ClientConfiguration(FileSyncModel):
|
|
235
235
|
else:
|
236
236
|
raise RuntimeError(
|
237
237
|
"No active project is configured. Run "
|
238
|
-
"`zenml project set
|
238
|
+
"`zenml project set <NAME>` to set the active "
|
239
239
|
"project."
|
240
240
|
)
|
241
241
|
|
@@ -876,6 +876,7 @@ class Client(metaclass=ClientMetaClass):
|
|
876
876
|
old_password: Optional[str] = None,
|
877
877
|
updated_is_admin: Optional[bool] = None,
|
878
878
|
updated_metadata: Optional[Dict[str, Any]] = None,
|
879
|
+
updated_default_project_id: Optional[UUID] = None,
|
879
880
|
active: Optional[bool] = None,
|
880
881
|
) -> UserResponse:
|
881
882
|
"""Update a user.
|
@@ -891,6 +892,7 @@ class Client(metaclass=ClientMetaClass):
|
|
891
892
|
update.
|
892
893
|
updated_is_admin: Whether the user should be an admin.
|
893
894
|
updated_metadata: The new metadata for the user.
|
895
|
+
updated_default_project_id: The new default project ID for the user.
|
894
896
|
active: Use to activate or deactivate the user.
|
895
897
|
|
896
898
|
Returns:
|
@@ -928,6 +930,9 @@ class Client(metaclass=ClientMetaClass):
|
|
928
930
|
if updated_metadata is not None:
|
929
931
|
user_update.user_metadata = updated_metadata
|
930
932
|
|
933
|
+
if updated_default_project_id is not None:
|
934
|
+
user_update.default_project_id = updated_default_project_id
|
935
|
+
|
931
936
|
return self.zen_store.update_user(
|
932
937
|
user_id=user.id, user_update=user_update
|
933
938
|
)
|
@@ -1154,7 +1159,7 @@ class Client(metaclass=ClientMetaClass):
|
|
1154
1159
|
if not project:
|
1155
1160
|
raise RuntimeError(
|
1156
1161
|
"No active project is configured. Run "
|
1157
|
-
"`zenml project set
|
1162
|
+
"`zenml project set <NAME>` to set the active "
|
1158
1163
|
"project."
|
1159
1164
|
)
|
1160
1165
|
|
zenml/config/global_config.py
CHANGED
@@ -113,7 +113,7 @@ class GlobalConfiguration(BaseModel, metaclass=GlobalConfigMetaClass):
|
|
113
113
|
global config.
|
114
114
|
store: Store configuration.
|
115
115
|
active_stack_id: The ID of the active stack.
|
116
|
-
|
116
|
+
active_project_id: The ID of the active project.
|
117
117
|
"""
|
118
118
|
|
119
119
|
user_id: uuid.UUID = Field(default_factory=uuid.uuid4)
|
@@ -123,7 +123,7 @@ class GlobalConfiguration(BaseModel, metaclass=GlobalConfigMetaClass):
|
|
123
123
|
version: Optional[str] = None
|
124
124
|
store: Optional[SerializeAsAny[StoreConfiguration]] = None
|
125
125
|
active_stack_id: Optional[uuid.UUID] = None
|
126
|
-
|
126
|
+
active_project_id: Optional[uuid.UUID] = None
|
127
127
|
|
128
128
|
_zen_store: Optional["BaseZenStore"] = None
|
129
129
|
_active_project: Optional["ProjectResponse"] = None
|
@@ -393,15 +393,15 @@ class GlobalConfiguration(BaseModel, metaclass=GlobalConfigMetaClass):
|
|
393
393
|
if ENV_ZENML_SERVER in os.environ:
|
394
394
|
return
|
395
395
|
active_project, active_stack = self.zen_store.validate_active_config(
|
396
|
-
self.
|
396
|
+
self.active_project_id,
|
397
397
|
self.active_stack_id,
|
398
398
|
config_name="global",
|
399
399
|
)
|
400
400
|
if active_project:
|
401
|
-
self.
|
401
|
+
self.active_project_id = active_project.id
|
402
402
|
self._active_project = active_project
|
403
403
|
else:
|
404
|
-
self.
|
404
|
+
self.active_project_id = None
|
405
405
|
self._active_project = None
|
406
406
|
|
407
407
|
self.set_active_stack(active_stack)
|
@@ -730,7 +730,7 @@ class GlobalConfiguration(BaseModel, metaclass=GlobalConfigMetaClass):
|
|
730
730
|
Returns:
|
731
731
|
The project that was set active.
|
732
732
|
"""
|
733
|
-
self.
|
733
|
+
self.active_project_id = project.id
|
734
734
|
self._active_project = project
|
735
735
|
# Sanitize the global configuration to reflect the new project
|
736
736
|
self._sanitize_config()
|
@@ -751,35 +751,35 @@ class GlobalConfiguration(BaseModel, metaclass=GlobalConfigMetaClass):
|
|
751
751
|
Returns:
|
752
752
|
The model of the active project.
|
753
753
|
"""
|
754
|
-
|
754
|
+
project_id = self.get_active_project_id()
|
755
755
|
|
756
756
|
if self._active_project is not None:
|
757
757
|
return self._active_project
|
758
758
|
|
759
759
|
project = self.zen_store.get_project(
|
760
|
-
project_name_or_id=
|
760
|
+
project_name_or_id=project_id,
|
761
761
|
)
|
762
762
|
return self.set_active_project(project)
|
763
763
|
|
764
|
-
def
|
765
|
-
"""Get the
|
764
|
+
def get_active_project_id(self) -> UUID:
|
765
|
+
"""Get the ID of the active project.
|
766
766
|
|
767
767
|
Returns:
|
768
|
-
The
|
768
|
+
The ID of the active project.
|
769
769
|
|
770
770
|
Raises:
|
771
771
|
RuntimeError: If the active project is not set.
|
772
772
|
"""
|
773
|
-
if self.
|
773
|
+
if self.active_project_id is None:
|
774
774
|
_ = self.zen_store
|
775
|
-
if self.
|
775
|
+
if self.active_project_id is None:
|
776
776
|
raise RuntimeError(
|
777
777
|
"No project is currently set as active. Please set the "
|
778
|
-
"active project using the `zenml project set
|
778
|
+
"active project using the `zenml project set <NAME>` CLI "
|
779
779
|
"command."
|
780
780
|
)
|
781
781
|
|
782
|
-
return self.
|
782
|
+
return self.active_project_id
|
783
783
|
|
784
784
|
def get_active_stack_id(self) -> UUID:
|
785
785
|
"""Get the ID of the active stack.
|
@@ -238,7 +238,7 @@ class KubernetesOrchestrator(ContainerizedOrchestrator):
|
|
238
238
|
)
|
239
239
|
if kubernetes_context != active_context:
|
240
240
|
logger.warning(
|
241
|
-
f"{msg}the Kubernetes context "
|
241
|
+
f"{msg}the Kubernetes context " # nosec
|
242
242
|
f"'{kubernetes_context}' configured for the "
|
243
243
|
f"Kubernetes orchestrator is not the same as the "
|
244
244
|
f"active context in the local Kubernetes "
|
zenml/models/v2/core/user.py
CHANGED
@@ -203,6 +203,10 @@ class UserUpdate(UserBase, BaseUpdate):
|
|
203
203
|
"accounts. Required when updating the password.",
|
204
204
|
max_length=STR_FIELD_MAX_LENGTH,
|
205
205
|
)
|
206
|
+
default_project_id: Optional[UUID] = Field(
|
207
|
+
default=None,
|
208
|
+
title="The default project ID for the user.",
|
209
|
+
)
|
206
210
|
|
207
211
|
@model_validator(mode="after")
|
208
212
|
def user_email_updates(self) -> "UserUpdate":
|
@@ -279,6 +283,10 @@ class UserResponseBody(BaseDatedResponseBody):
|
|
279
283
|
is_admin: bool = Field(
|
280
284
|
title="Whether the account is an administrator.",
|
281
285
|
)
|
286
|
+
default_project_id: Optional[UUID] = Field(
|
287
|
+
default=None,
|
288
|
+
title="The default project ID for the user.",
|
289
|
+
)
|
282
290
|
|
283
291
|
|
284
292
|
class UserResponseMetadata(BaseResponseMetadata):
|
@@ -422,6 +430,15 @@ class UserResponse(
|
|
422
430
|
"""
|
423
431
|
return self.get_metadata().user_metadata
|
424
432
|
|
433
|
+
@property
|
434
|
+
def default_project_id(self) -> Optional[UUID]:
|
435
|
+
"""The `default_project_id` property.
|
436
|
+
|
437
|
+
Returns:
|
438
|
+
the value of the property.
|
439
|
+
"""
|
440
|
+
return self.get_body().default_project_id
|
441
|
+
|
425
442
|
# Helper methods
|
426
443
|
@classmethod
|
427
444
|
def _get_crypt_context(cls) -> "CryptContext":
|
@@ -216,30 +216,28 @@ class ServiceConnectorRegistry:
|
|
216
216
|
AWSServiceConnector,
|
217
217
|
)
|
218
218
|
except ImportError as e:
|
219
|
-
logger.
|
219
|
+
logger.debug(f"Could not import AWS service connector: {e}.")
|
220
220
|
|
221
221
|
try:
|
222
222
|
from zenml.integrations.gcp.service_connectors.gcp_service_connector import ( # noqa
|
223
223
|
GCPServiceConnector,
|
224
224
|
)
|
225
225
|
except ImportError as e:
|
226
|
-
logger.
|
226
|
+
logger.debug(f"Could not import GCP service connector: {e}.")
|
227
227
|
|
228
228
|
try:
|
229
229
|
from zenml.integrations.azure.service_connectors.azure_service_connector import ( # noqa
|
230
230
|
AzureServiceConnector,
|
231
231
|
)
|
232
232
|
except ImportError as e:
|
233
|
-
logger.
|
234
|
-
f"Could not import Azure service connector: {e}."
|
235
|
-
)
|
233
|
+
logger.debug(f"Could not import Azure service connector: {e}.")
|
236
234
|
|
237
235
|
try:
|
238
236
|
from zenml.integrations.kubernetes.service_connectors.kubernetes_service_connector import ( # noqa
|
239
237
|
KubernetesServiceConnector,
|
240
238
|
)
|
241
239
|
except ImportError as e:
|
242
|
-
logger.
|
240
|
+
logger.debug(
|
243
241
|
f"Could not import Kubernetes service connector: {e}."
|
244
242
|
)
|
245
243
|
|
@@ -248,7 +246,7 @@ class ServiceConnectorRegistry:
|
|
248
246
|
DockerServiceConnector,
|
249
247
|
)
|
250
248
|
except ImportError as e:
|
251
|
-
logger.
|
249
|
+
logger.debug(
|
252
250
|
f"Could not import Docker service connector: {e}."
|
253
251
|
)
|
254
252
|
|
@@ -257,7 +255,7 @@ class ServiceConnectorRegistry:
|
|
257
255
|
HyperAIServiceConnector,
|
258
256
|
)
|
259
257
|
except ImportError as e:
|
260
|
-
logger.
|
258
|
+
logger.debug(
|
261
259
|
f"Could not import HyperAI service connector: {e}."
|
262
260
|
)
|
263
261
|
|
@@ -65,6 +65,11 @@ from zenml.zen_server.utils import (
|
|
65
65
|
|
66
66
|
logger = get_logger(__name__)
|
67
67
|
|
68
|
+
pass_change_limiter = RequestLimiter(
|
69
|
+
day_limit=server_config().login_rate_limit_day,
|
70
|
+
minute_limit=server_config().login_rate_limit_minute,
|
71
|
+
)
|
72
|
+
|
68
73
|
router = APIRouter(
|
69
74
|
prefix=API + VERSION_1 + USERS,
|
70
75
|
tags=["users"],
|
@@ -223,179 +228,6 @@ def get_user(
|
|
223
228
|
# When the auth scheme is set to EXTERNAL, users cannot be updated via the
|
224
229
|
# API.
|
225
230
|
if server_config().auth_scheme != AuthScheme.EXTERNAL:
|
226
|
-
pass_change_limiter = RequestLimiter(
|
227
|
-
day_limit=server_config().login_rate_limit_day,
|
228
|
-
minute_limit=server_config().login_rate_limit_minute,
|
229
|
-
)
|
230
|
-
|
231
|
-
@router.put(
|
232
|
-
"/{user_name_or_id}",
|
233
|
-
responses={
|
234
|
-
401: error_response,
|
235
|
-
404: error_response,
|
236
|
-
422: error_response,
|
237
|
-
},
|
238
|
-
)
|
239
|
-
@handle_exceptions
|
240
|
-
def update_user(
|
241
|
-
user_name_or_id: Union[str, UUID],
|
242
|
-
user_update: UserUpdate,
|
243
|
-
request: Request,
|
244
|
-
auth_context: AuthContext = Security(authorize),
|
245
|
-
) -> UserResponse:
|
246
|
-
"""Updates a specific user.
|
247
|
-
|
248
|
-
Args:
|
249
|
-
user_name_or_id: Name or ID of the user.
|
250
|
-
user_update: the user to use for the update.
|
251
|
-
request: The request object.
|
252
|
-
auth_context: Authentication context.
|
253
|
-
|
254
|
-
Returns:
|
255
|
-
The updated user.
|
256
|
-
|
257
|
-
Raises:
|
258
|
-
IllegalOperationError: if the user tries change admin status,
|
259
|
-
while not an admin, if the user tries to change the password
|
260
|
-
of another user, or if the user tries to change their own
|
261
|
-
password without providing the old password or providing
|
262
|
-
an incorrect old password.
|
263
|
-
"""
|
264
|
-
user = zen_store().get_user(user_name_or_id)
|
265
|
-
|
266
|
-
# Use a separate object to compute the update that will be applied to
|
267
|
-
# the user to avoid giving the API requester direct control over the
|
268
|
-
# user attributes that are updated.
|
269
|
-
#
|
270
|
-
# Exclude attributes that cannot be updated through this endpoint:
|
271
|
-
#
|
272
|
-
# - activation_token
|
273
|
-
# - external_user_id
|
274
|
-
# - old_password
|
275
|
-
#
|
276
|
-
# Exclude things that are not always safe to update and need to be
|
277
|
-
# validated first:
|
278
|
-
#
|
279
|
-
# - admin
|
280
|
-
# - active
|
281
|
-
# - password
|
282
|
-
# - email_opted_in + email
|
283
|
-
#
|
284
|
-
safe_user_update = user_update.create_copy(
|
285
|
-
exclude={
|
286
|
-
"activation_token",
|
287
|
-
"external_user_id",
|
288
|
-
"is_admin",
|
289
|
-
"active",
|
290
|
-
"password",
|
291
|
-
"old_password",
|
292
|
-
"email_opted_in",
|
293
|
-
"email",
|
294
|
-
},
|
295
|
-
)
|
296
|
-
|
297
|
-
if user.id != auth_context.user.id:
|
298
|
-
verify_admin_status_if_no_rbac(
|
299
|
-
auth_context.user.is_admin, "update other user account"
|
300
|
-
)
|
301
|
-
# verify_permission_for_model(
|
302
|
-
# user,
|
303
|
-
# action=Action.UPDATE,
|
304
|
-
# )
|
305
|
-
|
306
|
-
# Validate a password change
|
307
|
-
if user_update.password is not None:
|
308
|
-
if user.id != auth_context.user.id:
|
309
|
-
raise IllegalOperationError(
|
310
|
-
"Users cannot change the password of other users. Use the "
|
311
|
-
"account deactivation and activation flow instead."
|
312
|
-
)
|
313
|
-
|
314
|
-
# If the user is updating their own password, we need to verify
|
315
|
-
# the old password
|
316
|
-
if user_update.old_password is None:
|
317
|
-
raise IllegalOperationError(
|
318
|
-
"The current password must be supplied when changing the "
|
319
|
-
"password."
|
320
|
-
)
|
321
|
-
|
322
|
-
with pass_change_limiter.limit_failed_requests(request):
|
323
|
-
auth_user = zen_store().get_auth_user(user_name_or_id)
|
324
|
-
if not UserAuthModel.verify_password(
|
325
|
-
user_update.old_password, auth_user
|
326
|
-
):
|
327
|
-
raise IllegalOperationError(
|
328
|
-
"The current password is incorrect."
|
329
|
-
)
|
330
|
-
|
331
|
-
# Accept the password update
|
332
|
-
safe_user_update.password = user_update.password
|
333
|
-
|
334
|
-
# Validate an admin status change
|
335
|
-
if (
|
336
|
-
user_update.is_admin is not None
|
337
|
-
and user.is_admin != user_update.is_admin
|
338
|
-
):
|
339
|
-
if user.id == auth_context.user.id:
|
340
|
-
raise IllegalOperationError(
|
341
|
-
"Cannot change the admin status of your own user account."
|
342
|
-
)
|
343
|
-
|
344
|
-
if (
|
345
|
-
user.id != auth_context.user.id
|
346
|
-
and not auth_context.user.is_admin
|
347
|
-
):
|
348
|
-
raise IllegalOperationError(
|
349
|
-
"Only admins are allowed to change the admin status of "
|
350
|
-
"other user accounts."
|
351
|
-
)
|
352
|
-
|
353
|
-
# Accept the admin status update
|
354
|
-
safe_user_update.is_admin = user_update.is_admin
|
355
|
-
|
356
|
-
# Validate an active status change
|
357
|
-
if (
|
358
|
-
user_update.active is not None
|
359
|
-
and user.active != user_update.active
|
360
|
-
):
|
361
|
-
if user.id == auth_context.user.id:
|
362
|
-
raise IllegalOperationError(
|
363
|
-
"Cannot change the active status of your own user account."
|
364
|
-
)
|
365
|
-
|
366
|
-
if (
|
367
|
-
user.id != auth_context.user.id
|
368
|
-
and not auth_context.user.is_admin
|
369
|
-
):
|
370
|
-
raise IllegalOperationError(
|
371
|
-
"Only admins are allowed to change the active status of "
|
372
|
-
"other user accounts."
|
373
|
-
)
|
374
|
-
|
375
|
-
# Accept the admin status update
|
376
|
-
safe_user_update.is_admin = user_update.is_admin
|
377
|
-
|
378
|
-
# Validate changes to private user account information
|
379
|
-
if (
|
380
|
-
user_update.email_opted_in is not None
|
381
|
-
or user_update.email is not None
|
382
|
-
):
|
383
|
-
if user.id != auth_context.user.id:
|
384
|
-
raise IllegalOperationError(
|
385
|
-
"Cannot change the private user account information for "
|
386
|
-
"another user account."
|
387
|
-
)
|
388
|
-
|
389
|
-
# Accept the private user account information update
|
390
|
-
if safe_user_update.email_opted_in is not None:
|
391
|
-
safe_user_update.email_opted_in = user_update.email_opted_in
|
392
|
-
safe_user_update.email = user_update.email
|
393
|
-
|
394
|
-
updated_user = zen_store().update_user(
|
395
|
-
user_id=user.id,
|
396
|
-
user_update=safe_user_update,
|
397
|
-
)
|
398
|
-
return dehydrate_response_model(updated_user)
|
399
231
|
|
400
232
|
@activation_router.put(
|
401
233
|
"/{user_name_or_id}" + ACTIVATE,
|
@@ -599,6 +431,170 @@ if server_config().auth_scheme != AuthScheme.EXTERNAL:
|
|
599
431
|
)
|
600
432
|
|
601
433
|
|
434
|
+
@router.put(
|
435
|
+
"/{user_name_or_id}",
|
436
|
+
responses={
|
437
|
+
401: error_response,
|
438
|
+
404: error_response,
|
439
|
+
422: error_response,
|
440
|
+
},
|
441
|
+
)
|
442
|
+
@handle_exceptions
|
443
|
+
def update_user(
|
444
|
+
user_name_or_id: Union[str, UUID],
|
445
|
+
user_update: UserUpdate,
|
446
|
+
request: Request,
|
447
|
+
auth_context: AuthContext = Security(authorize),
|
448
|
+
) -> UserResponse:
|
449
|
+
"""Updates a specific user.
|
450
|
+
|
451
|
+
Args:
|
452
|
+
user_name_or_id: Name or ID of the user.
|
453
|
+
user_update: the user to use for the update.
|
454
|
+
request: The request object.
|
455
|
+
auth_context: Authentication context.
|
456
|
+
|
457
|
+
Returns:
|
458
|
+
The updated user.
|
459
|
+
|
460
|
+
Raises:
|
461
|
+
IllegalOperationError: if the user tries change admin status,
|
462
|
+
while not an admin, if the user tries to change the password
|
463
|
+
of another user, or if the user tries to change their own
|
464
|
+
password without providing the old password or providing
|
465
|
+
an incorrect old password.
|
466
|
+
"""
|
467
|
+
if server_config().auth_scheme == AuthScheme.EXTERNAL:
|
468
|
+
# For external auth, we only allow updating the default project
|
469
|
+
user_update = UserUpdate(
|
470
|
+
default_project_id=user_update.default_project_id,
|
471
|
+
)
|
472
|
+
|
473
|
+
user = zen_store().get_user(user_name_or_id)
|
474
|
+
|
475
|
+
# Use a separate object to compute the update that will be applied to
|
476
|
+
# the user to avoid giving the API requester direct control over the
|
477
|
+
# user attributes that are updated.
|
478
|
+
#
|
479
|
+
# Exclude attributes that cannot be updated through this endpoint:
|
480
|
+
#
|
481
|
+
# - activation_token
|
482
|
+
# - external_user_id
|
483
|
+
# - old_password
|
484
|
+
#
|
485
|
+
# Exclude things that are not always safe to update and need to be
|
486
|
+
# validated first:
|
487
|
+
#
|
488
|
+
# - admin
|
489
|
+
# - active
|
490
|
+
# - password
|
491
|
+
# - email_opted_in + email
|
492
|
+
#
|
493
|
+
safe_user_update = user_update.create_copy(
|
494
|
+
exclude={
|
495
|
+
"activation_token",
|
496
|
+
"external_user_id",
|
497
|
+
"is_admin",
|
498
|
+
"active",
|
499
|
+
"password",
|
500
|
+
"old_password",
|
501
|
+
"email_opted_in",
|
502
|
+
"email",
|
503
|
+
},
|
504
|
+
)
|
505
|
+
|
506
|
+
if user.id != auth_context.user.id:
|
507
|
+
verify_admin_status_if_no_rbac(
|
508
|
+
auth_context.user.is_admin, "update other user account"
|
509
|
+
)
|
510
|
+
# verify_permission_for_model(
|
511
|
+
# user,
|
512
|
+
# action=Action.UPDATE,
|
513
|
+
# )
|
514
|
+
|
515
|
+
# Validate a password change
|
516
|
+
if user_update.password is not None:
|
517
|
+
if user.id != auth_context.user.id:
|
518
|
+
raise IllegalOperationError(
|
519
|
+
"Users cannot change the password of other users. Use the "
|
520
|
+
"account deactivation and activation flow instead."
|
521
|
+
)
|
522
|
+
|
523
|
+
# If the user is updating their own password, we need to verify
|
524
|
+
# the old password
|
525
|
+
if user_update.old_password is None:
|
526
|
+
raise IllegalOperationError(
|
527
|
+
"The current password must be supplied when changing the "
|
528
|
+
"password."
|
529
|
+
)
|
530
|
+
|
531
|
+
with pass_change_limiter.limit_failed_requests(request):
|
532
|
+
auth_user = zen_store().get_auth_user(user_name_or_id)
|
533
|
+
if not UserAuthModel.verify_password(
|
534
|
+
user_update.old_password, auth_user
|
535
|
+
):
|
536
|
+
raise IllegalOperationError(
|
537
|
+
"The current password is incorrect."
|
538
|
+
)
|
539
|
+
|
540
|
+
# Accept the password update
|
541
|
+
safe_user_update.password = user_update.password
|
542
|
+
|
543
|
+
# Validate an admin status change
|
544
|
+
if (
|
545
|
+
user_update.is_admin is not None
|
546
|
+
and user.is_admin != user_update.is_admin
|
547
|
+
):
|
548
|
+
if user.id == auth_context.user.id:
|
549
|
+
raise IllegalOperationError(
|
550
|
+
"Cannot change the admin status of your own user account."
|
551
|
+
)
|
552
|
+
|
553
|
+
if user.id != auth_context.user.id and not auth_context.user.is_admin:
|
554
|
+
raise IllegalOperationError(
|
555
|
+
"Only admins are allowed to change the admin status of "
|
556
|
+
"other user accounts."
|
557
|
+
)
|
558
|
+
|
559
|
+
# Accept the admin status update
|
560
|
+
safe_user_update.is_admin = user_update.is_admin
|
561
|
+
|
562
|
+
# Validate an active status change
|
563
|
+
if user_update.active is not None and user.active != user_update.active:
|
564
|
+
if user.id == auth_context.user.id:
|
565
|
+
raise IllegalOperationError(
|
566
|
+
"Cannot change the active status of your own user account."
|
567
|
+
)
|
568
|
+
|
569
|
+
if user.id != auth_context.user.id and not auth_context.user.is_admin:
|
570
|
+
raise IllegalOperationError(
|
571
|
+
"Only admins are allowed to change the active status of "
|
572
|
+
"other user accounts."
|
573
|
+
)
|
574
|
+
|
575
|
+
# Accept the admin status update
|
576
|
+
safe_user_update.is_admin = user_update.is_admin
|
577
|
+
|
578
|
+
# Validate changes to private user account information
|
579
|
+
if user_update.email_opted_in is not None or user_update.email is not None:
|
580
|
+
if user.id != auth_context.user.id:
|
581
|
+
raise IllegalOperationError(
|
582
|
+
"Cannot change the private user account information for "
|
583
|
+
"another user account."
|
584
|
+
)
|
585
|
+
|
586
|
+
# Accept the private user account information update
|
587
|
+
if safe_user_update.email_opted_in is not None:
|
588
|
+
safe_user_update.email_opted_in = user_update.email_opted_in
|
589
|
+
safe_user_update.email = user_update.email
|
590
|
+
|
591
|
+
updated_user = zen_store().update_user(
|
592
|
+
user_id=user.id,
|
593
|
+
user_update=safe_user_update,
|
594
|
+
)
|
595
|
+
return dehydrate_response_model(updated_user)
|
596
|
+
|
597
|
+
|
602
598
|
@current_user_router.get(
|
603
599
|
"/current-user",
|
604
600
|
responses={401: error_response, 404: error_response, 422: error_response},
|
@@ -22,7 +22,6 @@ from typing import (
|
|
22
22
|
Optional,
|
23
23
|
Tuple,
|
24
24
|
Type,
|
25
|
-
Union,
|
26
25
|
)
|
27
26
|
from uuid import UUID
|
28
27
|
|
@@ -46,6 +45,7 @@ from zenml.enums import (
|
|
46
45
|
from zenml.exceptions import IllegalOperationError
|
47
46
|
from zenml.logger import get_logger
|
48
47
|
from zenml.models import (
|
48
|
+
ProjectFilter,
|
49
49
|
ProjectResponse,
|
50
50
|
ServerDatabaseType,
|
51
51
|
ServerDeploymentType,
|
@@ -232,7 +232,6 @@ class BaseZenStore(
|
|
232
232
|
Returns:
|
233
233
|
The initialized store.
|
234
234
|
"""
|
235
|
-
logger.debug(f"Creating store with config '{config}'...")
|
236
235
|
store_class = BaseZenStore.get_store_class(config.type)
|
237
236
|
store = store_class(
|
238
237
|
config=config,
|
@@ -292,7 +291,7 @@ class BaseZenStore(
|
|
292
291
|
|
293
292
|
def validate_active_config(
|
294
293
|
self,
|
295
|
-
|
294
|
+
active_project_id: Optional[UUID] = None,
|
296
295
|
active_stack_id: Optional[UUID] = None,
|
297
296
|
config_name: str = "",
|
298
297
|
) -> Tuple[Optional[ProjectResponse], StackResponse]:
|
@@ -307,7 +306,7 @@ class BaseZenStore(
|
|
307
306
|
stack will be returned in their stead.
|
308
307
|
|
309
308
|
Args:
|
310
|
-
|
309
|
+
active_project_id: The ID of the active project.
|
311
310
|
active_stack_id: The ID of the active stack.
|
312
311
|
config_name: The name of the configuration to validate (used in the
|
313
312
|
displayed logs/messages).
|
@@ -317,30 +316,62 @@ class BaseZenStore(
|
|
317
316
|
"""
|
318
317
|
active_project: Optional[ProjectResponse] = None
|
319
318
|
|
320
|
-
if
|
319
|
+
if active_project_id:
|
321
320
|
try:
|
322
|
-
active_project = self.get_project(
|
321
|
+
active_project = self.get_project(active_project_id)
|
323
322
|
except (KeyError, IllegalOperationError):
|
324
|
-
|
323
|
+
active_project_id = None
|
325
324
|
logger.warning(
|
326
325
|
f"The current {config_name} active project is no longer "
|
327
326
|
f"available."
|
328
327
|
)
|
329
328
|
|
329
|
+
if active_project is None:
|
330
|
+
user = self.get_user()
|
331
|
+
if user.default_project_id:
|
332
|
+
try:
|
333
|
+
active_project = self.get_project(user.default_project_id)
|
334
|
+
except (KeyError, IllegalOperationError):
|
335
|
+
logger.warning(
|
336
|
+
"The default project %s for the active user is no longer "
|
337
|
+
"available.",
|
338
|
+
user.default_project_id,
|
339
|
+
)
|
340
|
+
else:
|
341
|
+
logger.info(
|
342
|
+
f"Setting the {config_name} active project "
|
343
|
+
f"to '{active_project.name}'."
|
344
|
+
)
|
345
|
+
|
330
346
|
if active_project is None:
|
331
347
|
try:
|
332
|
-
|
333
|
-
|
348
|
+
projects = self.list_projects(
|
349
|
+
project_filter_model=ProjectFilter()
|
350
|
+
)
|
351
|
+
except Exception:
|
352
|
+
# There was some failure, we force the user to set the active
|
353
|
+
# project manually
|
334
354
|
logger.warning(
|
335
355
|
"An active project is not set. Please set the active "
|
336
|
-
"project by running `zenml project set "
|
337
|
-
"<project-name>`."
|
356
|
+
"project by running `zenml project set <NAME>`."
|
338
357
|
)
|
339
358
|
else:
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
359
|
+
if len(projects) == 0:
|
360
|
+
logger.warning(
|
361
|
+
"No available projects. Please create a project by "
|
362
|
+
"running `zenml project register <NAME> --set`."
|
363
|
+
)
|
364
|
+
elif len(projects) == 1:
|
365
|
+
active_project = projects.items[0]
|
366
|
+
logger.info(
|
367
|
+
f"Setting the {config_name} active project "
|
368
|
+
f"to '{active_project.name}'."
|
369
|
+
)
|
370
|
+
else:
|
371
|
+
logger.warning(
|
372
|
+
"Multiple projects are available. Please set the "
|
373
|
+
"active project by running `zenml project set <NAME>`."
|
374
|
+
)
|
344
375
|
|
345
376
|
active_stack: StackResponse
|
346
377
|
|
@@ -0,0 +1,51 @@
|
|
1
|
+
"""Add user default project [1f1105204aaf].
|
2
|
+
|
3
|
+
Revision ID: 1f1105204aaf
|
4
|
+
Revises: 0.80.0
|
5
|
+
Create Date: 2025-03-25 11:11:13.480745
|
6
|
+
|
7
|
+
"""
|
8
|
+
|
9
|
+
import sqlalchemy as sa
|
10
|
+
import sqlmodel
|
11
|
+
from alembic import op
|
12
|
+
|
13
|
+
# revision identifiers, used by Alembic.
|
14
|
+
revision = "1f1105204aaf"
|
15
|
+
down_revision = "0.80.0"
|
16
|
+
branch_labels = None
|
17
|
+
depends_on = None
|
18
|
+
|
19
|
+
|
20
|
+
def upgrade() -> None:
|
21
|
+
"""Upgrade database schema and/or data, creating a new revision."""
|
22
|
+
# ### commands auto generated by Alembic - please adjust! ###
|
23
|
+
with op.batch_alter_table("user", schema=None) as batch_op:
|
24
|
+
batch_op.add_column(
|
25
|
+
sa.Column(
|
26
|
+
"default_project_id",
|
27
|
+
sqlmodel.sql.sqltypes.GUID(),
|
28
|
+
nullable=True,
|
29
|
+
)
|
30
|
+
)
|
31
|
+
batch_op.create_foreign_key(
|
32
|
+
"fk_user_default_project_id_project",
|
33
|
+
"project",
|
34
|
+
["default_project_id"],
|
35
|
+
["id"],
|
36
|
+
ondelete="SET NULL",
|
37
|
+
)
|
38
|
+
|
39
|
+
# ### end Alembic commands ###
|
40
|
+
|
41
|
+
|
42
|
+
def downgrade() -> None:
|
43
|
+
"""Downgrade database schema and/or data back to the previous revision."""
|
44
|
+
# ### commands auto generated by Alembic - please adjust! ###
|
45
|
+
with op.batch_alter_table("user", schema=None) as batch_op:
|
46
|
+
batch_op.drop_constraint(
|
47
|
+
"fk_user_default_project_id_project", type_="foreignkey"
|
48
|
+
)
|
49
|
+
batch_op.drop_column("default_project_id")
|
50
|
+
|
51
|
+
# ### end Alembic commands ###
|
@@ -34,6 +34,7 @@ from zenml.models import (
|
|
34
34
|
)
|
35
35
|
from zenml.utils.time_utils import utc_now
|
36
36
|
from zenml.zen_stores.schemas.base_schemas import NamedSchema
|
37
|
+
from zenml.zen_stores.schemas.schema_utils import build_foreign_key_field
|
37
38
|
|
38
39
|
if TYPE_CHECKING:
|
39
40
|
from zenml.zen_stores.schemas import (
|
@@ -83,6 +84,15 @@ class UserSchema(NamedSchema, table=True):
|
|
83
84
|
is_admin: bool = Field(default=False)
|
84
85
|
user_metadata: Optional[str] = Field(nullable=True)
|
85
86
|
|
87
|
+
default_project_id: Optional[UUID] = build_foreign_key_field(
|
88
|
+
source=__tablename__,
|
89
|
+
target="project",
|
90
|
+
source_column="default_project_id",
|
91
|
+
target_column="id",
|
92
|
+
ondelete="SET NULL",
|
93
|
+
nullable=True,
|
94
|
+
)
|
95
|
+
|
86
96
|
stacks: List["StackSchema"] = Relationship(back_populates="user")
|
87
97
|
components: List["StackComponentSchema"] = Relationship(
|
88
98
|
back_populates="user",
|
@@ -299,6 +309,7 @@ class UserSchema(NamedSchema, table=True):
|
|
299
309
|
created=self.created,
|
300
310
|
updated=self.updated,
|
301
311
|
is_admin=self.is_admin,
|
312
|
+
default_project_id=self.default_project_id,
|
302
313
|
),
|
303
314
|
metadata=metadata,
|
304
315
|
)
|
{zenml_nightly-0.80.0.dev20250325.dist-info → zenml_nightly-0.80.0.dev20250327.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=aOovWdLqRIV4qVkeYqC1inlhULjhqv_F5RCcFDdaXWc,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
|
@@ -42,10 +42,10 @@ zenml/cli/login.py,sha256=-tPuTaWctRDkWZOcY4Af2uens6_oEWFkehl8ITeKFHk,38836
|
|
42
42
|
zenml/cli/model.py,sha256=7lmeMLwD3BIWaw_P3WBFRe42Twfvb11K67p_xmvRWH0,22817
|
43
43
|
zenml/cli/model_registry.py,sha256=zzxWXXFhKu2B1Wp0u7prKVnN1ftM-JdGdQwlD-5G-QM,20786
|
44
44
|
zenml/cli/pipeline.py,sha256=Vlz1OgGb1Ep-4Ekgd-Wz5SmieWigfx56i8wA5BGl228,19222
|
45
|
-
zenml/cli/project.py,sha256=
|
45
|
+
zenml/cli/project.py,sha256=MD0HNHc5HSOYvG-mMNJGvDXv0DlGCZsnSDBzwEhQo9s,6407
|
46
46
|
zenml/cli/secret.py,sha256=zwt07v0xoIf_dLf-qY5CFdbKepBEuwmXD2HIMcLe_xU,20164
|
47
47
|
zenml/cli/served_model.py,sha256=3w1UcAbg6Geu37fr7ej1_81GBCt3fF7j3Ge799YE4Mc,14974
|
48
|
-
zenml/cli/server.py,sha256=
|
48
|
+
zenml/cli/server.py,sha256=EmElo8MlPujj15waddSN7wb7M7vu0HCfkIFgILGLL6Q,26130
|
49
49
|
zenml/cli/service_accounts.py,sha256=DkSrBroYvQ3zNDHVYbY9IxqmbN7f8wGsAmt0Wyjq1FE,17766
|
50
50
|
zenml/cli/service_connectors.py,sha256=ZGo1X3UwoHZ2BEFVev216Vfaf9wBEb0PKduwtX3mnk4,74332
|
51
51
|
zenml/cli/stack.py,sha256=J5FzZWOrn9RLoJ6WjsxDl75pcTrBMiPOJeQj_lNix6U,67236
|
@@ -55,7 +55,7 @@ zenml/cli/text_utils.py,sha256=bY1GIjoULt1cW2FyrPlMoAXNS2R7cSOjDFEZQqrpVQ8,3553
|
|
55
55
|
zenml/cli/user_management.py,sha256=sNnhaUxH-cHecbZBR1L0mEU0TnLNZHzI6ZBCUSQa7OY,13078
|
56
56
|
zenml/cli/utils.py,sha256=6Bv2-gqkHC8DdUT4b_HL6pgGMErY8lwjuJb-eHgPTJA,86383
|
57
57
|
zenml/cli/version.py,sha256=nm1iSU_1V6-MUwpMKeXcwFhLYGUMLswvQL67cEuCpxA,3635
|
58
|
-
zenml/client.py,sha256=
|
58
|
+
zenml/client.py,sha256=l8nHsajF_Ctn3ne4unrn7OHW-VG4OKOKObt-POYFZzE,292402
|
59
59
|
zenml/client_lazy_loader.py,sha256=MOBgS1ITYqGvPUnWQ6edn9s8Hr_72YfWbwEIfHKUr9g,7104
|
60
60
|
zenml/code_repositories/__init__.py,sha256=W5bDfzAG8OXIKZSV1L-VHuzMcSCYa9qzTdPb3jqfyYw,920
|
61
61
|
zenml/code_repositories/base_code_repository.py,sha256=Id6VjbUu8N3ZpNvBGhOgbahtoMiCAtYXed3G7YQ_iAc,5225
|
@@ -68,7 +68,7 @@ zenml/config/build_configuration.py,sha256=Jsng7ebpeaRbzXlbszU-uYkaVihgQ4OrD839y
|
|
68
68
|
zenml/config/compiler.py,sha256=pBRJRAzjHloYShJiknDugbH5FGiit5G1o2IJ2dnE9-E,23318
|
69
69
|
zenml/config/constants.py,sha256=QvSgMwXWxtspcJ45CrFDP1ZY3w6gS3bIhXLOtIDAbZA,713
|
70
70
|
zenml/config/docker_settings.py,sha256=KTUR9FaRn3ivcagzFgpLe4eev8fvd5Wq1oV8wGNMB-g,13322
|
71
|
-
zenml/config/global_config.py,sha256=
|
71
|
+
zenml/config/global_config.py,sha256=3w2PLnbfmu6qUdJ1LIn1cdmylSy7VhB2pG1_sxbOPjQ,29556
|
72
72
|
zenml/config/pipeline_configurations.py,sha256=f6mxkTFCCKhGXSPgNQ2JUdBzfL2m_VYuRxWG-OKx54M,3751
|
73
73
|
zenml/config/pipeline_run_configuration.py,sha256=uWTD4778HcCjDpPSfGmBlVqddxTq4cq1_du5kQIIGBA,2263
|
74
74
|
zenml/config/pipeline_spec.py,sha256=uWpiIfznJvXAiKs1yMIUDT1h1tYEFNO-RDVTYcIv9CE,2821
|
@@ -338,7 +338,7 @@ zenml/integrations/kubernetes/flavors/kubernetes_orchestrator_flavor.py,sha256=0
|
|
338
338
|
zenml/integrations/kubernetes/flavors/kubernetes_step_operator_flavor.py,sha256=ILN-H4cl7z3i4ltb4UBs55wbtIo871b4ib28pYkQoyQ,5605
|
339
339
|
zenml/integrations/kubernetes/orchestrators/__init__.py,sha256=TJID3OTieZBox36WpQpzD0jdVRA_aZVcs_bNtfXS8ik,811
|
340
340
|
zenml/integrations/kubernetes/orchestrators/kube_utils.py,sha256=roAYEGTvjnjCERCbjnN2o4v6kL_2xKI-eFnhiRBs1oY,14759
|
341
|
-
zenml/integrations/kubernetes/orchestrators/kubernetes_orchestrator.py,sha256=
|
341
|
+
zenml/integrations/kubernetes/orchestrators/kubernetes_orchestrator.py,sha256=GsOyxmDW6BUNSowK-vWCVXxsO-P7xROtIB9vmP3l1Kg,24810
|
342
342
|
zenml/integrations/kubernetes/orchestrators/kubernetes_orchestrator_entrypoint.py,sha256=T8r6k9sRBl_0PvsiG-k56gT9uG9VB4YxYrIoiGQZ4IM,7721
|
343
343
|
zenml/integrations/kubernetes/orchestrators/kubernetes_orchestrator_entrypoint_configuration.py,sha256=Y7uGU8eksMluGyXYsf688CwpiXwI_W6WYLscYwRZXRY,2494
|
344
344
|
zenml/integrations/kubernetes/orchestrators/manifest_utils.py,sha256=Owyuz5Iix-QvCnKObC6xhcuQtNG_ik-8Vbdmk13eWfc,12557
|
@@ -662,7 +662,7 @@ zenml/models/v2/core/tag.py,sha256=eS9Xzuay91OURfKfNa_fE1CtGmlmPkFDIr6T_QWFZ34,7
|
|
662
662
|
zenml/models/v2/core/tag_resource.py,sha256=H7CPj9oaUpym8vSkwuYSJ6_rWfHMEKVRedPw2kyxmII,2640
|
663
663
|
zenml/models/v2/core/trigger.py,sha256=L6-pzWPM2HFsfA6-6rM1XeHx4UChZrIY58G6ZG1PA10,12782
|
664
664
|
zenml/models/v2/core/trigger_execution.py,sha256=WMYifA3nFKjVXLhx_cg4yMEjGDGo5a8PkV32CzRFhlc,3377
|
665
|
-
zenml/models/v2/core/user.py,sha256=
|
665
|
+
zenml/models/v2/core/user.py,sha256=Y7Qbe3JSeeovp5x3JOekWu9itX406GB2VHjOvBSNouc,14435
|
666
666
|
zenml/models/v2/misc/__init__.py,sha256=knhroJ2h0uHBCGzAiBBGJEiuhEA3cwI6XYBRIyXdbkQ,613
|
667
667
|
zenml/models/v2/misc/auth_models.py,sha256=j31CQt9qfH20tyCjY0depqbKP0YZEewcgGKrixqBUbg,3688
|
668
668
|
zenml/models/v2/misc/build_item.py,sha256=66Fywatv8bDY86pf0k530fsHTk_L4IkHL6uJL7-6dAo,1938
|
@@ -715,7 +715,7 @@ zenml/secret/schemas/gcp_secret_schema.py,sha256=tDSxPXlfh4BOSICZjfJjUukfzEyBEgx
|
|
715
715
|
zenml/service_connectors/__init__.py,sha256=gIBAVUPBZtdO6JtEBCixy9YG4wZRA1mnaxaGAxi3T1Q,645
|
716
716
|
zenml/service_connectors/docker_service_connector.py,sha256=_6WPqYCcSUf8JPakipbkJRvaN2ghhY7zCr38WCHG0SI,13218
|
717
717
|
zenml/service_connectors/service_connector.py,sha256=rVYXZDVp2XJEYIbhkQW3zEjlgsvxqGN9ZOmmVE_pum4,54977
|
718
|
-
zenml/service_connectors/service_connector_registry.py,sha256=
|
718
|
+
zenml/service_connectors/service_connector_registry.py,sha256=U5MdC9M_RfkHK56AoERB9HtDP4vxk2hDFoZRlWzBA9g,9608
|
719
719
|
zenml/service_connectors/service_connector_utils.py,sha256=25eD-2BDWHmRFwpdV5xCAtM3osgGwBzZcZecYRox6Tk,17958
|
720
720
|
zenml/services/__init__.py,sha256=BhqBztNXLrqN-4FZr24WHP9ujP_M0plt6axQvakh1jQ,2784
|
721
721
|
zenml/services/container/__init__.py,sha256=dFHcmlXgNXjUaCR18oGQJ19-I_6f3UeAUURHjqldjTs,668
|
@@ -1056,7 +1056,7 @@ zenml/zen_server/routers/steps_endpoints.py,sha256=By-9_VKrJeSo6UUqrggDhGKtrnhxi
|
|
1056
1056
|
zenml/zen_server/routers/tag_resource_endpoints.py,sha256=AdmbujrwKK6arnSx2VHpJWbZXnlviGlay7LCov4x9Fc,3203
|
1057
1057
|
zenml/zen_server/routers/tags_endpoints.py,sha256=lRjnMaJOdTnooMHoQYIViKfgu32cMq7rI3Lyeaxq4QI,4467
|
1058
1058
|
zenml/zen_server/routers/triggers_endpoints.py,sha256=5fb0EITa3bs--AtKQRQZ5QswHu4pb37OrG5y0OlnGXE,9983
|
1059
|
-
zenml/zen_server/routers/users_endpoints.py,sha256=
|
1059
|
+
zenml/zen_server/routers/users_endpoints.py,sha256=b1zZRbVJF8MT3XjwAwj7FJ0scplnQuNT4AzmbCU8PcU,24344
|
1060
1060
|
zenml/zen_server/routers/webhook_endpoints.py,sha256=KOJsuykv_TMjL3oEItpC4OWWP75p-OEvVjRSUBd5Mro,3983
|
1061
1061
|
zenml/zen_server/secure_headers.py,sha256=glh6QujnjyeoH1_FK-tAS-105G-qKS_34AqSzqJ6TRc,4182
|
1062
1062
|
zenml/zen_server/template_execution/__init__.py,sha256=79knXLKfegsvVSVSWecpqrepq6iAavTUA4hKuiDk-WE,613
|
@@ -1066,7 +1066,7 @@ zenml/zen_server/template_execution/workload_manager_interface.py,sha256=CL9c7z8
|
|
1066
1066
|
zenml/zen_server/utils.py,sha256=Jc2Q4UBaYG2ruHdsN9JmbOWfWU_eWD9wTBBEgcGAbqg,17439
|
1067
1067
|
zenml/zen_server/zen_server_api.py,sha256=ALyv5096frXXRNySegEtsmkDbHLLqHd402bbQI7RnII,17941
|
1068
1068
|
zenml/zen_stores/__init__.py,sha256=6LTgH6XwDeDxKqVJ1JTfGhmS8II1NLopPloINGmdyI0,691
|
1069
|
-
zenml/zen_stores/base_zen_store.py,sha256=
|
1069
|
+
zenml/zen_stores/base_zen_store.py,sha256=UtclHihv9-YA0vgbznh8Hp7Rpuivw8ZF7J7oPUM-IuY,17290
|
1070
1070
|
zenml/zen_stores/migrations/README.md,sha256=x04jsb6EOP6PBEGMQlDELiqKEham2O-iztAs9AylMFc,4898
|
1071
1071
|
zenml/zen_stores/migrations/__init__.py,sha256=N9CHfdz0AZ6KniQ450VCIV3H0CuWtx83AloYy82woho,657
|
1072
1072
|
zenml/zen_stores/migrations/alembic.py,sha256=JDqx7Md6DxnHtP3xrZG1I0cNv6NyTR0oO3tPRUPaS2I,7455
|
@@ -1173,6 +1173,7 @@ zenml/zen_stores/migrations/versions/1ac1b9c04da1_make_secrets_values_optional.p
|
|
1173
1173
|
zenml/zen_stores/migrations/versions/1cb6477f72d6_move_artifact_save_type.py,sha256=sv2-qjqwVifEiJr1IRERmqBVPaOB1BEkJLyOfJXOyHk,3151
|
1174
1174
|
zenml/zen_stores/migrations/versions/1d74e596abb8_add_run_once_start_time_to_schedule.py,sha256=GIGHE1qkwjske0vtc7XsVBRlIr7A2XKf1-tsfxrov94,1032
|
1175
1175
|
zenml/zen_stores/migrations/versions/1d8f30c54477_migrate_to_new_.py,sha256=ICZLr5MsjGqOnMWwG8W6ixKq3OX2rfs3XkXRzHhSUnA,4200
|
1176
|
+
zenml/zen_stores/migrations/versions/1f1105204aaf_add_user_default_project.py,sha256=vN-MvyhO-W9D7NVcwaU6_p0JA3MVdl2l-yrntDcnahM,1427
|
1176
1177
|
zenml/zen_stores/migrations/versions/1f9d1cd00b90_add_unique_name_constraints.py,sha256=NSjB4G94c7akAAKT3PpBVKvJHuGMWKob60lPxF65LoA,8044
|
1177
1178
|
zenml/zen_stores/migrations/versions/248dfd320b68_update_size_of_flavor_config_schema.py,sha256=rdHrVpqtRtVPzOUawWXx7SrBfv8tog-uXJQr_k4r4_0,1229
|
1178
1179
|
zenml/zen_stores/migrations/versions/25155145c545_separate_actions_and_triggers.py,sha256=T1A3e0YAtSIdGFmJUjUSfp6f8v82T91XHT-kziui4N4,7588
|
@@ -1294,7 +1295,7 @@ zenml/zen_stores/schemas/stack_schemas.py,sha256=SkMspxsnR420KU4mZlulPbEOR4DMSRy
|
|
1294
1295
|
zenml/zen_stores/schemas/step_run_schemas.py,sha256=NuJtCXZ_Zacz4_X7GZ5PQ-fLpzVBhnhScGx2fBqAlDg,16333
|
1295
1296
|
zenml/zen_stores/schemas/tag_schemas.py,sha256=GMKdyT5pZb977vscOW41N2beVt-IHcELSiSSIBHqlUI,6377
|
1296
1297
|
zenml/zen_stores/schemas/trigger_schemas.py,sha256=IOfd6enpAr9mwN5p4KbA2jvQEHlMEUXDXAMqIULS4lc,10711
|
1297
|
-
zenml/zen_stores/schemas/user_schemas.py,sha256=
|
1298
|
+
zenml/zen_stores/schemas/user_schemas.py,sha256=wLSHtfjjrYBWnX_PXv5KPz_DRdheTxZVjcgBe-cP__c,11497
|
1298
1299
|
zenml/zen_stores/schemas/utils.py,sha256=82-LQj1EV4jp69kKE2GolQw_zTDBvAkyA4cHDaSIj6U,4160
|
1299
1300
|
zenml/zen_stores/secrets_stores/__init__.py,sha256=VGMVerFv3xUWxnp5X_bHyQJwGCeN7BTovUDwho_w-4w,651
|
1300
1301
|
zenml/zen_stores/secrets_stores/aws_secrets_store.py,sha256=o2kftfG0nr6oTodEDHWYvSK6zKbs1WGfqgMd5bJ4k0k,13799
|
@@ -1308,8 +1309,8 @@ zenml/zen_stores/secrets_stores/sql_secrets_store.py,sha256=nEO0bAPlULBLxLVk-UTR
|
|
1308
1309
|
zenml/zen_stores/sql_zen_store.py,sha256=RmcpUHnSlPOMLNZ9StPxi_9FPqB1HgfiK_Humst9sns,440431
|
1309
1310
|
zenml/zen_stores/template_utils.py,sha256=GWBP5QEOyvhzndS_MLPmvh28sQaOPpPoZFXCIX9CRL4,9065
|
1310
1311
|
zenml/zen_stores/zen_store_interface.py,sha256=fF_uL_FplnvGvM5o3jOQ8i1zHXhuhKLL2n4nvIKSR7E,92090
|
1311
|
-
zenml_nightly-0.80.0.
|
1312
|
-
zenml_nightly-0.80.0.
|
1313
|
-
zenml_nightly-0.80.0.
|
1314
|
-
zenml_nightly-0.80.0.
|
1315
|
-
zenml_nightly-0.80.0.
|
1312
|
+
zenml_nightly-0.80.0.dev20250327.dist-info/LICENSE,sha256=wbnfEnXnafPbqwANHkV6LUsPKOtdpsd-SNw37rogLtc,11359
|
1313
|
+
zenml_nightly-0.80.0.dev20250327.dist-info/METADATA,sha256=riu8q-gWcij4HNT2KkKdnB_-vTAiJyuuN66-l53C3-4,24227
|
1314
|
+
zenml_nightly-0.80.0.dev20250327.dist-info/WHEEL,sha256=XbeZDeTWKc1w7CSIyre5aMDU_-PohRwTQceYnisIYYY,88
|
1315
|
+
zenml_nightly-0.80.0.dev20250327.dist-info/entry_points.txt,sha256=QK3ETQE0YswAM2mWypNMOv8TLtr7EjnqAFq1br_jEFE,43
|
1316
|
+
zenml_nightly-0.80.0.dev20250327.dist-info/RECORD,,
|
{zenml_nightly-0.80.0.dev20250325.dist-info → zenml_nightly-0.80.0.dev20250327.dist-info}/LICENSE
RENAMED
File without changes
|
{zenml_nightly-0.80.0.dev20250325.dist-info → zenml_nightly-0.80.0.dev20250327.dist-info}/WHEEL
RENAMED
File without changes
|
File without changes
|