zenml-nightly 0.75.0.dev20250312__py3-none-any.whl → 0.75.0.dev20250314__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/__init__.py +2 -0
- zenml/analytics/context.py +7 -0
- zenml/analytics/enums.py +2 -2
- zenml/artifacts/utils.py +2 -4
- zenml/cli/__init__.py +8 -9
- zenml/cli/base.py +2 -2
- zenml/cli/code_repository.py +1 -1
- zenml/cli/login.py +6 -0
- zenml/cli/model.py +7 -15
- zenml/cli/pipeline.py +3 -3
- zenml/cli/project.py +172 -0
- zenml/cli/secret.py +47 -44
- zenml/cli/service_accounts.py +0 -1
- zenml/cli/service_connectors.py +15 -17
- zenml/cli/stack.py +0 -3
- zenml/cli/stack_components.py +2 -2
- zenml/cli/tag.py +3 -5
- zenml/cli/utils.py +25 -23
- zenml/client.py +749 -475
- zenml/config/global_config.py +48 -37
- zenml/config/pipeline_configurations.py +3 -2
- zenml/config/pipeline_run_configuration.py +2 -1
- zenml/config/secret_reference_mixin.py +1 -1
- zenml/constants.py +6 -6
- zenml/enums.py +0 -7
- zenml/event_hub/event_hub.py +3 -1
- zenml/exceptions.py +0 -24
- zenml/integrations/aws/orchestrators/sagemaker_orchestrator.py +5 -3
- zenml/integrations/bitbucket/plugins/event_sources/bitbucket_webhook_event_source.py +1 -4
- zenml/integrations/gcp/service_connectors/gcp_service_connector.py +7 -6
- zenml/integrations/github/plugins/event_sources/github_webhook_event_source.py +1 -4
- zenml/integrations/mlflow/steps/mlflow_registry.py +3 -3
- zenml/integrations/seldon/model_deployers/seldon_model_deployer.py +1 -1
- zenml/integrations/wandb/__init__.py +1 -1
- zenml/integrations/wandb/experiment_trackers/wandb_experiment_tracker.py +29 -9
- zenml/integrations/wandb/flavors/wandb_experiment_tracker_flavor.py +5 -3
- zenml/model/model.py +10 -10
- zenml/model_registries/base_model_registry.py +1 -1
- zenml/models/__init__.py +45 -28
- zenml/models/v2/base/base.py +0 -5
- zenml/models/v2/base/filter.py +2 -2
- zenml/models/v2/base/scoped.py +135 -156
- zenml/models/v2/core/action.py +12 -12
- zenml/models/v2/core/api_key.py +1 -1
- zenml/models/v2/core/artifact.py +31 -18
- zenml/models/v2/core/artifact_version.py +57 -40
- zenml/models/v2/core/code_repository.py +12 -12
- zenml/models/v2/core/component.py +22 -33
- zenml/models/v2/core/device.py +3 -2
- zenml/models/v2/core/event_source.py +14 -14
- zenml/models/v2/core/flavor.py +19 -47
- zenml/models/v2/core/logs.py +1 -2
- zenml/models/v2/core/model.py +23 -20
- zenml/models/v2/core/model_version.py +51 -42
- zenml/models/v2/core/pipeline.py +16 -16
- zenml/models/v2/core/pipeline_build.py +14 -14
- zenml/models/v2/core/pipeline_deployment.py +12 -14
- zenml/models/v2/core/pipeline_run.py +21 -29
- zenml/models/v2/core/project.py +203 -0
- zenml/models/v2/core/run_metadata.py +2 -2
- zenml/models/v2/core/run_template.py +16 -17
- zenml/models/v2/core/schedule.py +12 -21
- zenml/models/v2/core/secret.py +94 -128
- zenml/models/v2/core/server_settings.py +2 -2
- zenml/models/v2/core/service.py +57 -26
- zenml/models/v2/core/service_connector.py +14 -16
- zenml/models/v2/core/stack.py +24 -26
- zenml/models/v2/core/step_run.py +16 -28
- zenml/models/v2/core/tag.py +41 -15
- zenml/models/v2/core/trigger.py +13 -13
- zenml/models/v2/core/trigger_execution.py +2 -2
- zenml/models/v2/core/user.py +2 -2
- zenml/models/v2/misc/statistics.py +45 -0
- zenml/models/v2/misc/tag.py +27 -0
- zenml/orchestrators/cache_utils.py +7 -7
- zenml/orchestrators/input_utils.py +1 -0
- zenml/orchestrators/step_launcher.py +1 -2
- zenml/orchestrators/step_run_utils.py +2 -4
- zenml/orchestrators/step_runner.py +10 -1
- zenml/orchestrators/utils.py +4 -4
- zenml/pipelines/build_utils.py +2 -4
- zenml/pipelines/pipeline_decorator.py +3 -2
- zenml/pipelines/pipeline_definition.py +8 -9
- zenml/pipelines/run_utils.py +4 -4
- zenml/service_connectors/service_connector.py +0 -10
- zenml/service_connectors/service_connector_utils.py +0 -2
- zenml/stack/authentication_mixin.py +1 -1
- zenml/stack/flavor.py +3 -14
- zenml/stack/stack.py +0 -1
- zenml/stack/stack_component.py +1 -5
- zenml/steps/base_step.py +10 -2
- zenml/steps/step_context.py +19 -0
- zenml/utils/string_utils.py +1 -1
- zenml/utils/tag_utils.py +642 -0
- zenml/zen_server/cloud_utils.py +21 -0
- zenml/zen_server/exceptions.py +0 -6
- zenml/zen_server/rbac/endpoint_utils.py +134 -46
- zenml/zen_server/rbac/models.py +65 -3
- zenml/zen_server/rbac/rbac_interface.py +9 -0
- zenml/zen_server/rbac/rbac_sql_zen_store.py +15 -7
- zenml/zen_server/rbac/utils.py +155 -30
- zenml/zen_server/rbac/zenml_cloud_rbac.py +39 -11
- zenml/zen_server/routers/actions_endpoints.py +3 -5
- zenml/zen_server/routers/artifact_endpoint.py +0 -5
- zenml/zen_server/routers/artifact_version_endpoints.py +15 -9
- zenml/zen_server/routers/auth_endpoints.py +22 -7
- zenml/zen_server/routers/code_repositories_endpoints.py +54 -3
- zenml/zen_server/routers/devices_endpoints.py +0 -4
- zenml/zen_server/routers/event_source_endpoints.py +0 -5
- zenml/zen_server/routers/flavors_endpoints.py +0 -5
- zenml/zen_server/routers/logs_endpoints.py +0 -1
- zenml/zen_server/routers/model_versions_endpoints.py +100 -23
- zenml/zen_server/routers/models_endpoints.py +50 -69
- zenml/zen_server/routers/pipeline_builds_endpoints.py +55 -3
- zenml/zen_server/routers/pipeline_deployments_endpoints.py +56 -4
- zenml/zen_server/routers/pipelines_endpoints.py +70 -3
- zenml/zen_server/routers/plugin_endpoints.py +0 -1
- zenml/zen_server/routers/projects_endpoints.py +283 -0
- zenml/zen_server/routers/run_metadata_endpoints.py +97 -0
- zenml/zen_server/routers/run_templates_endpoints.py +64 -3
- zenml/zen_server/routers/runs_endpoints.py +58 -8
- zenml/zen_server/routers/schedule_endpoints.py +67 -6
- zenml/zen_server/routers/secrets_endpoints.py +38 -4
- zenml/zen_server/routers/server_endpoints.py +53 -1
- zenml/zen_server/routers/service_accounts_endpoints.py +14 -15
- zenml/zen_server/routers/service_connectors_endpoints.py +94 -14
- zenml/zen_server/routers/service_endpoints.py +18 -7
- zenml/zen_server/routers/stack_components_endpoints.py +66 -7
- zenml/zen_server/routers/stacks_endpoints.py +95 -6
- zenml/zen_server/routers/steps_endpoints.py +17 -11
- zenml/zen_server/routers/tag_resource_endpoints.py +115 -0
- zenml/zen_server/routers/tags_endpoints.py +6 -17
- zenml/zen_server/routers/triggers_endpoints.py +5 -8
- zenml/zen_server/routers/users_endpoints.py +9 -12
- zenml/zen_server/template_execution/utils.py +8 -7
- zenml/zen_server/utils.py +21 -0
- zenml/zen_server/zen_server_api.py +7 -2
- zenml/zen_stores/base_zen_store.py +50 -69
- zenml/zen_stores/migrations/versions/12eff0206201_rename_workspace_to_project.py +768 -0
- zenml/zen_stores/migrations/versions/1cb6477f72d6_move_artifact_save_type.py +20 -10
- zenml/zen_stores/migrations/versions/1f9d1cd00b90_add_unique_name_constraints.py +231 -0
- zenml/zen_stores/migrations/versions/288f4fb6e112_make_tags_user_scoped.py +74 -0
- zenml/zen_stores/migrations/versions/2e695a26fe7a_add_user_default_workspace.py +45 -0
- zenml/zen_stores/migrations/versions/3b1776345020_remove_workspace_from_globals.py +81 -0
- zenml/zen_stores/migrations/versions/41b28cae31ce_make_artifacts_workspace_scoped.py +136 -0
- zenml/zen_stores/migrations/versions/9e7bf0970266_adding_exclusive_attribute_to_tags.py +47 -0
- zenml/zen_stores/migrations/versions/b557b2871693_update_step_run_input_types.py +8 -4
- zenml/zen_stores/migrations/versions/cbc6acd71f92_add_workspace_display_name.py +58 -0
- zenml/zen_stores/migrations/versions/cc269488e5a9_separate_run_metadata.py +12 -6
- zenml/zen_stores/migrations/versions/f1d723fd723b_add_secret_private_attr.py +61 -0
- zenml/zen_stores/migrations/versions/f76a368a25a5_add_stack_description.py +35 -0
- zenml/zen_stores/rest_zen_store.py +223 -230
- zenml/zen_stores/schemas/__init__.py +2 -2
- zenml/zen_stores/schemas/action_schemas.py +15 -8
- zenml/zen_stores/schemas/api_key_schemas.py +8 -1
- zenml/zen_stores/schemas/artifact_schemas.py +35 -10
- zenml/zen_stores/schemas/code_repository_schemas.py +22 -17
- zenml/zen_stores/schemas/component_schemas.py +9 -14
- zenml/zen_stores/schemas/event_source_schemas.py +15 -8
- zenml/zen_stores/schemas/flavor_schemas.py +14 -20
- zenml/zen_stores/schemas/model_schemas.py +18 -17
- zenml/zen_stores/schemas/pipeline_build_schemas.py +7 -7
- zenml/zen_stores/schemas/pipeline_deployment_schemas.py +10 -8
- zenml/zen_stores/schemas/pipeline_run_schemas.py +9 -12
- zenml/zen_stores/schemas/pipeline_schemas.py +9 -9
- zenml/zen_stores/schemas/{workspace_schemas.py → project_schemas.py} +53 -65
- zenml/zen_stores/schemas/run_metadata_schemas.py +5 -5
- zenml/zen_stores/schemas/run_template_schemas.py +17 -13
- zenml/zen_stores/schemas/schedule_schema.py +16 -21
- zenml/zen_stores/schemas/secret_schemas.py +15 -25
- zenml/zen_stores/schemas/service_connector_schemas.py +8 -17
- zenml/zen_stores/schemas/service_schemas.py +7 -8
- zenml/zen_stores/schemas/stack_schemas.py +12 -15
- zenml/zen_stores/schemas/step_run_schemas.py +14 -15
- zenml/zen_stores/schemas/tag_schemas.py +30 -2
- zenml/zen_stores/schemas/trigger_schemas.py +15 -8
- zenml/zen_stores/schemas/user_schemas.py +12 -2
- zenml/zen_stores/schemas/utils.py +16 -0
- zenml/zen_stores/secrets_stores/service_connector_secrets_store.py +0 -3
- zenml/zen_stores/sql_zen_store.py +2984 -2369
- zenml/zen_stores/template_utils.py +1 -1
- zenml/zen_stores/zen_store_interface.py +136 -126
- {zenml_nightly-0.75.0.dev20250312.dist-info → zenml_nightly-0.75.0.dev20250314.dist-info}/METADATA +1 -1
- {zenml_nightly-0.75.0.dev20250312.dist-info → zenml_nightly-0.75.0.dev20250314.dist-info}/RECORD +188 -173
- zenml/cli/workspace.py +0 -86
- zenml/models/v2/core/workspace.py +0 -131
- zenml/zen_server/routers/workspaces_endpoints.py +0 -1469
- {zenml_nightly-0.75.0.dev20250312.dist-info → zenml_nightly-0.75.0.dev20250314.dist-info}/LICENSE +0 -0
- {zenml_nightly-0.75.0.dev20250312.dist-info → zenml_nightly-0.75.0.dev20250314.dist-info}/WHEEL +0 -0
- {zenml_nightly-0.75.0.dev20250312.dist-info → zenml_nightly-0.75.0.dev20250314.dist-info}/entry_points.txt +0 -0
zenml/models/__init__.py
CHANGED
@@ -34,13 +34,13 @@ from zenml.models.v2.base.scoped import (
|
|
34
34
|
UserScopedResponse,
|
35
35
|
UserScopedResponseBody,
|
36
36
|
UserScopedResponseMetadata,
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
37
|
+
ProjectScopedRequest,
|
38
|
+
ProjectScopedFilter,
|
39
|
+
ProjectScopedResponse,
|
40
|
+
ProjectScopedResponseBody,
|
41
|
+
ProjectScopedResponseMetadata,
|
42
|
+
ProjectScopedResponseResources,
|
43
|
+
ProjectScopedFilter,
|
44
44
|
)
|
45
45
|
from zenml.models.v2.base.filter import (
|
46
46
|
BaseFilter,
|
@@ -133,7 +133,8 @@ from zenml.models.v2.core.component import (
|
|
133
133
|
ComponentResponse,
|
134
134
|
ComponentResponseBody,
|
135
135
|
ComponentResponseMetadata,
|
136
|
-
ComponentResponseResources
|
136
|
+
ComponentResponseResources,
|
137
|
+
DefaultComponentRequest,
|
137
138
|
)
|
138
139
|
from zenml.models.v2.core.event_source_flavor import (
|
139
140
|
EventSourceFlavorResponse,
|
@@ -275,6 +276,7 @@ from zenml.models.v2.core.service_connector import (
|
|
275
276
|
ServiceConnectorResponseMetadata,
|
276
277
|
)
|
277
278
|
from zenml.models.v2.core.stack import (
|
279
|
+
DefaultStackRequest,
|
278
280
|
StackRequest,
|
279
281
|
StackUpdate,
|
280
282
|
StackFilter,
|
@@ -282,6 +284,10 @@ from zenml.models.v2.core.stack import (
|
|
282
284
|
StackResponseBody,
|
283
285
|
StackResponseMetadata,
|
284
286
|
)
|
287
|
+
from zenml.models.v2.misc.statistics import (
|
288
|
+
ProjectStatistics,
|
289
|
+
ServerStatistics,
|
290
|
+
)
|
285
291
|
from zenml.models.v2.core.step_run import (
|
286
292
|
StepRunRequest,
|
287
293
|
StepRunUpdate,
|
@@ -295,6 +301,7 @@ from zenml.models.v2.core.tag import (
|
|
295
301
|
TagFilter,
|
296
302
|
TagResponse,
|
297
303
|
TagResponseBody,
|
304
|
+
TagResponseMetadata,
|
298
305
|
TagRequest,
|
299
306
|
TagUpdate,
|
300
307
|
)
|
@@ -311,13 +318,13 @@ from zenml.models.v2.core.user import (
|
|
311
318
|
UserResponseBody,
|
312
319
|
UserResponseMetadata,
|
313
320
|
)
|
314
|
-
from zenml.models.v2.core.
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
+
from zenml.models.v2.core.project import (
|
322
|
+
ProjectRequest,
|
323
|
+
ProjectUpdate,
|
324
|
+
ProjectFilter,
|
325
|
+
ProjectResponse,
|
326
|
+
ProjectResponseBody,
|
327
|
+
ProjectResponseMetadata,
|
321
328
|
)
|
322
329
|
|
323
330
|
# V2 Misc
|
@@ -395,6 +402,9 @@ from zenml.models.v2.misc.stack_deployment import (
|
|
395
402
|
StackDeploymentConfig,
|
396
403
|
StackDeploymentInfo,
|
397
404
|
)
|
405
|
+
from zenml.models.v2.misc.tag import (
|
406
|
+
TagResource,
|
407
|
+
)
|
398
408
|
from zenml.models.v2.misc.info_models import (
|
399
409
|
ComponentInfo,
|
400
410
|
ServiceConnectorInfo,
|
@@ -440,6 +450,7 @@ PipelineDeploymentRequest.model_rebuild()
|
|
440
450
|
PipelineDeploymentResponseBody.model_rebuild()
|
441
451
|
PipelineDeploymentResponseMetadata.model_rebuild()
|
442
452
|
PipelineDeploymentResponseResources.model_rebuild()
|
453
|
+
PipelineRunRequest.model_rebuild()
|
443
454
|
PipelineRunResponseBody.model_rebuild()
|
444
455
|
PipelineRunResponseMetadata.model_rebuild()
|
445
456
|
PipelineRunResponseResources.model_rebuild()
|
@@ -492,13 +503,13 @@ __all__ = [
|
|
492
503
|
"UserScopedResponse",
|
493
504
|
"UserScopedResponseBody",
|
494
505
|
"UserScopedResponseMetadata",
|
495
|
-
"
|
496
|
-
"
|
497
|
-
"
|
498
|
-
"
|
499
|
-
"
|
500
|
-
"
|
501
|
-
"
|
506
|
+
"ProjectScopedRequest",
|
507
|
+
"ProjectScopedFilter",
|
508
|
+
"ProjectScopedResponse",
|
509
|
+
"ProjectScopedResponseBody",
|
510
|
+
"ProjectScopedResponseMetadata",
|
511
|
+
"ProjectScopedResponseResources",
|
512
|
+
"ProjectScopedFilter",
|
502
513
|
"BaseFilter",
|
503
514
|
"StrFilter",
|
504
515
|
"BoolFilter",
|
@@ -562,6 +573,8 @@ __all__ = [
|
|
562
573
|
"ComponentResponseBody",
|
563
574
|
"ComponentResponseMetadata",
|
564
575
|
"ComponentResponseResources",
|
576
|
+
"DefaultComponentRequest",
|
577
|
+
"DefaultStackRequest",
|
565
578
|
"EventSourceFlavorResponse",
|
566
579
|
"EventSourceFlavorResponseBody",
|
567
580
|
"EventSourceFlavorResponseMetadata",
|
@@ -695,6 +708,7 @@ __all__ = [
|
|
695
708
|
"TagResourceRequest",
|
696
709
|
"TagResponse",
|
697
710
|
"TagResponseBody",
|
711
|
+
"TagResponseMetadata",
|
698
712
|
"TagRequest",
|
699
713
|
"TagUpdate",
|
700
714
|
"TriggerResponse",
|
@@ -723,12 +737,12 @@ __all__ = [
|
|
723
737
|
"UserResponse",
|
724
738
|
"UserResponseBody",
|
725
739
|
"UserResponseMetadata",
|
726
|
-
"
|
727
|
-
"
|
728
|
-
"
|
729
|
-
"
|
730
|
-
"
|
731
|
-
"
|
740
|
+
"ProjectRequest",
|
741
|
+
"ProjectUpdate",
|
742
|
+
"ProjectFilter",
|
743
|
+
"ProjectResponse",
|
744
|
+
"ProjectResponseBody",
|
745
|
+
"ProjectResponseMetadata",
|
732
746
|
# V2 Misc
|
733
747
|
"AuthenticationMethodModel",
|
734
748
|
"DeployedStack",
|
@@ -745,6 +759,7 @@ __all__ = [
|
|
745
759
|
"ServerModel",
|
746
760
|
"ServerDatabaseType",
|
747
761
|
"ServerDeploymentType",
|
762
|
+
"ServerStatistics",
|
748
763
|
"StackDeploymentConfig",
|
749
764
|
"StackDeploymentInfo",
|
750
765
|
"OAuthDeviceAuthorizationRequest",
|
@@ -757,7 +772,9 @@ __all__ = [
|
|
757
772
|
"ComponentInfo",
|
758
773
|
"ServiceConnectorInfo",
|
759
774
|
"ServiceConnectorResourcesInfo",
|
775
|
+
"TagResource",
|
760
776
|
"ResourcesInfo",
|
761
777
|
"RunMetadataEntry",
|
762
778
|
"RunMetadataResource",
|
779
|
+
"ProjectStatistics",
|
763
780
|
]
|
zenml/models/v2/base/base.py
CHANGED
@@ -65,11 +65,6 @@ class BaseUpdate(BaseZenModel):
|
|
65
65
|
Used as a base class for all update models.
|
66
66
|
"""
|
67
67
|
|
68
|
-
model_config = ConfigDict(
|
69
|
-
# Ignore extras on all update models.
|
70
|
-
extra="ignore",
|
71
|
-
)
|
72
|
-
|
73
68
|
|
74
69
|
# -------------------- Response Model --------------------
|
75
70
|
|
zenml/models/v2/base/filter.py
CHANGED
@@ -421,7 +421,7 @@ class BaseFilter(BaseModel):
|
|
421
421
|
```
|
422
422
|
ResourceListModel(
|
423
423
|
name="contains:default",
|
424
|
-
|
424
|
+
project="default"
|
425
425
|
count_steps="gte:5"
|
426
426
|
sort_by="created",
|
427
427
|
page=2,
|
@@ -716,7 +716,7 @@ class BaseFilter(BaseModel):
|
|
716
716
|
value: The filter value.
|
717
717
|
table: The table to filter.
|
718
718
|
additional_columns: Additional table columns that should also
|
719
|
-
|
719
|
+
filter for the given value as part of the or condition.
|
720
720
|
|
721
721
|
Returns:
|
722
722
|
The query conditions.
|
zenml/models/v2/base/scoped.py
CHANGED
@@ -27,8 +27,9 @@ from typing import (
|
|
27
27
|
)
|
28
28
|
from uuid import UUID
|
29
29
|
|
30
|
-
from pydantic import Field
|
30
|
+
from pydantic import Field, model_validator
|
31
31
|
|
32
|
+
from zenml.logger import get_logger
|
32
33
|
from zenml.models.v2.base.base import (
|
33
34
|
BaseDatedResponseBody,
|
34
35
|
BaseIdentifiedResponse,
|
@@ -41,12 +42,15 @@ from zenml.models.v2.base.filter import AnyQuery, BaseFilter
|
|
41
42
|
if TYPE_CHECKING:
|
42
43
|
from sqlalchemy.sql.elements import ColumnElement
|
43
44
|
|
45
|
+
from zenml.models.v2.core.project import ProjectResponse
|
44
46
|
from zenml.models.v2.core.user import UserResponse
|
45
|
-
from zenml.models.v2.core.workspace import WorkspaceResponse
|
46
47
|
from zenml.zen_stores.schemas import BaseSchema
|
47
48
|
|
48
49
|
AnySchema = TypeVar("AnySchema", bound=BaseSchema)
|
49
50
|
|
51
|
+
logger = get_logger(__name__)
|
52
|
+
|
53
|
+
|
50
54
|
# ---------------------- Request Models ----------------------
|
51
55
|
|
52
56
|
|
@@ -56,7 +60,14 @@ class UserScopedRequest(BaseRequest):
|
|
56
60
|
Used as a base class for all domain models that are "owned" by a user.
|
57
61
|
"""
|
58
62
|
|
59
|
-
user: UUID = Field(
|
63
|
+
user: Optional[UUID] = Field(
|
64
|
+
default=None,
|
65
|
+
title="The id of the user that created this resource. Set "
|
66
|
+
"automatically by the server.",
|
67
|
+
# This field is set automatically by the server, so the client doesn't
|
68
|
+
# need to set it and it will not be serialized.
|
69
|
+
exclude=True,
|
70
|
+
)
|
60
71
|
|
61
72
|
def get_analytics_metadata(self) -> Dict[str, Any]:
|
62
73
|
"""Fetches the analytics metadata for user scoped models.
|
@@ -69,24 +80,22 @@ class UserScopedRequest(BaseRequest):
|
|
69
80
|
return metadata
|
70
81
|
|
71
82
|
|
72
|
-
class
|
73
|
-
"""Base
|
83
|
+
class ProjectScopedRequest(UserScopedRequest):
|
84
|
+
"""Base project-scoped request domain model.
|
74
85
|
|
75
|
-
Used as a base class for all domain models that are
|
86
|
+
Used as a base class for all domain models that are project-scoped.
|
76
87
|
"""
|
77
88
|
|
78
|
-
|
79
|
-
title="The workspace to which this resource belongs."
|
80
|
-
)
|
89
|
+
project: UUID = Field(title="The project to which this resource belongs.")
|
81
90
|
|
82
91
|
def get_analytics_metadata(self) -> Dict[str, Any]:
|
83
|
-
"""Fetches the analytics metadata for
|
92
|
+
"""Fetches the analytics metadata for project scoped models.
|
84
93
|
|
85
94
|
Returns:
|
86
95
|
The analytics metadata.
|
87
96
|
"""
|
88
97
|
metadata = super().get_analytics_metadata()
|
89
|
-
metadata["
|
98
|
+
metadata["project_id"] = self.project
|
90
99
|
return metadata
|
91
100
|
|
92
101
|
|
@@ -157,7 +166,6 @@ class UserScopedFilter(BaseFilter):
|
|
157
166
|
]
|
158
167
|
CLI_EXCLUDE_FIELDS: ClassVar[List[str]] = [
|
159
168
|
*BaseFilter.CLI_EXCLUDE_FIELDS,
|
160
|
-
"user_id",
|
161
169
|
"scope_user",
|
162
170
|
]
|
163
171
|
CUSTOM_SORTING_OPTIONS: ClassVar[List[str]] = [
|
@@ -169,14 +177,10 @@ class UserScopedFilter(BaseFilter):
|
|
169
177
|
default=None,
|
170
178
|
description="The user to scope this query to.",
|
171
179
|
)
|
172
|
-
user_id: Optional[Union[UUID, str]] = Field(
|
173
|
-
default=None,
|
174
|
-
description="UUID of the user that created the entity.",
|
175
|
-
union_mode="left_to_right",
|
176
|
-
)
|
177
180
|
user: Optional[Union[UUID, str]] = Field(
|
178
181
|
default=None,
|
179
182
|
description="Name/ID of the user that created the entity.",
|
183
|
+
union_mode="left_to_right",
|
180
184
|
)
|
181
185
|
|
182
186
|
def set_scope_user(self, user_id: UUID) -> None:
|
@@ -279,122 +283,82 @@ class UserScopedFilter(BaseFilter):
|
|
279
283
|
return query
|
280
284
|
|
281
285
|
|
282
|
-
#
|
286
|
+
# Project-scoped models
|
283
287
|
|
284
288
|
|
285
|
-
class
|
286
|
-
"""Base
|
289
|
+
class ProjectScopedResponseBody(UserScopedResponseBody):
|
290
|
+
"""Base project-scoped body."""
|
287
291
|
|
288
292
|
|
289
|
-
class
|
290
|
-
"""Base
|
293
|
+
class ProjectScopedResponseMetadata(UserScopedResponseMetadata):
|
294
|
+
"""Base project-scoped metadata."""
|
291
295
|
|
292
|
-
|
293
|
-
title="The workspace of this resource."
|
294
|
-
)
|
296
|
+
project: "ProjectResponse" = Field(title="The project of this resource.")
|
295
297
|
|
296
298
|
|
297
|
-
class
|
298
|
-
"""Base
|
299
|
+
class ProjectScopedResponseResources(UserScopedResponseResources):
|
300
|
+
"""Base project-scoped resources."""
|
299
301
|
|
300
302
|
|
301
|
-
|
302
|
-
|
303
|
-
"
|
303
|
+
ProjectBody = TypeVar("ProjectBody", bound=ProjectScopedResponseBody)
|
304
|
+
ProjectMetadata = TypeVar(
|
305
|
+
"ProjectMetadata", bound=ProjectScopedResponseMetadata
|
304
306
|
)
|
305
|
-
|
306
|
-
"
|
307
|
+
ProjectResources = TypeVar(
|
308
|
+
"ProjectResources", bound=ProjectScopedResponseResources
|
307
309
|
)
|
308
310
|
|
309
311
|
|
310
|
-
class
|
311
|
-
UserScopedResponse[
|
312
|
-
Generic[
|
312
|
+
class ProjectScopedResponse(
|
313
|
+
UserScopedResponse[ProjectBody, ProjectMetadata, ProjectResources],
|
314
|
+
Generic[ProjectBody, ProjectMetadata, ProjectResources],
|
313
315
|
):
|
314
|
-
"""Base
|
316
|
+
"""Base project-scoped domain model.
|
315
317
|
|
316
|
-
Used as a base class for all domain models that are
|
318
|
+
Used as a base class for all domain models that are project-scoped.
|
317
319
|
"""
|
318
320
|
|
321
|
+
# Analytics
|
322
|
+
def get_analytics_metadata(self) -> Dict[str, Any]:
|
323
|
+
"""Fetches the analytics metadata for project scoped models.
|
324
|
+
|
325
|
+
Returns:
|
326
|
+
The analytics metadata.
|
327
|
+
"""
|
328
|
+
metadata = super().get_analytics_metadata()
|
329
|
+
if self.project is not None:
|
330
|
+
metadata["project_id"] = self.project.id
|
331
|
+
return metadata
|
332
|
+
|
319
333
|
# Body and metadata properties
|
320
334
|
@property
|
321
|
-
def
|
322
|
-
"""The
|
335
|
+
def project(self) -> "ProjectResponse":
|
336
|
+
"""The project property.
|
323
337
|
|
324
338
|
Returns:
|
325
339
|
the value of the property.
|
326
340
|
"""
|
327
|
-
return self.get_metadata().
|
341
|
+
return self.get_metadata().project
|
342
|
+
|
343
|
+
|
344
|
+
# ---------------------- Filter Models ----------------------
|
328
345
|
|
329
346
|
|
330
|
-
class
|
331
|
-
"""Model to enable advanced scoping with
|
347
|
+
class ProjectScopedFilter(UserScopedFilter):
|
348
|
+
"""Model to enable advanced scoping with project."""
|
332
349
|
|
333
350
|
FILTER_EXCLUDE_FIELDS: ClassVar[List[str]] = [
|
334
351
|
*UserScopedFilter.FILTER_EXCLUDE_FIELDS,
|
335
|
-
"
|
336
|
-
"scope_workspace",
|
352
|
+
"project",
|
337
353
|
]
|
338
|
-
|
339
|
-
*UserScopedFilter.CLI_EXCLUDE_FIELDS,
|
340
|
-
"workspace_id",
|
341
|
-
"workspace",
|
342
|
-
"scope_workspace",
|
343
|
-
]
|
344
|
-
CUSTOM_SORTING_OPTIONS: ClassVar[List[str]] = [
|
345
|
-
*UserScopedFilter.CUSTOM_SORTING_OPTIONS,
|
346
|
-
"workspace",
|
347
|
-
]
|
348
|
-
scope_workspace: Optional[UUID] = Field(
|
354
|
+
project: Optional[Union[UUID, str]] = Field(
|
349
355
|
default=None,
|
350
|
-
description="
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
description="UUID of the workspace that this entity belongs to.",
|
356
|
+
description="Name/ID of the project which the search is scoped to. "
|
357
|
+
"This field must always be set and is always applied in addition to "
|
358
|
+
"the other filters, regardless of the value of the "
|
359
|
+
"logical_operator field.",
|
355
360
|
union_mode="left_to_right",
|
356
361
|
)
|
357
|
-
workspace: Optional[Union[UUID, str]] = Field(
|
358
|
-
default=None,
|
359
|
-
description="Name/ID of the workspace that this entity belongs to.",
|
360
|
-
)
|
361
|
-
|
362
|
-
def set_scope_workspace(self, workspace_id: UUID) -> None:
|
363
|
-
"""Set the workspace to scope this response.
|
364
|
-
|
365
|
-
Args:
|
366
|
-
workspace_id: The workspace to scope this response to.
|
367
|
-
"""
|
368
|
-
self.scope_workspace = workspace_id
|
369
|
-
|
370
|
-
def get_custom_filters(
|
371
|
-
self, table: Type["AnySchema"]
|
372
|
-
) -> List["ColumnElement[bool]"]:
|
373
|
-
"""Get custom filters.
|
374
|
-
|
375
|
-
Args:
|
376
|
-
table: The query table.
|
377
|
-
|
378
|
-
Returns:
|
379
|
-
A list of custom filters.
|
380
|
-
"""
|
381
|
-
custom_filters = super().get_custom_filters(table)
|
382
|
-
|
383
|
-
from sqlmodel import and_
|
384
|
-
|
385
|
-
from zenml.zen_stores.schemas import WorkspaceSchema
|
386
|
-
|
387
|
-
if self.workspace:
|
388
|
-
workspace_filter = and_(
|
389
|
-
getattr(table, "workspace_id") == WorkspaceSchema.id,
|
390
|
-
self.generate_name_or_id_query_conditions(
|
391
|
-
value=self.workspace,
|
392
|
-
table=WorkspaceSchema,
|
393
|
-
),
|
394
|
-
)
|
395
|
-
custom_filters.append(workspace_filter)
|
396
|
-
|
397
|
-
return custom_filters
|
398
362
|
|
399
363
|
def apply_filter(
|
400
364
|
self,
|
@@ -409,59 +373,35 @@ class WorkspaceScopedFilter(UserScopedFilter):
|
|
409
373
|
|
410
374
|
Returns:
|
411
375
|
The query with filter applied.
|
412
|
-
"""
|
413
|
-
from sqlmodel import or_
|
414
376
|
|
415
|
-
|
416
|
-
|
417
|
-
if self.scope_workspace:
|
418
|
-
scope_filter = or_(
|
419
|
-
getattr(table, "workspace_id") == self.scope_workspace,
|
420
|
-
getattr(table, "workspace_id").is_(None),
|
421
|
-
)
|
422
|
-
query = query.where(scope_filter)
|
423
|
-
|
424
|
-
return query
|
425
|
-
|
426
|
-
def apply_sorting(
|
427
|
-
self,
|
428
|
-
query: AnyQuery,
|
429
|
-
table: Type["AnySchema"],
|
430
|
-
) -> AnyQuery:
|
431
|
-
"""Apply sorting to the query.
|
432
|
-
|
433
|
-
Args:
|
434
|
-
query: The query to which to apply the sorting.
|
435
|
-
table: The query table.
|
436
|
-
|
437
|
-
Returns:
|
438
|
-
The query with sorting applied.
|
377
|
+
Raises:
|
378
|
+
ValueError: If the project scope is missing from the filter.
|
439
379
|
"""
|
440
|
-
|
441
|
-
|
442
|
-
from zenml.enums import SorterOps
|
443
|
-
from zenml.zen_stores.schemas import WorkspaceSchema
|
444
|
-
|
445
|
-
sort_by, operand = self.sorting_params
|
446
|
-
|
447
|
-
if sort_by == "workspace":
|
448
|
-
column = WorkspaceSchema.name
|
380
|
+
query = super().apply_filter(query=query, table=table)
|
449
381
|
|
450
|
-
|
451
|
-
|
452
|
-
|
382
|
+
# The project scope must always be set and must be a UUID. If the
|
383
|
+
# client sets this to a string, the server will try to resolve it to a
|
384
|
+
# project ID.
|
385
|
+
#
|
386
|
+
# If not set by the client, the server will fall back to using the
|
387
|
+
# user's default project or even the server's default project, if
|
388
|
+
# they are configured. If this also fails to yield a project, this
|
389
|
+
# method will raise a ValueError.
|
390
|
+
#
|
391
|
+
# See: SqlZenStore._set_filter_project_id
|
392
|
+
|
393
|
+
if not self.project:
|
394
|
+
raise ValueError("Project scope missing from the filter.")
|
395
|
+
|
396
|
+
if not isinstance(self.project, UUID):
|
397
|
+
raise ValueError(
|
398
|
+
f"Project scope must be a UUID, got {type(self.project)}."
|
453
399
|
)
|
454
400
|
|
455
|
-
|
401
|
+
scope_filter = getattr(table, "project_id") == self.project
|
402
|
+
query = query.where(scope_filter)
|
456
403
|
|
457
|
-
|
458
|
-
query = query.order_by(asc(column))
|
459
|
-
else:
|
460
|
-
query = query.order_by(desc(column))
|
461
|
-
|
462
|
-
return query
|
463
|
-
|
464
|
-
return super().apply_sorting(query=query, table=table)
|
404
|
+
return query
|
465
405
|
|
466
406
|
|
467
407
|
class TaggableFilter(BaseFilter):
|
@@ -470,16 +410,44 @@ class TaggableFilter(BaseFilter):
|
|
470
410
|
tag: Optional[str] = Field(
|
471
411
|
description="Tag to apply to the filter query.", default=None
|
472
412
|
)
|
413
|
+
tags: Optional[List[str]] = Field(
|
414
|
+
description="Tags to apply to the filter query.", default=None
|
415
|
+
)
|
473
416
|
|
417
|
+
CLI_EXCLUDE_FIELDS = [
|
418
|
+
*BaseFilter.CLI_EXCLUDE_FIELDS,
|
419
|
+
]
|
474
420
|
FILTER_EXCLUDE_FIELDS: ClassVar[List[str]] = [
|
475
421
|
*BaseFilter.FILTER_EXCLUDE_FIELDS,
|
476
422
|
"tag",
|
423
|
+
"tags",
|
477
424
|
]
|
478
425
|
CUSTOM_SORTING_OPTIONS: ClassVar[List[str]] = [
|
479
426
|
*BaseFilter.CUSTOM_SORTING_OPTIONS,
|
480
427
|
"tags",
|
481
428
|
]
|
482
429
|
|
430
|
+
@model_validator(mode="after")
|
431
|
+
def add_tag_to_tags(self) -> "TaggableFilter":
|
432
|
+
"""Deprecated the tag attribute in favor of the tags attribute.
|
433
|
+
|
434
|
+
Returns:
|
435
|
+
self
|
436
|
+
"""
|
437
|
+
if self.tag is not None:
|
438
|
+
logger.warning(
|
439
|
+
"The `tag` attribute is deprecated in favor of the `tags` attribute. "
|
440
|
+
"Please update your code to use the `tags` attribute instead."
|
441
|
+
)
|
442
|
+
if self.tags is not None:
|
443
|
+
self.tags.append(self.tag)
|
444
|
+
else:
|
445
|
+
self.tags = [self.tag]
|
446
|
+
|
447
|
+
self.tag = None
|
448
|
+
|
449
|
+
return self
|
450
|
+
|
483
451
|
def apply_filter(
|
484
452
|
self,
|
485
453
|
query: AnyQuery,
|
@@ -497,7 +465,8 @@ class TaggableFilter(BaseFilter):
|
|
497
465
|
from zenml.zen_stores.schemas import TagResourceSchema, TagSchema
|
498
466
|
|
499
467
|
query = super().apply_filter(query=query, table=table)
|
500
|
-
|
468
|
+
|
469
|
+
if self.tags:
|
501
470
|
query = query.join(
|
502
471
|
TagResourceSchema,
|
503
472
|
TagResourceSchema.resource_id == getattr(table, "id"),
|
@@ -516,15 +485,25 @@ class TaggableFilter(BaseFilter):
|
|
516
485
|
Returns:
|
517
486
|
A list of custom filters.
|
518
487
|
"""
|
519
|
-
from zenml.zen_stores.schemas import TagSchema
|
520
|
-
|
521
488
|
custom_filters = super().get_custom_filters(table)
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
|
489
|
+
|
490
|
+
if self.tags:
|
491
|
+
from sqlmodel import exists, select
|
492
|
+
|
493
|
+
from zenml.zen_stores.schemas import TagResourceSchema, TagSchema
|
494
|
+
|
495
|
+
for tag in self.tags:
|
496
|
+
condition = self.generate_custom_query_conditions_for_column(
|
497
|
+
value=tag, table=TagSchema, column="name"
|
526
498
|
)
|
527
|
-
|
499
|
+
exists_subquery = exists(
|
500
|
+
select(TagResourceSchema)
|
501
|
+
.join(TagSchema, TagSchema.id == TagResourceSchema.tag_id) # type: ignore[arg-type]
|
502
|
+
.where(
|
503
|
+
TagResourceSchema.resource_id == table.id, condition
|
504
|
+
)
|
505
|
+
)
|
506
|
+
custom_filters.append(exists_subquery)
|
528
507
|
|
529
508
|
return custom_filters
|
530
509
|
|