zenml-nightly 0.71.0.dev20250109__py3-none-any.whl → 0.71.0.dev20250112__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/base.py +1 -1
- zenml/cli/formatter.py +1 -1
- zenml/cli/integration.py +1 -1
- zenml/cli/model_registry.py +1 -2
- zenml/cli/secret.py +1 -2
- zenml/cli/service_connectors.py +1 -1
- zenml/cli/stack.py +2 -3
- zenml/cli/stack_components.py +4 -6
- zenml/cli/text_utils.py +1 -1
- zenml/cli/utils.py +4 -5
- zenml/client.py +1 -4
- zenml/constants.py +1 -0
- zenml/entrypoints/step_entrypoint_configuration.py +15 -0
- zenml/integrations/azure/__init__.py +1 -1
- zenml/integrations/azure/azureml_utils.py +1 -1
- zenml/integrations/azure/orchestrators/azureml_orchestrator_entrypoint_config.py +0 -5
- zenml/integrations/bitbucket/plugins/event_sources/bitbucket_webhook_event_source.py +3 -3
- zenml/integrations/databricks/orchestrators/databricks_orchestrator.py +1 -3
- zenml/integrations/evidently/metrics.py +2 -2
- zenml/integrations/evidently/tests.py +2 -2
- zenml/integrations/gcp/service_connectors/gcp_service_connector.py +3 -3
- zenml/integrations/github/plugins/event_sources/github_webhook_event_source.py +3 -3
- zenml/integrations/s3/utils.py +1 -2
- zenml/logger.py +1 -1
- zenml/models/v2/base/scoped.py +32 -28
- zenml/models/v2/core/artifact.py +86 -2
- zenml/models/v2/core/model.py +81 -2
- zenml/models/v2/core/pipeline.py +15 -12
- zenml/models/v2/core/pipeline_run.py +2 -0
- zenml/services/container/container_service.py +1 -1
- zenml/stack/stack_component.py +1 -1
- zenml/utils/deprecation_utils.py +6 -6
- zenml/utils/filesync_model.py +3 -3
- zenml/utils/function_utils.py +1 -1
- zenml/utils/pipeline_docker_image_builder.py +1 -1
- zenml/zen_server/auth.py +2 -5
- zenml/zen_server/dashboard/assets/{404-Cqu3EDCm.js → 404-Dfq64Boz.js} +1 -1
- zenml/zen_server/dashboard/assets/{@reactflow-D2Y7BWwz.js → @reactflow-BUNIMFeC.js} +1 -1
- zenml/zen_server/dashboard/assets/{AlertDialogDropdownItem-BHd71pVS.js → AlertDialogDropdownItem-B73Vs10T.js} +1 -1
- zenml/zen_server/dashboard/assets/{CodeSnippet-DIonwetW.js → CodeSnippet-DIJRT2NT.js} +1 -1
- zenml/zen_server/dashboard/assets/{CollapsibleCard-CDnC97pB.js → CollapsibleCard-BzUHGZOU.js} +1 -1
- zenml/zen_server/dashboard/assets/{Commands-BVEXKAOj.js → Commands-BEGyld4c.js} +1 -1
- zenml/zen_server/dashboard/assets/{ComponentBadge-CrRvovox.js → ComponentBadge-xyKiek1s.js} +1 -1
- zenml/zen_server/dashboard/assets/{CopyButton-B6wGAhQv.js → CopyButton-DhW-mapu.js} +1 -1
- zenml/zen_server/dashboard/assets/{CsvVizualization-CjcT7LMm.js → CsvVizualization-D8oazBiE.js} +1 -1
- zenml/zen_server/dashboard/assets/{DeleteAlertDialog-D2ELtM2W.js → DeleteAlertDialog-WkSIIgfy.js} +1 -1
- zenml/zen_server/dashboard/assets/{DialogItem-DXIMhBgU.js → DialogItem-Bgroeg29.js} +1 -1
- zenml/zen_server/dashboard/assets/{Error-B8uUfTpL.js → Error-CY5tlu17.js} +1 -1
- zenml/zen_server/dashboard/assets/{ExecutionStatus-ibAdY-dG.js → ExecutionStatus-G8mjIaeA.js} +1 -1
- zenml/zen_server/dashboard/assets/{Helpbox-BfAfhKHw.js → Helpbox-Bb1ed--O.js} +1 -1
- zenml/zen_server/dashboard/assets/{Infobox-M_SMOu96.js → Infobox-Da6-76M2.js} +1 -1
- zenml/zen_server/dashboard/assets/{InlineAvatar-DBA0a0-a.js → InlineAvatar-DqnZaBNq.js} +1 -1
- zenml/zen_server/dashboard/assets/{NestedCollapsible-DpgmEFKw.js → NestedCollapsible-aK5ojKoF.js} +1 -1
- zenml/zen_server/dashboard/assets/{Partials-D_ldD9if.js → Partials-CqZp5NMX.js} +1 -1
- zenml/zen_server/dashboard/assets/{ProBadge-DQbfFotM.js → ProBadge-B4tRUYve.js} +1 -1
- zenml/zen_server/dashboard/assets/{ProCta-Bcpb4rcY.js → ProCta-CZuP29Qz.js} +1 -1
- zenml/zen_server/dashboard/assets/{ProviderIcon-BZpgPigN.js → ProviderIcon-Bd7GUQ1_.js} +1 -1
- zenml/zen_server/dashboard/assets/{ProviderRadio-DWPnMuQ1.js → ProviderRadio-mstdqzsS.js} +1 -1
- zenml/zen_server/dashboard/assets/{RunSelector-DgRGaAc6.js → RunSelector-CsruSB4i.js} +1 -1
- zenml/zen_server/dashboard/assets/{RunsBody-KecfSkjY.js → RunsBody-DxxtWVYz.js} +1 -1
- zenml/zen_server/dashboard/assets/{SearchField-n-ILHnaP.js → SearchField-D6tPxyqw.js} +1 -1
- zenml/zen_server/dashboard/assets/{SecretTooltip-B8MrX5yu.js → SecretTooltip-CLzJIYW_.js} +1 -1
- zenml/zen_server/dashboard/assets/{SetPassword-B_IVq_wg.js → SetPassword-Yn50ooBC.js} +1 -1
- zenml/zen_server/dashboard/assets/{StackList-TWPBYnkF.js → StackList-U537qoYd.js} +1 -1
- zenml/zen_server/dashboard/assets/{Tabs-Rg857zmd.js → Tabs-CNv-eTYM.js} +1 -1
- zenml/zen_server/dashboard/assets/{Tick-COg4A-xo.js → Tick-jEIevzVf.js} +1 -1
- zenml/zen_server/dashboard/assets/{UpdatePasswordSchemas-C6Aj3hm6.js → UpdatePasswordSchemas-C16GW-kX.js} +1 -1
- zenml/zen_server/dashboard/assets/{UsageReason-BTLbx7w4.js → UsageReason-Bf2tzhv1.js} +1 -1
- zenml/zen_server/dashboard/assets/{WizardFooter-BCAj69Vj.js → WizardFooter-D6i-AP1K.js} +1 -1
- zenml/zen_server/dashboard/assets/{all-pipeline-runs-query-DMXkDrV2.js → all-pipeline-runs-query-DUti43aF.js} +1 -1
- zenml/zen_server/dashboard/assets/{create-stack-HfdbhLs4.js → create-stack-Ch2WPs9U.js} +1 -1
- zenml/zen_server/dashboard/assets/{delete-run-DZ4hIXff.js → delete-run-Byf9hTjA.js} +1 -1
- zenml/zen_server/dashboard/assets/{form-schemas-B0AVEd9b.js → form-schemas-BZqKBPBF.js} +1 -1
- zenml/zen_server/dashboard/assets/{index-FO-p0GU7.js → index-CE0aQlv8.js} +3 -3
- zenml/zen_server/dashboard/assets/{index-DScjfBRb.js → index-CtdYkjUi.js} +1 -1
- zenml/zen_server/dashboard/assets/{index-DPqSWjug.js → index-CyBKZcpO.js} +1 -1
- zenml/zen_server/dashboard/assets/{index-I3bKUGUj.js → index-v6gQjDEo.js} +1 -1
- zenml/zen_server/dashboard/assets/{login-mutation-BQeo4wTY.js → login-mutation-DNDVp_2H.js} +1 -1
- zenml/zen_server/dashboard/assets/{not-found-gAJ5aDdR.js → not-found-Bmup4ctE.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-I3nKFGie.js → page--XLMzHrn.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-DO1UcqPX.js → page-ANYGfEUL.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-AUwiQ14W.js → page-B5Sr8pib.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-CcQr8CPP.js → page-BC27C_OI.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-zaMqB_ao.js → page-BNxYrN0q.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-CiYxgZP_.js → page-BYJfqgLN.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-h_Stveon.js → page-B_0XkV48.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-R5dx3xGF.js → page-BrmJp1Wt.js} +1 -1
- zenml/zen_server/dashboard/assets/page-C2nU3Gxn.js +1 -0
- zenml/zen_server/dashboard/assets/{page-Dk32IeZm.js → page-C70wZtV2.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-CWxT5K5J.js → page-CHRn1fQm.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-M0w-n6vn.js → page-CWr96ZKN.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-Ce4Hrjnr.js → page-CXAbSyp9.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-D8ObrbH8.js → page-CaeI9ptC.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-B_Apk3xg.js → page-Cc8ZEuj4.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-BxL4qD4_.js → page-CltCNL0T.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-D4wdonLm.js → page-CmlYj7Nl.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-DFuAUGt4.js → page-D6Ev5P8V.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-u_-ZXBKb.js → page-D9Oh05fl.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-DRYXdL5o.js → page-DGlm1RVc.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-r8XK5vR7.js → page-DN4BVIOL.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-DYEquBC2.js → page-Dif8CWyZ.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-BdowiCbr.js → page-DlIi5ThM.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-9Y9-gig0.js → page-DoW7YxTu.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-BKZYc2Zv.js → page-Dth9X1Ih.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-bT5pOvcB.js → page-DweqqCkF.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-CXuQufSe.js → page-DyOJ_pq3.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-DGazBpuP.js → page-Hn8q9iJZ.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-hUqK889I.js → page-IhckKFnD.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-BU9FG4sR.js → page-LyZ_l8vR.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-Cldq1mpe.js → page-PamGpk0j.js} +1 -1
- zenml/zen_server/dashboard/assets/page-PxOWfKgF.js +2 -0
- zenml/zen_server/dashboard/assets/{persist-DAUi_3za.js → persist-DeXRG61d.js} +1 -1
- zenml/zen_server/dashboard/assets/{persist-AppN1B0J.js → persist-vP0-Xl4f.js} +1 -1
- zenml/zen_server/dashboard/assets/{service-BqqeXLEe.js → service-DH_oUqQj.js} +1 -1
- zenml/zen_server/dashboard/assets/{sharedSchema-uXN9FLLk.js → sharedSchema-Bw1_Wa7l.js} +1 -1
- zenml/zen_server/dashboard/assets/{stack-detail-query-XfZBiBP2.js → stack-detail-query-B_0R_fd6.js} +1 -1
- zenml/zen_server/dashboard/assets/{update-server-settings-mutation-BWmgVJwA.js → update-server-settings-mutation-D9qYhfaN.js} +1 -1
- zenml/zen_server/dashboard/assets/{url-BLwMbzES.js → url-Dh93fvh0.js} +1 -1
- zenml/zen_server/dashboard/index.html +3 -3
- zenml/zen_server/deploy/deployer.py +1 -1
- zenml/zen_server/rbac/rbac_sql_zen_store.py +3 -1
- zenml/zen_server/routers/webhook_endpoints.py +1 -2
- zenml/zen_stores/migrations/utils.py +1 -2
- zenml/zen_stores/migrations/versions/5330ba58bf20_rename_tables_and_foreign_keys.py +7 -9
- zenml/zen_stores/rest_zen_store.py +1 -1
- zenml/zen_stores/sql_zen_store.py +9 -3
- {zenml_nightly-0.71.0.dev20250109.dist-info → zenml_nightly-0.71.0.dev20250112.dist-info}/METADATA +2 -2
- {zenml_nightly-0.71.0.dev20250109.dist-info → zenml_nightly-0.71.0.dev20250112.dist-info}/RECORD +132 -132
- zenml/zen_server/dashboard/assets/page-B6XU7yYT.js +0 -2
- zenml/zen_server/dashboard/assets/page-Bg8OjTRe.js +0 -1
- {zenml_nightly-0.71.0.dev20250109.dist-info → zenml_nightly-0.71.0.dev20250112.dist-info}/LICENSE +0 -0
- {zenml_nightly-0.71.0.dev20250109.dist-info → zenml_nightly-0.71.0.dev20250112.dist-info}/WHEEL +0 -0
- {zenml_nightly-0.71.0.dev20250109.dist-info → zenml_nightly-0.71.0.dev20250112.dist-info}/entry_points.txt +0 -0
zenml/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.71.0.
|
1
|
+
0.71.0.dev20250112
|
zenml/cli/base.py
CHANGED
@@ -87,7 +87,7 @@ ZENML_PROJECT_TEMPLATES = dict(
|
|
87
87
|
),
|
88
88
|
nlp=ZenMLProjectTemplateLocation(
|
89
89
|
github_url="zenml-io/template-nlp",
|
90
|
-
github_tag="
|
90
|
+
github_tag="2025.01.08", # Make sure it is aligned with .github/workflows/update-templates-to-examples.yml
|
91
91
|
),
|
92
92
|
llm_finetuning=ZenMLProjectTemplateLocation(
|
93
93
|
github_url="zenml-io/template-llm-finetuning",
|
zenml/cli/formatter.py
CHANGED
zenml/cli/integration.py
CHANGED
@@ -83,7 +83,7 @@ def get_requirements(integration_name: Optional[str] = None) -> None:
|
|
83
83
|
else:
|
84
84
|
if requirements:
|
85
85
|
title(
|
86
|
-
f
|
86
|
+
f"Requirements for {integration_name or 'all integrations'}:\n"
|
87
87
|
)
|
88
88
|
declare(f"{requirements}")
|
89
89
|
warning(
|
zenml/cli/model_registry.py
CHANGED
@@ -183,8 +183,7 @@ def register_model_registry_subcommands() -> None: # noqa: C901
|
|
183
183
|
return
|
184
184
|
if not yes:
|
185
185
|
confirmation = cli_utils.confirmation(
|
186
|
-
f"Found Model with name {name}. Do you want to "
|
187
|
-
f"delete them?"
|
186
|
+
f"Found Model with name {name}. Do you want to delete them?"
|
188
187
|
)
|
189
188
|
if not confirmation:
|
190
189
|
cli_utils.declare("Model deletion canceled.")
|
zenml/cli/secret.py
CHANGED
@@ -347,8 +347,7 @@ def update_secret(
|
|
347
347
|
)
|
348
348
|
|
349
349
|
declare(
|
350
|
-
"You will now have a chance to update each secret pair "
|
351
|
-
"one by one."
|
350
|
+
"You will now have a chance to update each secret pair one by one."
|
352
351
|
)
|
353
352
|
secret_args_add_update = {}
|
354
353
|
for k, _ in secret.secret_values.items():
|
zenml/cli/service_connectors.py
CHANGED
@@ -1483,7 +1483,7 @@ def update_service_connector(
|
|
1483
1483
|
resource_type = None
|
1484
1484
|
title = (
|
1485
1485
|
"The connector is configured to access any of the supported "
|
1486
|
-
f
|
1486
|
+
f"resource types ({', '.join(available_resource_types)}). "
|
1487
1487
|
"Would you like to restrict it to a single resource type?"
|
1488
1488
|
)
|
1489
1489
|
else:
|
zenml/cli/stack.py
CHANGED
@@ -1073,8 +1073,7 @@ def set_active_stack_command(stack_name_or_id: str) -> None:
|
|
1073
1073
|
cli_utils.error(str(err))
|
1074
1074
|
|
1075
1075
|
cli_utils.declare(
|
1076
|
-
f"Active {scope} stack set to: "
|
1077
|
-
f"'{client.active_stack_model.name}'"
|
1076
|
+
f"Active {scope} stack set to: '{client.active_stack_model.name}'"
|
1078
1077
|
)
|
1079
1078
|
|
1080
1079
|
|
@@ -1763,7 +1762,7 @@ def _get_service_connector_info(
|
|
1763
1762
|
required = ""
|
1764
1763
|
for each_req in schema["required"]:
|
1765
1764
|
field = schema["properties"][each_req]
|
1766
|
-
required += f"[bold]{each_req}[/bold] [italic]({field.get('title','no description')})[/italic]\n"
|
1765
|
+
required += f"[bold]{each_req}[/bold] [italic]({field.get('title', 'no description')})[/italic]\n"
|
1767
1766
|
choices.append([value.name, required])
|
1768
1767
|
|
1769
1768
|
selected_auth_idx = cli_utils.multi_choice_prompt(
|
zenml/cli/stack_components.py
CHANGED
@@ -266,7 +266,7 @@ def generate_stack_component_register_command(
|
|
266
266
|
client.get_service_connector(connector)
|
267
267
|
except KeyError as err:
|
268
268
|
cli_utils.error(
|
269
|
-
f"Could not find a connector '{connector}':
|
269
|
+
f"Could not find a connector '{connector}': {str(err)}"
|
270
270
|
)
|
271
271
|
|
272
272
|
with console.status(f"Registering {display_name} '{name}'...\n"):
|
@@ -971,8 +971,7 @@ def prompt_select_resource(
|
|
971
971
|
# Prompt the user to select a connector by its name or ID
|
972
972
|
while True:
|
973
973
|
connector_id = click.prompt(
|
974
|
-
"Please enter the name or ID of the connector you want "
|
975
|
-
"to use",
|
974
|
+
"Please enter the name or ID of the connector you want to use",
|
976
975
|
type=click.Choice(
|
977
976
|
[
|
978
977
|
str(connector.id)
|
@@ -1344,8 +1343,7 @@ def connect_stack_component_with_service_connector(
|
|
1344
1343
|
|
1345
1344
|
if not connector and not interactive:
|
1346
1345
|
cli_utils.error(
|
1347
|
-
"Please provide either a connector ID or set the interactive "
|
1348
|
-
"flag."
|
1346
|
+
"Please provide either a connector ID or set the interactive flag."
|
1349
1347
|
)
|
1350
1348
|
|
1351
1349
|
if connector and interactive:
|
@@ -1446,7 +1444,7 @@ def connect_stack_component_with_service_connector(
|
|
1446
1444
|
connector_model = client.get_service_connector(connector)
|
1447
1445
|
except KeyError as err:
|
1448
1446
|
cli_utils.error(
|
1449
|
-
f"Could not find a connector '{connector}':
|
1447
|
+
f"Could not find a connector '{connector}': {str(err)}"
|
1450
1448
|
)
|
1451
1449
|
|
1452
1450
|
connector_id = connector_model.id
|
zenml/cli/text_utils.py
CHANGED
@@ -77,7 +77,7 @@ def zenml_go_notebook_tutorial_message(ipynb_files: List[str]) -> Markdown:
|
|
77
77
|
|
78
78
|
The ZenML tutorial repository was cloned to your current working directory.
|
79
79
|
Within the repository you can get started on one of these notebooks:
|
80
|
-
{
|
80
|
+
{"".join(ipynb_files)}
|
81
81
|
Next we will start a Jupyter notebook server. Feel free to try your hand at our
|
82
82
|
tutorial notebooks. If your browser does not open automatically click one of the
|
83
83
|
links below.\n
|
zenml/cli/utils.py
CHANGED
@@ -1812,8 +1812,7 @@ def print_service_connector_configuration(
|
|
1812
1812
|
)
|
1813
1813
|
else:
|
1814
1814
|
declare(
|
1815
|
-
f"Service connector '{connector.name}' of type "
|
1816
|
-
f"'{connector.type}'."
|
1815
|
+
f"Service connector '{connector.name}' of type '{connector.type}'."
|
1817
1816
|
)
|
1818
1817
|
|
1819
1818
|
title_ = f"'{connector.name}' {connector.type} Service Connector Details"
|
@@ -1993,7 +1992,7 @@ def print_service_connector_resource_type(
|
|
1993
1992
|
message = f"{title}\n" if title else ""
|
1994
1993
|
emoji = replace_emojis(resource_type.emoji) if resource_type.emoji else ""
|
1995
1994
|
supported_auth_methods = [
|
1996
|
-
f
|
1995
|
+
f"{Emoji('lock')} {a}" for a in resource_type.auth_methods
|
1997
1996
|
]
|
1998
1997
|
message += (
|
1999
1998
|
f"{heading} {emoji} {resource_type.name} "
|
@@ -2117,7 +2116,7 @@ def print_service_connector_type(
|
|
2117
2116
|
"""
|
2118
2117
|
message = f"{title}\n" if title else ""
|
2119
2118
|
supported_auth_methods = [
|
2120
|
-
f
|
2119
|
+
f"{Emoji('lock')} {a.auth_method}" for a in connector_type.auth_methods
|
2121
2120
|
]
|
2122
2121
|
supported_resource_types = [
|
2123
2122
|
f"{replace_emojis(r.emoji)} {r.resource_type}"
|
@@ -2724,7 +2723,7 @@ def multi_choice_prompt(
|
|
2724
2723
|
*([f"Create a new {object_type}"] * len(headers)),
|
2725
2724
|
)
|
2726
2725
|
for i, one_choice in enumerate(choices):
|
2727
|
-
table.add_row(f"[{i+i_shift}]", *[str(x) for x in one_choice])
|
2726
|
+
table.add_row(f"[{i + i_shift}]", *[str(x) for x in one_choice])
|
2728
2727
|
Console().print(table)
|
2729
2728
|
|
2730
2729
|
selected = Prompt.ask(
|
zenml/client.py
CHANGED
@@ -4669,10 +4669,7 @@ class Client(metaclass=ClientMetaClass):
|
|
4669
4669
|
hydrate=hydrate,
|
4670
4670
|
)
|
4671
4671
|
|
4672
|
-
msg =
|
4673
|
-
f"No secret found with name, ID or prefix "
|
4674
|
-
f"'{name_id_or_prefix}'"
|
4675
|
-
)
|
4672
|
+
msg = f"No secret found with name, ID or prefix '{name_id_or_prefix}'"
|
4676
4673
|
if scope is not None:
|
4677
4674
|
msg += f" in scope '{scope}'"
|
4678
4675
|
|
zenml/constants.py
CHANGED
@@ -429,6 +429,7 @@ PAGE_SIZE_MAXIMUM: int = handle_int_env_var(
|
|
429
429
|
)
|
430
430
|
FILTERING_DATETIME_FORMAT: str = "%Y-%m-%d %H:%M:%S"
|
431
431
|
SORT_PIPELINES_BY_LATEST_RUN_KEY = "latest_run"
|
432
|
+
SORT_BY_LATEST_VERSION_KEY = "latest_version"
|
432
433
|
|
433
434
|
# Metadata constants
|
434
435
|
METADATA_ORCHESTRATOR_URL = "orchestrator_url"
|
@@ -13,6 +13,8 @@
|
|
13
13
|
# permissions and limitations under the License.
|
14
14
|
"""Base class for entrypoint configurations that run a single step."""
|
15
15
|
|
16
|
+
import os
|
17
|
+
import sys
|
16
18
|
from typing import TYPE_CHECKING, Any, List, Set
|
17
19
|
|
18
20
|
from zenml.client import Client
|
@@ -153,10 +155,23 @@ class StepEntrypointConfiguration(BaseEntrypointConfiguration):
|
|
153
155
|
|
154
156
|
step_name = self.entrypoint_args[STEP_NAME_OPTION]
|
155
157
|
|
158
|
+
# Change the working directory to make sure we're in the correct
|
159
|
+
# directory where the files in the Docker image should be included.
|
160
|
+
# This is necessary as some services overwrite the working directory
|
161
|
+
# configured in the Docker image itself.
|
162
|
+
os.makedirs("/app", exist_ok=True)
|
163
|
+
os.chdir("/app")
|
164
|
+
|
156
165
|
self.download_code_if_necessary(
|
157
166
|
deployment=deployment, step_name=step_name
|
158
167
|
)
|
159
168
|
|
169
|
+
# If the working directory is not in the sys.path, we include it to make
|
170
|
+
# sure user code gets correctly imported.
|
171
|
+
cwd = os.getcwd()
|
172
|
+
if cwd not in sys.path:
|
173
|
+
sys.path.insert(0, cwd)
|
174
|
+
|
160
175
|
pipeline_name = deployment.pipeline_configuration.name
|
161
176
|
|
162
177
|
step = deployment.step_configurations[step_name]
|
@@ -48,7 +48,7 @@ class AzureIntegration(Integration):
|
|
48
48
|
"azure-mgmt-containerservice>=20.0.0",
|
49
49
|
"azure-storage-blob==12.17.0", # temporary fix for https://github.com/Azure/azure-sdk-for-python/issues/32056
|
50
50
|
"kubernetes",
|
51
|
-
"azure-ai-ml==1.
|
51
|
+
"azure-ai-ml==1.23.1",
|
52
52
|
# In azureml/core/_metrics.py:212 of azureml-core 1.56.0, they use
|
53
53
|
# an attribute that was removed in Numpy 2.0. However, AzureML itself
|
54
54
|
# does not have a limitation on numpy.
|
@@ -159,7 +159,7 @@ def create_or_get_compute(
|
|
159
159
|
# If the compute target does not exist create it
|
160
160
|
except ResourceNotFoundError:
|
161
161
|
logger.info(
|
162
|
-
"Can not find the compute target with name:
|
162
|
+
f"Can not find the compute target with name: '{compute_name}':"
|
163
163
|
)
|
164
164
|
|
165
165
|
if settings.mode == AzureMLComputeTypes.COMPUTE_INSTANCE:
|
@@ -67,11 +67,6 @@ class AzureMLEntrypointConfiguration(StepEntrypointConfiguration):
|
|
67
67
|
# Set the environmental variables first
|
68
68
|
self._set_env_variables()
|
69
69
|
|
70
|
-
# Azure automatically changes the working directory, we have to set it
|
71
|
-
# back to /app before running the step.
|
72
|
-
os.makedirs("/app", exist_ok=True)
|
73
|
-
os.chdir("/app")
|
74
|
-
|
75
70
|
# Run the step
|
76
71
|
super().run()
|
77
72
|
|
@@ -327,9 +327,9 @@ class BitbucketWebhookEventSourceHandler(BaseWebhookEventSourceHandler):
|
|
327
327
|
config: Event source configuration instantiated from the response.
|
328
328
|
"""
|
329
329
|
assert isinstance(config, BitbucketWebhookEventSourceConfiguration)
|
330
|
-
assert (
|
331
|
-
|
332
|
-
)
|
330
|
+
assert event_source.user is not None, (
|
331
|
+
"User is not set for event source"
|
332
|
+
)
|
333
333
|
|
334
334
|
secret_key_value = random_str(12)
|
335
335
|
webhook_secret = SecretRequest(
|
@@ -495,9 +495,7 @@ class DatabricksOrchestrator(WheeledOrchestrator):
|
|
495
495
|
Returns:
|
496
496
|
A dictionary of metadata.
|
497
497
|
"""
|
498
|
-
run_url = (
|
499
|
-
f"{self.config.host}/jobs/" f"{self.get_orchestrator_run_id()}"
|
500
|
-
)
|
498
|
+
run_url = f"{self.config.host}/jobs/{self.get_orchestrator_run_id()}"
|
501
499
|
return {
|
502
500
|
METADATA_ORCHESTRATOR_URL: Uri(run_url),
|
503
501
|
}
|
@@ -211,7 +211,7 @@ class EvidentlyMetricConfig(BaseModel):
|
|
211
211
|
else:
|
212
212
|
raise ValueError(f"Invalid Evidently Metric class: {metric}")
|
213
213
|
|
214
|
-
class_path = f"{metric_class.__module__}.
|
214
|
+
class_path = f"{metric_class.__module__}.{metric_class.__name__}"
|
215
215
|
|
216
216
|
config = cls(
|
217
217
|
class_path=class_path,
|
@@ -291,7 +291,7 @@ class EvidentlyMetricConfig(BaseModel):
|
|
291
291
|
f"Invalid Evidently Metric or MetricPreset class: {metric}"
|
292
292
|
)
|
293
293
|
|
294
|
-
class_path = f"{metric_class.__module__}.
|
294
|
+
class_path = f"{metric_class.__module__}.{metric_class.__name__}"
|
295
295
|
|
296
296
|
config = cls(class_path=class_path, parameters=parameters)
|
297
297
|
|
@@ -205,7 +205,7 @@ class EvidentlyTestConfig(BaseModel):
|
|
205
205
|
else:
|
206
206
|
raise ValueError(f"Invalid Evidently Test class: {test}")
|
207
207
|
|
208
|
-
class_path = f"{test_class.__module__}.
|
208
|
+
class_path = f"{test_class.__module__}.{test_class.__name__}"
|
209
209
|
|
210
210
|
config = cls(
|
211
211
|
class_path=class_path,
|
@@ -284,7 +284,7 @@ class EvidentlyTestConfig(BaseModel):
|
|
284
284
|
f"Invalid Evidently Test or TestPreset class: {test}"
|
285
285
|
)
|
286
286
|
|
287
|
-
class_path = f"{test_class.__module__}.
|
287
|
+
class_path = f"{test_class.__module__}.{test_class.__name__}"
|
288
288
|
config = cls(class_path=class_path, parameters=parameters)
|
289
289
|
|
290
290
|
# Try to instantiate the configuration to check if the parameters are
|
@@ -169,7 +169,7 @@ class GCPUserAccountCredentials(AuthenticationConfig):
|
|
169
169
|
if missing_fields:
|
170
170
|
raise ValueError(
|
171
171
|
f"GCP user account credentials JSON is missing required "
|
172
|
-
f
|
172
|
+
f"fields: {', '.join(list(missing_fields))}"
|
173
173
|
)
|
174
174
|
|
175
175
|
if user_account_info["type"] != "authorized_user":
|
@@ -276,7 +276,7 @@ class GCPServiceAccountCredentials(AuthenticationConfig):
|
|
276
276
|
if missing_fields:
|
277
277
|
raise ValueError(
|
278
278
|
f"GCP service account credentials JSON is missing required "
|
279
|
-
f
|
279
|
+
f"fields: {', '.join(list(missing_fields))}"
|
280
280
|
)
|
281
281
|
|
282
282
|
if service_account_info["type"] != "service_account":
|
@@ -376,7 +376,7 @@ class GCPExternalAccountCredentials(AuthenticationConfig):
|
|
376
376
|
if missing_fields:
|
377
377
|
raise ValueError(
|
378
378
|
f"GCP external account credentials JSON is missing required "
|
379
|
-
f
|
379
|
+
f"fields: {', '.join(list(missing_fields))}"
|
380
380
|
)
|
381
381
|
|
382
382
|
if external_account_info["type"] != "external_account":
|
@@ -353,9 +353,9 @@ class GithubWebhookEventSourceHandler(BaseWebhookEventSourceHandler):
|
|
353
353
|
config: Event source configuration instantiated from the response.
|
354
354
|
"""
|
355
355
|
assert isinstance(config, GithubWebhookEventSourceConfiguration)
|
356
|
-
assert (
|
357
|
-
|
358
|
-
)
|
356
|
+
assert event_source.user is not None, (
|
357
|
+
"User is not set for event source"
|
358
|
+
)
|
359
359
|
|
360
360
|
secret_key_value = random_str(12)
|
361
361
|
webhook_secret = SecretRequest(
|
zenml/integrations/s3/utils.py
CHANGED
@@ -31,8 +31,7 @@ def split_s3_path(s3_path: str) -> Tuple[str, str]:
|
|
31
31
|
"""
|
32
32
|
if not s3_path.startswith("s3://"):
|
33
33
|
raise ValueError(
|
34
|
-
f"Invalid S3 URI given: {s3_path}. "
|
35
|
-
"It should start with `s3://`."
|
34
|
+
f"Invalid S3 URI given: {s3_path}. It should start with `s3://`."
|
36
35
|
)
|
37
36
|
path_parts = s3_path.replace("s3://", "").split("/")
|
38
37
|
bucket = path_parts.pop(0)
|
zenml/logger.py
CHANGED
@@ -136,7 +136,7 @@ def set_root_verbosity() -> None:
|
|
136
136
|
|
137
137
|
logging.root.setLevel(level=level.value)
|
138
138
|
get_logger(__name__).debug(
|
139
|
-
f"Logging set to level:
|
139
|
+
f"Logging set to level: {logging.getLevelName(level.value)}"
|
140
140
|
)
|
141
141
|
else:
|
142
142
|
logging.disable(sys.maxsize)
|
zenml/models/v2/base/scoped.py
CHANGED
@@ -245,6 +245,8 @@ class UserScopedFilter(BaseFilter):
|
|
245
245
|
UserSchema, getattr(table, "user_id") == UserSchema.id
|
246
246
|
)
|
247
247
|
|
248
|
+
query = query.add_columns(UserSchema.name)
|
249
|
+
|
248
250
|
if operand == SorterOps.ASCENDING:
|
249
251
|
query = query.order_by(asc(column))
|
250
252
|
else:
|
@@ -449,6 +451,8 @@ class WorkspaceScopedFilter(UserScopedFilter):
|
|
449
451
|
getattr(table, "workspace_id") == WorkspaceSchema.id,
|
450
452
|
)
|
451
453
|
|
454
|
+
query = query.add_columns(WorkspaceSchema.name)
|
455
|
+
|
452
456
|
if operand == SorterOps.ASCENDING:
|
453
457
|
query = query.order_by(asc(column))
|
454
458
|
else:
|
@@ -470,10 +474,9 @@ class WorkspaceScopedTaggableFilter(WorkspaceScopedFilter):
|
|
470
474
|
*WorkspaceScopedFilter.FILTER_EXCLUDE_FIELDS,
|
471
475
|
"tag",
|
472
476
|
]
|
473
|
-
|
474
477
|
CUSTOM_SORTING_OPTIONS: ClassVar[List[str]] = [
|
475
478
|
*WorkspaceScopedFilter.CUSTOM_SORTING_OPTIONS,
|
476
|
-
"
|
479
|
+
"tags",
|
477
480
|
]
|
478
481
|
|
479
482
|
def apply_filter(
|
@@ -540,8 +543,8 @@ class WorkspaceScopedTaggableFilter(WorkspaceScopedFilter):
|
|
540
543
|
"""
|
541
544
|
sort_by, operand = self.sorting_params
|
542
545
|
|
543
|
-
if sort_by == "
|
544
|
-
from sqlmodel import
|
546
|
+
if sort_by == "tags":
|
547
|
+
from sqlmodel import asc, desc, func, select
|
545
548
|
|
546
549
|
from zenml.enums import SorterOps, TaggableResourceTypes
|
547
550
|
from zenml.zen_stores.schemas import (
|
@@ -566,35 +569,36 @@ class WorkspaceScopedTaggableFilter(WorkspaceScopedFilter):
|
|
566
569
|
RunTemplateSchema: TaggableResourceTypes.RUN_TEMPLATE,
|
567
570
|
}
|
568
571
|
|
569
|
-
|
570
|
-
|
571
|
-
|
572
|
-
|
573
|
-
|
574
|
-
|
575
|
-
|
576
|
-
|
572
|
+
sorted_tags = (
|
573
|
+
select(TagResourceSchema.resource_id, TagSchema.name)
|
574
|
+
.join(TagSchema, TagResourceSchema.tag_id == TagSchema.id) # type: ignore[arg-type]
|
575
|
+
.filter(
|
576
|
+
TagResourceSchema.resource_type # type: ignore[arg-type]
|
577
|
+
== resource_type_mapping[table]
|
578
|
+
)
|
579
|
+
.order_by(
|
580
|
+
asc(TagResourceSchema.resource_id), asc(TagSchema.name)
|
577
581
|
)
|
578
|
-
|
579
|
-
|
582
|
+
).alias("sorted_tags")
|
583
|
+
|
584
|
+
tags_subquery = (
|
585
|
+
select(
|
586
|
+
sorted_tags.c.resource_id,
|
587
|
+
func.group_concat(sorted_tags.c.name, ", ").label(
|
588
|
+
"tags_list"
|
589
|
+
),
|
590
|
+
).group_by(sorted_tags.c.resource_id)
|
591
|
+
).alias("tags_subquery")
|
592
|
+
|
593
|
+
query = query.add_columns(tags_subquery.c.tags_list).outerjoin(
|
594
|
+
tags_subquery, table.id == tags_subquery.c.resource_id
|
580
595
|
)
|
581
596
|
|
597
|
+
# Apply ordering based on the tags list
|
582
598
|
if operand == SorterOps.ASCENDING:
|
583
|
-
query = query.order_by(
|
584
|
-
asc(
|
585
|
-
func.group_concat(TagSchema.name, ",").label(
|
586
|
-
"tags_list"
|
587
|
-
)
|
588
|
-
)
|
589
|
-
)
|
599
|
+
query = query.order_by(asc("tags_list"))
|
590
600
|
else:
|
591
|
-
query = query.order_by(
|
592
|
-
desc(
|
593
|
-
func.group_concat(TagSchema.name, ",").label(
|
594
|
-
"tags_list"
|
595
|
-
)
|
596
|
-
)
|
597
|
-
)
|
601
|
+
query = query.order_by(desc("tags_list"))
|
598
602
|
|
599
603
|
return query
|
600
604
|
|
zenml/models/v2/core/artifact.py
CHANGED
@@ -13,12 +13,21 @@
|
|
13
13
|
# permissions and limitations under the License.
|
14
14
|
"""Models representing artifacts."""
|
15
15
|
|
16
|
-
from typing import
|
16
|
+
from typing import (
|
17
|
+
TYPE_CHECKING,
|
18
|
+
Any,
|
19
|
+
ClassVar,
|
20
|
+
Dict,
|
21
|
+
List,
|
22
|
+
Optional,
|
23
|
+
Type,
|
24
|
+
TypeVar,
|
25
|
+
)
|
17
26
|
from uuid import UUID
|
18
27
|
|
19
28
|
from pydantic import BaseModel, Field
|
20
29
|
|
21
|
-
from zenml.constants import STR_FIELD_MAX_LENGTH
|
30
|
+
from zenml.constants import SORT_BY_LATEST_VERSION_KEY, STR_FIELD_MAX_LENGTH
|
22
31
|
from zenml.models.v2.base.base import (
|
23
32
|
BaseDatedResponseBody,
|
24
33
|
BaseIdentifiedResponse,
|
@@ -31,6 +40,11 @@ from zenml.models.v2.core.tag import TagResponse
|
|
31
40
|
|
32
41
|
if TYPE_CHECKING:
|
33
42
|
from zenml.models.v2.core.artifact_version import ArtifactVersionResponse
|
43
|
+
from zenml.zen_stores.schemas import BaseSchema
|
44
|
+
|
45
|
+
AnySchema = TypeVar("AnySchema", bound=BaseSchema)
|
46
|
+
|
47
|
+
AnyQuery = TypeVar("AnyQuery", bound=Any)
|
34
48
|
|
35
49
|
# ------------------ Request Model ------------------
|
36
50
|
|
@@ -174,3 +188,73 @@ class ArtifactFilter(WorkspaceScopedTaggableFilter):
|
|
174
188
|
|
175
189
|
name: Optional[str] = None
|
176
190
|
has_custom_name: Optional[bool] = None
|
191
|
+
|
192
|
+
CUSTOM_SORTING_OPTIONS: ClassVar[List[str]] = [
|
193
|
+
*WorkspaceScopedTaggableFilter.CUSTOM_SORTING_OPTIONS,
|
194
|
+
SORT_BY_LATEST_VERSION_KEY,
|
195
|
+
]
|
196
|
+
|
197
|
+
def apply_sorting(
|
198
|
+
self,
|
199
|
+
query: AnyQuery,
|
200
|
+
table: Type["AnySchema"],
|
201
|
+
) -> AnyQuery:
|
202
|
+
"""Apply sorting to the query for Artifacts.
|
203
|
+
|
204
|
+
Args:
|
205
|
+
query: The query to which to apply the sorting.
|
206
|
+
table: The query table.
|
207
|
+
|
208
|
+
Returns:
|
209
|
+
The query with sorting applied.
|
210
|
+
"""
|
211
|
+
from sqlmodel import asc, case, col, desc, func, select
|
212
|
+
|
213
|
+
from zenml.enums import SorterOps
|
214
|
+
from zenml.zen_stores.schemas import (
|
215
|
+
ArtifactSchema,
|
216
|
+
ArtifactVersionSchema,
|
217
|
+
)
|
218
|
+
|
219
|
+
sort_by, operand = self.sorting_params
|
220
|
+
|
221
|
+
if sort_by == SORT_BY_LATEST_VERSION_KEY:
|
222
|
+
# Subquery to find the latest version per artifact
|
223
|
+
latest_version_subquery = (
|
224
|
+
select(
|
225
|
+
ArtifactSchema.id,
|
226
|
+
case(
|
227
|
+
(
|
228
|
+
func.max(ArtifactVersionSchema.created).is_(None),
|
229
|
+
ArtifactSchema.created,
|
230
|
+
),
|
231
|
+
else_=func.max(ArtifactVersionSchema.created),
|
232
|
+
).label("latest_version_created"),
|
233
|
+
)
|
234
|
+
.outerjoin(
|
235
|
+
ArtifactVersionSchema,
|
236
|
+
ArtifactSchema.id == ArtifactVersionSchema.artifact_id, # type: ignore[arg-type]
|
237
|
+
)
|
238
|
+
.group_by(col(ArtifactSchema.id))
|
239
|
+
.subquery()
|
240
|
+
)
|
241
|
+
|
242
|
+
query = query.add_columns(
|
243
|
+
latest_version_subquery.c.latest_version_created,
|
244
|
+
).where(ArtifactSchema.id == latest_version_subquery.c.id)
|
245
|
+
|
246
|
+
# Apply sorting based on the operand
|
247
|
+
if operand == SorterOps.ASCENDING:
|
248
|
+
query = query.order_by(
|
249
|
+
asc(latest_version_subquery.c.latest_version_created),
|
250
|
+
asc(ArtifactSchema.id),
|
251
|
+
)
|
252
|
+
else:
|
253
|
+
query = query.order_by(
|
254
|
+
desc(latest_version_subquery.c.latest_version_created),
|
255
|
+
desc(ArtifactSchema.id),
|
256
|
+
)
|
257
|
+
return query
|
258
|
+
|
259
|
+
# For other sorting cases, delegate to the parent class
|
260
|
+
return super().apply_sorting(query=query, table=table)
|