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/utils/tag_utils.py
ADDED
@@ -0,0 +1,642 @@
|
|
1
|
+
# Copyright (c) ZenML GmbH 2025. All Rights Reserved.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at:
|
6
|
+
#
|
7
|
+
# https://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
12
|
+
# or implied. See the License for the specific language governing
|
13
|
+
# permissions and limitations under the License.
|
14
|
+
"""Utility functions for tags."""
|
15
|
+
|
16
|
+
from typing import (
|
17
|
+
TYPE_CHECKING,
|
18
|
+
List,
|
19
|
+
Optional,
|
20
|
+
TypeVar,
|
21
|
+
Union,
|
22
|
+
overload,
|
23
|
+
)
|
24
|
+
from uuid import UUID
|
25
|
+
|
26
|
+
from pydantic import BaseModel
|
27
|
+
|
28
|
+
from zenml.enums import ColorVariants, TaggableResourceTypes
|
29
|
+
from zenml.logger import get_logger
|
30
|
+
|
31
|
+
add_tags_warning = """
|
32
|
+
# Automatic tagging to a pipeline run (within a step)
|
33
|
+
add_tags(tags=[...])
|
34
|
+
|
35
|
+
# Manual tagging to a pipeline run
|
36
|
+
add_tags(tags=[...], run=...)
|
37
|
+
|
38
|
+
# Manual tagging to a pipeline
|
39
|
+
add_tags(tags=[...], pipeline=...)
|
40
|
+
|
41
|
+
# Manual tagging to a run template
|
42
|
+
add_tags(tags=[...], run_template=...)
|
43
|
+
|
44
|
+
# Manual tagging to an artifact
|
45
|
+
add_tags(tags=[...], artifact=...)
|
46
|
+
|
47
|
+
# Automatic tagging to an artifact version(within a step)
|
48
|
+
add_tags(tags=[...], infer_artifact=True) # step with single output
|
49
|
+
add_tags(tags=[...], artifact_name=..., infer_artifact=True) # specific output of a step
|
50
|
+
|
51
|
+
# Manual tagging to an artifact version
|
52
|
+
add_tags(tags=[...], artifact_name=..., artifact_version=...)
|
53
|
+
add_tags(tags=[...], artifact_version_id=...)
|
54
|
+
"""
|
55
|
+
|
56
|
+
remove_tags_warning = """
|
57
|
+
# Automatic tag removal from a pipeline run (within a step)
|
58
|
+
remove_tags(tags=[...])
|
59
|
+
|
60
|
+
# Manual tag removal from a pipeline run
|
61
|
+
remove_tags(tags=[...], run=...)
|
62
|
+
|
63
|
+
# Manual tag removal from a pipeline
|
64
|
+
remove_tags(tags=[...], pipeline=...)
|
65
|
+
|
66
|
+
# Manual tag removal from a run template
|
67
|
+
remove_tags(tags=[...], run_template=...)
|
68
|
+
|
69
|
+
# Manual tag removal from an artifact
|
70
|
+
remove_tags(tags=[...], artifact=...)
|
71
|
+
|
72
|
+
# Automatic tag removal from an artifact version (within a step)
|
73
|
+
remove_tags(tags=[...], infer_artifact=True) # step with single output
|
74
|
+
remove_tags(tags=[...], artifact_name=..., infer_artifact=True) # specific output of a step
|
75
|
+
|
76
|
+
# Manual tag removal from an artifact version
|
77
|
+
remove_tags(tags=[...], artifact_name=..., artifact_version=...)
|
78
|
+
remove_tags(tags=[...], artifact_version_id=...)
|
79
|
+
"""
|
80
|
+
|
81
|
+
|
82
|
+
if TYPE_CHECKING:
|
83
|
+
from zenml.models import TagRequest
|
84
|
+
from zenml.zen_stores.schemas.base_schemas import BaseSchema
|
85
|
+
|
86
|
+
AnySchema = TypeVar("AnySchema", bound=BaseSchema)
|
87
|
+
|
88
|
+
logger = get_logger(__name__)
|
89
|
+
|
90
|
+
|
91
|
+
class Tag(BaseModel):
|
92
|
+
"""A model representing a tag."""
|
93
|
+
|
94
|
+
name: str
|
95
|
+
color: Optional[ColorVariants] = None
|
96
|
+
exclusive: Optional[bool] = None
|
97
|
+
cascade: Optional[bool] = None
|
98
|
+
|
99
|
+
def to_request(self) -> "TagRequest":
|
100
|
+
"""Convert the tag to a TagRequest.
|
101
|
+
|
102
|
+
Returns:
|
103
|
+
The tag as a TagRequest.
|
104
|
+
"""
|
105
|
+
from zenml.models import TagRequest
|
106
|
+
|
107
|
+
request = TagRequest(name=self.name)
|
108
|
+
if self.color is not None:
|
109
|
+
request.color = self.color
|
110
|
+
|
111
|
+
if self.exclusive is not None:
|
112
|
+
request.exclusive = self.exclusive
|
113
|
+
return request
|
114
|
+
|
115
|
+
|
116
|
+
@overload
|
117
|
+
def add_tags(
|
118
|
+
tags: List[Union[str, Tag]],
|
119
|
+
) -> None: ...
|
120
|
+
|
121
|
+
|
122
|
+
@overload
|
123
|
+
def add_tags(
|
124
|
+
*,
|
125
|
+
tags: List[Union[str, Tag]],
|
126
|
+
run: Union[UUID, str],
|
127
|
+
) -> None: ...
|
128
|
+
|
129
|
+
|
130
|
+
@overload
|
131
|
+
def add_tags(
|
132
|
+
*,
|
133
|
+
tags: List[Union[str, Tag]],
|
134
|
+
artifact: Union[UUID, str],
|
135
|
+
) -> None: ...
|
136
|
+
|
137
|
+
|
138
|
+
@overload
|
139
|
+
def add_tags(
|
140
|
+
*,
|
141
|
+
tags: List[Union[str, Tag]],
|
142
|
+
artifact_version_id: UUID,
|
143
|
+
) -> None: ...
|
144
|
+
|
145
|
+
|
146
|
+
@overload
|
147
|
+
def add_tags(
|
148
|
+
*,
|
149
|
+
tags: List[Union[str, Tag]],
|
150
|
+
artifact_name: str,
|
151
|
+
artifact_version: Optional[str] = None,
|
152
|
+
) -> None: ...
|
153
|
+
|
154
|
+
|
155
|
+
@overload
|
156
|
+
def add_tags(
|
157
|
+
*,
|
158
|
+
tags: List[Union[str, Tag]],
|
159
|
+
infer_artifact: bool = False,
|
160
|
+
artifact_name: Optional[str] = None,
|
161
|
+
) -> None: ...
|
162
|
+
|
163
|
+
|
164
|
+
@overload
|
165
|
+
def add_tags(
|
166
|
+
*,
|
167
|
+
tags: List[Union[str, Tag]],
|
168
|
+
pipeline: Union[UUID, str],
|
169
|
+
) -> None: ...
|
170
|
+
|
171
|
+
|
172
|
+
@overload
|
173
|
+
def add_tags(
|
174
|
+
*,
|
175
|
+
tags: List[Union[str, Tag]],
|
176
|
+
run_template: Union[UUID, str],
|
177
|
+
) -> None: ...
|
178
|
+
|
179
|
+
|
180
|
+
def add_tags(
|
181
|
+
tags: List[Union[str, Tag]],
|
182
|
+
# Pipelines
|
183
|
+
pipeline: Optional[Union[UUID, str]] = None,
|
184
|
+
# Runs
|
185
|
+
run: Optional[Union[UUID, str]] = None,
|
186
|
+
# Run Templates
|
187
|
+
run_template: Optional[Union[UUID, str]] = None,
|
188
|
+
# Artifacts
|
189
|
+
artifact: Optional[Union[UUID, str]] = None,
|
190
|
+
# Artifact Versions
|
191
|
+
artifact_version_id: Optional[UUID] = None,
|
192
|
+
artifact_name: Optional[str] = None,
|
193
|
+
artifact_version: Optional[str] = None,
|
194
|
+
infer_artifact: bool = False,
|
195
|
+
) -> None:
|
196
|
+
"""Add tags to various resource types in a generalized way.
|
197
|
+
|
198
|
+
Args:
|
199
|
+
tags: The tags to add.
|
200
|
+
pipeline: The ID or the name of the pipeline.
|
201
|
+
run: The id, name or prefix of the run.
|
202
|
+
run_template: The ID or the name of the run template.
|
203
|
+
artifact: The ID or the name of the artifact.
|
204
|
+
artifact_version_id: The ID of the artifact version.
|
205
|
+
artifact_name: The name of the artifact.
|
206
|
+
artifact_version: The version of the artifact.
|
207
|
+
infer_artifact: Flag deciding whether the artifact version should be
|
208
|
+
inferred from the step context.
|
209
|
+
|
210
|
+
Raises:
|
211
|
+
ValueError: If no identifiers are provided and the function is not
|
212
|
+
called from within a step, or if exclusive is provided for a
|
213
|
+
resource type that doesn't support it.
|
214
|
+
"""
|
215
|
+
from zenml.client import Client
|
216
|
+
from zenml.models.v2.misc.tag import TagResource
|
217
|
+
|
218
|
+
client = Client()
|
219
|
+
resource_id = None
|
220
|
+
resource_type = None
|
221
|
+
|
222
|
+
# Tag a pipeline
|
223
|
+
if pipeline is not None:
|
224
|
+
pipeline_model = client.get_pipeline(name_id_or_prefix=pipeline)
|
225
|
+
resource_id = pipeline_model.id
|
226
|
+
resource_type = TaggableResourceTypes.PIPELINE
|
227
|
+
|
228
|
+
# Tag a run by ID
|
229
|
+
elif run is not None:
|
230
|
+
run_model = client.get_pipeline_run(name_id_or_prefix=run)
|
231
|
+
resource_id = run_model.id
|
232
|
+
resource_type = TaggableResourceTypes.PIPELINE_RUN
|
233
|
+
|
234
|
+
# Tag a run template
|
235
|
+
elif run_template is not None:
|
236
|
+
run_template_model = client.get_run_template(
|
237
|
+
name_id_or_prefix=run_template
|
238
|
+
)
|
239
|
+
resource_id = run_template_model.id
|
240
|
+
resource_type = TaggableResourceTypes.RUN_TEMPLATE
|
241
|
+
|
242
|
+
# Tag an artifact
|
243
|
+
elif artifact is not None:
|
244
|
+
artifact_model = client.get_artifact(name_id_or_prefix=artifact)
|
245
|
+
resource_id = artifact_model.id
|
246
|
+
resource_type = TaggableResourceTypes.ARTIFACT
|
247
|
+
|
248
|
+
# Tag an artifact version by its name and version
|
249
|
+
elif artifact_name is not None and artifact_version is not None:
|
250
|
+
artifact_version_model = client.get_artifact_version(
|
251
|
+
name_id_or_prefix=artifact_name, version=artifact_version
|
252
|
+
)
|
253
|
+
resource_id = artifact_version_model.id
|
254
|
+
resource_type = TaggableResourceTypes.ARTIFACT_VERSION
|
255
|
+
|
256
|
+
# Tag an artifact version by its ID
|
257
|
+
elif artifact_version_id is not None:
|
258
|
+
resource_id = artifact_version_id
|
259
|
+
resource_type = TaggableResourceTypes.ARTIFACT_VERSION
|
260
|
+
|
261
|
+
# Tag an artifact version through the step context
|
262
|
+
elif infer_artifact is True:
|
263
|
+
resource_type = TaggableResourceTypes.ARTIFACT_VERSION
|
264
|
+
|
265
|
+
try:
|
266
|
+
from zenml.steps.step_context import get_step_context
|
267
|
+
|
268
|
+
step_context = get_step_context()
|
269
|
+
except RuntimeError:
|
270
|
+
raise ValueError(
|
271
|
+
"When you are using the `infer_artifact` option when you call "
|
272
|
+
"`add_tags`, it must be called inside a step with outputs."
|
273
|
+
"Otherwise, you can provide a `artifact_version_id` or a "
|
274
|
+
"combination of `artifact_name` and `artifact_version`."
|
275
|
+
)
|
276
|
+
|
277
|
+
step_output_names = list(step_context._outputs.keys())
|
278
|
+
|
279
|
+
if artifact_name is not None:
|
280
|
+
# If a name provided, ensure it is in the outputs
|
281
|
+
if artifact_name not in step_output_names:
|
282
|
+
raise ValueError(
|
283
|
+
f"The provided artifact name`{artifact_name}` does not "
|
284
|
+
f"exist in the step outputs: {step_output_names}."
|
285
|
+
)
|
286
|
+
else:
|
287
|
+
# If no name provided, ensure there is only one output
|
288
|
+
if len(step_output_names) > 1:
|
289
|
+
raise ValueError(
|
290
|
+
"There is more than one output. If you would like to use "
|
291
|
+
"the `infer_artifact` option, you need to define an "
|
292
|
+
"`artifact_name`."
|
293
|
+
)
|
294
|
+
|
295
|
+
if len(step_output_names) == 0:
|
296
|
+
raise ValueError("The step does not have any outputs.")
|
297
|
+
|
298
|
+
artifact_name = step_output_names[0]
|
299
|
+
|
300
|
+
step_context.add_output_tags(
|
301
|
+
tags=[t.name if isinstance(t, Tag) else t for t in tags],
|
302
|
+
output_name=artifact_name,
|
303
|
+
)
|
304
|
+
|
305
|
+
# If every additional value is None, that means we are calling it bare bones
|
306
|
+
# and this call needs to happen during a step execution. We will use the
|
307
|
+
# step context to fetch the run and attach the tags accordingly.
|
308
|
+
elif all(
|
309
|
+
v is None
|
310
|
+
for v in [
|
311
|
+
run,
|
312
|
+
artifact_version_id,
|
313
|
+
artifact_name,
|
314
|
+
artifact_version,
|
315
|
+
pipeline,
|
316
|
+
run_template,
|
317
|
+
]
|
318
|
+
):
|
319
|
+
try:
|
320
|
+
from zenml.steps.step_context import get_step_context
|
321
|
+
|
322
|
+
step_context = get_step_context()
|
323
|
+
except RuntimeError:
|
324
|
+
raise ValueError(
|
325
|
+
f"""
|
326
|
+
You are calling 'add_tags()' outside of a step execution.
|
327
|
+
If you would like to add tags to a ZenML entity outside
|
328
|
+
of the step execution, please provide the required
|
329
|
+
identifiers.\n{add_tags_warning}
|
330
|
+
"""
|
331
|
+
)
|
332
|
+
|
333
|
+
# Tag the pipeline run, not the step
|
334
|
+
resource_id = step_context.pipeline_run.id
|
335
|
+
resource_type = TaggableResourceTypes.PIPELINE_RUN
|
336
|
+
|
337
|
+
else:
|
338
|
+
raise ValueError(
|
339
|
+
f"""
|
340
|
+
Unsupported way to call the `add_tags`. Possible combinations "
|
341
|
+
include: \n{add_tags_warning}
|
342
|
+
"""
|
343
|
+
)
|
344
|
+
|
345
|
+
# Create tag resources and add tags
|
346
|
+
for tag in tags:
|
347
|
+
try:
|
348
|
+
if isinstance(tag, Tag):
|
349
|
+
tag_model = client.get_tag(tag.name)
|
350
|
+
|
351
|
+
if tag.exclusive != tag_model.exclusive:
|
352
|
+
raise ValueError(
|
353
|
+
f"The tag `{tag.name}` is an "
|
354
|
+
f"{'exclusive' if tag_model.exclusive else 'non-exclusive'} "
|
355
|
+
"tag. Please update it before attaching it to a resource."
|
356
|
+
)
|
357
|
+
if tag.cascade is not None:
|
358
|
+
raise ValueError(
|
359
|
+
"Cascading tags can only be used with the "
|
360
|
+
"pipeline decorator."
|
361
|
+
)
|
362
|
+
else:
|
363
|
+
tag_model = client.get_tag(tag)
|
364
|
+
|
365
|
+
except KeyError:
|
366
|
+
if isinstance(tag, Tag):
|
367
|
+
tag_model = client.create_tag(
|
368
|
+
name=tag.name,
|
369
|
+
exclusive=tag.exclusive
|
370
|
+
if tag.exclusive is not None
|
371
|
+
else False,
|
372
|
+
)
|
373
|
+
|
374
|
+
if tag.cascade is not None:
|
375
|
+
raise ValueError(
|
376
|
+
"Cascading tags can only be used with the "
|
377
|
+
"pipeline decorator."
|
378
|
+
)
|
379
|
+
else:
|
380
|
+
tag_model = client.create_tag(name=tag)
|
381
|
+
|
382
|
+
if tag_model.exclusive and resource_type not in [
|
383
|
+
TaggableResourceTypes.PIPELINE_RUN,
|
384
|
+
TaggableResourceTypes.ARTIFACT_VERSION,
|
385
|
+
TaggableResourceTypes.RUN_TEMPLATE,
|
386
|
+
]:
|
387
|
+
logger.warning(
|
388
|
+
"The tag will be added, however, please keep in mind that "
|
389
|
+
"the functionality of having exclusive tags is only "
|
390
|
+
"applicable for pipeline runs, artifact versions and run "
|
391
|
+
f"templates, not {resource_type.value}s."
|
392
|
+
)
|
393
|
+
|
394
|
+
if resource_id:
|
395
|
+
client.attach_tag(
|
396
|
+
tag_name_or_id=tag_model.name,
|
397
|
+
resources=[TagResource(id=resource_id, type=resource_type)],
|
398
|
+
)
|
399
|
+
|
400
|
+
|
401
|
+
@overload
|
402
|
+
def remove_tags(
|
403
|
+
tags: List[str],
|
404
|
+
) -> None: ...
|
405
|
+
|
406
|
+
|
407
|
+
@overload
|
408
|
+
def remove_tags(
|
409
|
+
*,
|
410
|
+
tags: List[str],
|
411
|
+
pipeline: Union[UUID, str],
|
412
|
+
) -> None: ...
|
413
|
+
|
414
|
+
|
415
|
+
@overload
|
416
|
+
def remove_tags(
|
417
|
+
*,
|
418
|
+
tags: List[str],
|
419
|
+
run: Union[UUID, str],
|
420
|
+
) -> None: ...
|
421
|
+
|
422
|
+
|
423
|
+
@overload
|
424
|
+
def remove_tags(
|
425
|
+
*,
|
426
|
+
tags: List[str],
|
427
|
+
run_template: Union[UUID, str],
|
428
|
+
) -> None: ...
|
429
|
+
|
430
|
+
|
431
|
+
@overload
|
432
|
+
def remove_tags(
|
433
|
+
*,
|
434
|
+
tags: List[str],
|
435
|
+
artifact: Union[UUID, str],
|
436
|
+
) -> None: ...
|
437
|
+
|
438
|
+
|
439
|
+
@overload
|
440
|
+
def remove_tags(
|
441
|
+
*,
|
442
|
+
tags: List[str],
|
443
|
+
artifact_version_id: UUID,
|
444
|
+
) -> None: ...
|
445
|
+
|
446
|
+
|
447
|
+
@overload
|
448
|
+
def remove_tags(
|
449
|
+
*,
|
450
|
+
tags: List[str],
|
451
|
+
artifact_name: str,
|
452
|
+
artifact_version: Optional[str] = None,
|
453
|
+
) -> None: ...
|
454
|
+
|
455
|
+
|
456
|
+
@overload
|
457
|
+
def remove_tags(
|
458
|
+
*,
|
459
|
+
tags: List[str],
|
460
|
+
infer_artifact: bool = False,
|
461
|
+
artifact_name: Optional[str] = None,
|
462
|
+
) -> None: ...
|
463
|
+
|
464
|
+
|
465
|
+
def remove_tags(
|
466
|
+
tags: List[str],
|
467
|
+
# Pipelines
|
468
|
+
pipeline: Optional[Union[UUID, str]] = None,
|
469
|
+
# Runs
|
470
|
+
run: Optional[Union[UUID, str]] = None,
|
471
|
+
# Run Templates
|
472
|
+
run_template: Optional[Union[UUID, str]] = None,
|
473
|
+
# Artifacts
|
474
|
+
artifact: Optional[Union[UUID, str]] = None,
|
475
|
+
# Artifact Versions
|
476
|
+
artifact_version_id: Optional[UUID] = None,
|
477
|
+
artifact_name: Optional[str] = None,
|
478
|
+
artifact_version: Optional[str] = None,
|
479
|
+
infer_artifact: bool = False,
|
480
|
+
) -> None:
|
481
|
+
"""Remove tags from various resource types in a generalized way.
|
482
|
+
|
483
|
+
Args:
|
484
|
+
tags: The tags to remove.
|
485
|
+
pipeline: The ID or the name of the pipeline.
|
486
|
+
run: The id, name or prefix of the run.
|
487
|
+
run_template: The ID or the name of the run template.
|
488
|
+
artifact: The ID or the name of the artifact.
|
489
|
+
artifact_version_id: The ID of the artifact version.
|
490
|
+
artifact_name: The name of the artifact.
|
491
|
+
artifact_version: The version of the artifact.
|
492
|
+
infer_artifact: Flag deciding whether the artifact version should be
|
493
|
+
inferred from the step context.
|
494
|
+
|
495
|
+
Raises:
|
496
|
+
ValueError: If no identifiers are provided and the function is not
|
497
|
+
called from within a step.
|
498
|
+
"""
|
499
|
+
from zenml.client import Client
|
500
|
+
from zenml.models.v2.misc.tag import TagResource
|
501
|
+
|
502
|
+
client = Client()
|
503
|
+
resource_id = None
|
504
|
+
resource_type = None
|
505
|
+
|
506
|
+
# Remove tags from a pipeline
|
507
|
+
if pipeline is not None:
|
508
|
+
pipeline_model = client.get_pipeline(name_id_or_prefix=pipeline)
|
509
|
+
resource_id = pipeline_model.id
|
510
|
+
resource_type = TaggableResourceTypes.PIPELINE
|
511
|
+
|
512
|
+
# Remove tags from a run template
|
513
|
+
elif run_template is not None:
|
514
|
+
run_template_model = client.get_run_template(
|
515
|
+
name_id_or_prefix=run_template
|
516
|
+
)
|
517
|
+
resource_id = run_template_model.id
|
518
|
+
resource_type = TaggableResourceTypes.RUN_TEMPLATE
|
519
|
+
|
520
|
+
# Remove tags from a run
|
521
|
+
elif run is not None:
|
522
|
+
run_model = client.get_pipeline_run(name_id_or_prefix=run)
|
523
|
+
resource_id = run_model.id
|
524
|
+
resource_type = TaggableResourceTypes.PIPELINE_RUN
|
525
|
+
|
526
|
+
# Remove tags from an artifact
|
527
|
+
elif artifact is not None:
|
528
|
+
artifact_model = client.get_artifact(name_id_or_prefix=artifact)
|
529
|
+
resource_id = artifact_model.id
|
530
|
+
resource_type = TaggableResourceTypes.ARTIFACT
|
531
|
+
|
532
|
+
# Remove tags from an artifact version by its name and version
|
533
|
+
elif artifact_name is not None and artifact_version is not None:
|
534
|
+
artifact_version_model = client.get_artifact_version(
|
535
|
+
name_id_or_prefix=artifact_name, version=artifact_version
|
536
|
+
)
|
537
|
+
resource_id = artifact_version_model.id
|
538
|
+
resource_type = TaggableResourceTypes.ARTIFACT_VERSION
|
539
|
+
|
540
|
+
# Remove tags from an artifact version by its ID
|
541
|
+
elif artifact_version_id is not None:
|
542
|
+
resource_id = artifact_version_id
|
543
|
+
resource_type = TaggableResourceTypes.ARTIFACT_VERSION
|
544
|
+
|
545
|
+
# Remove tags from an artifact version through the step context
|
546
|
+
elif infer_artifact is True:
|
547
|
+
try:
|
548
|
+
from zenml.steps.step_context import get_step_context
|
549
|
+
|
550
|
+
step_context = get_step_context()
|
551
|
+
except RuntimeError:
|
552
|
+
raise ValueError(
|
553
|
+
"When you are using the `infer_artifact` option when you call "
|
554
|
+
"`remove_tags`, it must be called inside a step with outputs."
|
555
|
+
"Otherwise, you can provide a `artifact_version_id` or a "
|
556
|
+
"combination of `artifact_name` and `artifact_version`."
|
557
|
+
)
|
558
|
+
|
559
|
+
step_output_names = list(step_context._outputs.keys())
|
560
|
+
|
561
|
+
if artifact_name is not None:
|
562
|
+
# If a name provided, ensure it is in the outputs
|
563
|
+
if artifact_name not in step_output_names:
|
564
|
+
raise ValueError(
|
565
|
+
f"The provided artifact name`{artifact_name}` does not "
|
566
|
+
f"exist in the step outputs: {step_output_names}."
|
567
|
+
)
|
568
|
+
else:
|
569
|
+
# If no name provided, ensure there is only one output
|
570
|
+
if len(step_output_names) > 1:
|
571
|
+
raise ValueError(
|
572
|
+
"There is more than one output. If you would like to use "
|
573
|
+
"the `infer_artifact` option, you need to define an "
|
574
|
+
"`artifact_name`."
|
575
|
+
)
|
576
|
+
|
577
|
+
if len(step_output_names) == 0:
|
578
|
+
raise ValueError("The step does not have any outputs.")
|
579
|
+
|
580
|
+
artifact_name = step_output_names[0]
|
581
|
+
|
582
|
+
step_context.remove_output_tags(
|
583
|
+
tags=tags,
|
584
|
+
output_name=artifact_name,
|
585
|
+
)
|
586
|
+
return
|
587
|
+
|
588
|
+
# If every additional value is None, that means we are calling it bare bones
|
589
|
+
# and this call needs to happen during a step execution. We will use the
|
590
|
+
# step context to fetch the run and detach the tags accordingly.
|
591
|
+
elif all(
|
592
|
+
v is None
|
593
|
+
for v in [
|
594
|
+
run,
|
595
|
+
artifact_version_id,
|
596
|
+
artifact_name,
|
597
|
+
artifact_version,
|
598
|
+
pipeline,
|
599
|
+
run_template,
|
600
|
+
]
|
601
|
+
):
|
602
|
+
try:
|
603
|
+
from zenml.steps.step_context import get_step_context
|
604
|
+
|
605
|
+
step_context = get_step_context()
|
606
|
+
except RuntimeError:
|
607
|
+
raise ValueError(
|
608
|
+
f"""
|
609
|
+
You are calling 'remove_tags()' outside of a step execution.
|
610
|
+
If you would like to remove tags from a ZenML entity outside
|
611
|
+
of the step execution, please provide the required
|
612
|
+
identifiers. \n{remove_tags_warning}
|
613
|
+
"""
|
614
|
+
)
|
615
|
+
|
616
|
+
# Tag the pipeline run, not the step
|
617
|
+
resource_id = step_context.pipeline_run.id
|
618
|
+
resource_type = TaggableResourceTypes.PIPELINE_RUN
|
619
|
+
|
620
|
+
else:
|
621
|
+
raise ValueError(
|
622
|
+
f"""
|
623
|
+
Unsupported way to call the `remove_tags`. Possible combinations "
|
624
|
+
include: \n{remove_tags_warning}
|
625
|
+
"""
|
626
|
+
)
|
627
|
+
|
628
|
+
# Remove tags from resource
|
629
|
+
for tag_name in tags:
|
630
|
+
try:
|
631
|
+
# Get the tag
|
632
|
+
tag = client.get_tag(tag_name)
|
633
|
+
|
634
|
+
# Detach tag from resources
|
635
|
+
client.detach_tag(
|
636
|
+
tag_name_or_id=tag.id,
|
637
|
+
resources=[TagResource(id=resource_id, type=resource_type)],
|
638
|
+
)
|
639
|
+
|
640
|
+
except KeyError:
|
641
|
+
# Tag doesn't exist, nothing to remove
|
642
|
+
pass
|
zenml/zen_server/cloud_utils.py
CHANGED
@@ -130,6 +130,27 @@ class ZenMLCloudConnection:
|
|
130
130
|
method="PATCH", endpoint=endpoint, params=params, data=data
|
131
131
|
)
|
132
132
|
|
133
|
+
def delete(
|
134
|
+
self,
|
135
|
+
endpoint: str,
|
136
|
+
params: Optional[Dict[str, Any]] = None,
|
137
|
+
data: Optional[Dict[str, Any]] = None,
|
138
|
+
) -> requests.Response:
|
139
|
+
"""Send a DELETE request using the active session.
|
140
|
+
|
141
|
+
Args:
|
142
|
+
endpoint: The endpoint to send the request to. This will be appended
|
143
|
+
to the base URL.
|
144
|
+
params: Parameters to include in the request.
|
145
|
+
data: Data to include in the request.
|
146
|
+
|
147
|
+
Returns:
|
148
|
+
The response.
|
149
|
+
"""
|
150
|
+
return self.request(
|
151
|
+
method="DELETE", endpoint=endpoint, params=params, data=data
|
152
|
+
)
|
153
|
+
|
133
154
|
@property
|
134
155
|
def session(self) -> requests.Session:
|
135
156
|
"""Authenticate to the ZenML Pro Management Plane.
|
zenml/zen_server/exceptions.py
CHANGED
@@ -27,9 +27,6 @@ from zenml.exceptions import (
|
|
27
27
|
EntityExistsError,
|
28
28
|
IllegalOperationError,
|
29
29
|
MethodNotAllowedError,
|
30
|
-
SecretExistsError,
|
31
|
-
StackComponentExistsError,
|
32
|
-
StackExistsError,
|
33
30
|
SubscriptionUpgradeRequiredError,
|
34
31
|
ValidationError,
|
35
32
|
ZenKeyError,
|
@@ -72,9 +69,6 @@ error_response = dict(model=ErrorModel)
|
|
72
69
|
# different status codes (e.g. `ValueError` and the 400 and 422 status codes).
|
73
70
|
REST_API_EXCEPTIONS: List[Tuple[Type[Exception], int]] = [
|
74
71
|
# 409 Conflict
|
75
|
-
(StackExistsError, 409),
|
76
|
-
(StackComponentExistsError, 409),
|
77
|
-
(SecretExistsError, 409),
|
78
72
|
(DuplicateRunNameError, 409),
|
79
73
|
(EntityExistsError, 409),
|
80
74
|
# 403 Forbidden
|