zenml-nightly 0.68.1.dev20241106__py3-none-any.whl → 0.70.0.dev20241116__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.
- README.md +1 -1
- RELEASE_NOTES.md +77 -0
- zenml/VERSION +1 -1
- zenml/__init__.py +2 -0
- zenml/artifacts/external_artifact.py +2 -1
- zenml/artifacts/utils.py +138 -79
- zenml/cli/base.py +4 -4
- zenml/cli/model.py +1 -6
- zenml/cli/stack.py +1 -0
- zenml/client.py +29 -74
- zenml/config/server_config.py +17 -1
- zenml/constants.py +2 -7
- zenml/data_validators/base_data_validator.py +2 -2
- zenml/enums.py +20 -4
- zenml/exceptions.py +4 -0
- zenml/integrations/aws/orchestrators/sagemaker_orchestrator.py +20 -18
- zenml/integrations/azure/orchestrators/azureml_orchestrator.py +1 -1
- zenml/integrations/deepchecks/data_validators/deepchecks_data_validator.py +1 -1
- zenml/integrations/evidently/__init__.py +1 -1
- zenml/integrations/gcp/orchestrators/vertex_orchestrator.py +1 -1
- zenml/integrations/lightning/orchestrators/lightning_orchestrator.py +29 -9
- zenml/integrations/tensorboard/visualizers/tensorboard_visualizer.py +60 -54
- zenml/integrations/vllm/services/vllm_deployment.py +16 -7
- zenml/metadata/lazy_load.py +20 -7
- zenml/model/model.py +17 -64
- zenml/model/utils.py +5 -0
- zenml/models/__init__.py +0 -12
- zenml/models/v2/base/filter.py +121 -8
- zenml/models/v2/core/artifact_version.py +42 -7
- zenml/models/v2/core/model_version.py +26 -5
- zenml/models/v2/core/pipeline_run.py +25 -6
- zenml/models/v2/core/run_metadata.py +2 -217
- zenml/models/v2/core/step_run.py +62 -24
- zenml/orchestrators/base_orchestrator.py +12 -1
- zenml/orchestrators/input_utils.py +44 -19
- zenml/orchestrators/step_launcher.py +4 -3
- zenml/orchestrators/step_run_utils.py +19 -15
- zenml/orchestrators/step_runner.py +21 -13
- zenml/orchestrators/utils.py +45 -26
- zenml/stack_deployments/aws_stack_deployment.py +23 -6
- zenml/stack_deployments/azure_stack_deployment.py +28 -5
- zenml/stack_deployments/gcp_stack_deployment.py +25 -8
- zenml/stack_deployments/stack_deployment.py +3 -5
- zenml/steps/base_step.py +1 -1
- zenml/steps/entrypoint_function_utils.py +3 -5
- zenml/steps/step_context.py +3 -2
- zenml/steps/utils.py +13 -2
- zenml/utils/metadata_utils.py +335 -0
- zenml/zen_server/auth.py +221 -3
- zenml/zen_server/cache.py +208 -0
- zenml/zen_server/dashboard/assets/{404-DT4QRUqN.js → 404-NVXKFp-x.js} +1 -1
- zenml/zen_server/dashboard/assets/{@radix-DP6vWzyx.js → @radix-DeK6qiuw.js} +1 -1
- zenml/zen_server/dashboard/assets/{@react-router-BMhZulnd.js → @react-router-B3Z5rLr2.js} +1 -1
- zenml/zen_server/dashboard/assets/{@reactflow-8U9qNlMR.js → @reactflow-CK0KJUen.js} +2 -2
- zenml/zen_server/dashboard/assets/{@tanstack-BUCbhJyH.js → @tanstack-DT5WLu9C.js} +1 -1
- zenml/zen_server/dashboard/assets/AlertDialogDropdownItem-DezXKmDf.js +1 -0
- zenml/zen_server/dashboard/assets/{CodeSnippet-CqybNv0k.js → CodeSnippet-JzR8CEtw.js} +2 -2
- zenml/zen_server/dashboard/assets/{CollapsibleCard-0r_8G2Lj.js → CollapsibleCard-DQW_ktMO.js} +1 -1
- zenml/zen_server/dashboard/assets/{Commands-BDjgBQKi.js → Commands-DL2kwkRd.js} +1 -1
- zenml/zen_server/dashboard/assets/ComponentBadge-D_g62Wv8.js +1 -0
- zenml/zen_server/dashboard/assets/{CopyButton-C745BrKi.js → CopyButton-LNcWaa14.js} +1 -1
- zenml/zen_server/dashboard/assets/{CsvVizualization-PpAq0CeZ.js → CsvVizualization-DknpE5ej.js} +5 -5
- zenml/zen_server/dashboard/assets/{DialogItem-DcVCZEew.js → DialogItem-Bxf8FuAT.js} +1 -1
- zenml/zen_server/dashboard/assets/{DisplayDate-BeXgUG_C.js → DisplayDate-CDMUcQHS.js} +1 -1
- zenml/zen_server/dashboard/assets/{EmptyState-DeK7H4pr.js → EmptyState-BzdlCwp3.js} +1 -1
- zenml/zen_server/dashboard/assets/{Error-BMlzibXj.js → Error-DYflYyps.js} +1 -1
- zenml/zen_server/dashboard/assets/ExecutionStatus-C7zyIQKZ.js +1 -0
- zenml/zen_server/dashboard/assets/{Helpbox-BLf40fLV.js → Helpbox-oYSGpLqd.js} +1 -1
- zenml/zen_server/dashboard/assets/{Infobox-BwisKifi.js → Infobox-Cx4xGoXR.js} +1 -1
- zenml/zen_server/dashboard/assets/{InlineAvatar-jEgodSgX.js → InlineAvatar-DiGOWNKF.js} +1 -1
- zenml/zen_server/dashboard/assets/{Lock-3lLt1ih0.js → Lock-CYYy18Mm.js} +1 -1
- zenml/zen_server/dashboard/assets/{MarkdownVisualization-8O9kTr-2.js → MarkdownVisualization-ylXaAxev.js} +1 -1
- zenml/zen_server/dashboard/assets/NestedCollapsible-DYbgyKxK.js +1 -0
- zenml/zen_server/dashboard/assets/{NumberBox-T9eELfLZ.js → NumberBox-Dtp3J6g5.js} +1 -1
- zenml/zen_server/dashboard/assets/Partials-03iZf8-N.js +1 -0
- zenml/zen_server/dashboard/assets/{PasswordChecker-CW0kqY0W.js → PasswordChecker-B0nadgh6.js} +1 -1
- zenml/zen_server/dashboard/assets/ProBadge-D_EB8HNo.js +1 -0
- zenml/zen_server/dashboard/assets/ProCta-DqNS4v3x.js +1 -0
- zenml/zen_server/dashboard/assets/ProviderIcon-Bki2aw8w.js +1 -0
- zenml/zen_server/dashboard/assets/{ProviderRadio-BROY1700.js → ProviderRadio-8f43sPD4.js} +1 -1
- zenml/zen_server/dashboard/assets/RunSelector-DkPiIiNr.js +1 -0
- zenml/zen_server/dashboard/assets/RunsBody-07YEO7qI.js +1 -0
- zenml/zen_server/dashboard/assets/SearchField-lp1KgU4e.js +1 -0
- zenml/zen_server/dashboard/assets/{SecretTooltip-C_qByGWB.js → SecretTooltip-CgnbyeOx.js} +1 -1
- zenml/zen_server/dashboard/assets/{SetPassword-7pRB00El.js → SetPassword-CpP418A2.js} +1 -1
- zenml/zen_server/dashboard/assets/StackList-WvuKQusZ.js +1 -0
- zenml/zen_server/dashboard/assets/Tabs-BktHkCJJ.js +1 -0
- zenml/zen_server/dashboard/assets/Tick-BlMoIlJT.js +1 -0
- zenml/zen_server/dashboard/assets/{UpdatePasswordSchemas-DckMEkFf.js → UpdatePasswordSchemas-Sc0A0pP-.js} +1 -1
- zenml/zen_server/dashboard/assets/{UsageReason-DVceN14P.js → UsageReason-YYduL4fj.js} +1 -1
- zenml/zen_server/dashboard/assets/{WizardFooter-CW0Cvd70.js → WizardFooter-dgmizSJC.js} +1 -1
- zenml/zen_server/dashboard/assets/all-pipeline-runs-query-D-c2G6lV.js +1 -0
- zenml/zen_server/dashboard/assets/check-DloQpStc.js +1 -0
- zenml/zen_server/dashboard/assets/{check-circle-Dwxliy1Z.js → check-circle-jNbX5-sR.js} +1 -1
- zenml/zen_server/dashboard/assets/{chevron-down-8wLBS5pQ.js → chevron-down-6JyMkfjR.js} +1 -1
- zenml/zen_server/dashboard/assets/{chevron-right-double-DoD8iXWM.js → chevron-right-double-D7ojK9Co.js} +1 -1
- zenml/zen_server/dashboard/assets/{code-browser-CZUQs3Wa.js → code-browser-CUFUIHfp.js} +1 -1
- zenml/zen_server/dashboard/assets/{copy-CaSMXwiU.js → copy-C8XQA2Ug.js} +1 -1
- zenml/zen_server/dashboard/assets/create-stack-DM_JPgef.js +1 -0
- zenml/zen_server/dashboard/assets/delete-run-CJdh1P_h.js +1 -0
- zenml/zen_server/dashboard/assets/{docker-BFNgg-z3.js → docker-BdA9vrnW.js} +1 -1
- zenml/zen_server/dashboard/assets/{dots-horizontal-DK5Duzx4.js → dots-horizontal-otGBOSDJ.js} +1 -1
- zenml/zen_server/dashboard/assets/{form-schemas-1AyOCx90.js → form-schemas-K6FYKjwa.js} +1 -1
- zenml/zen_server/dashboard/assets/{gcp-7M2Yf3ZK.js → gcp-CFtm4BA7.js} +1 -1
- zenml/zen_server/dashboard/assets/{help-Dam461dC.js → help-Cc9bBIJH.js} +1 -1
- zenml/zen_server/dashboard/assets/index-B1mVPYxf.js +1 -0
- zenml/zen_server/dashboard/assets/index-BAkC7FXi.js +1 -0
- zenml/zen_server/dashboard/assets/{index-QQb7wQEC.js → index-CCOPpudF.js} +8 -8
- zenml/zen_server/dashboard/assets/index-CEV4Cvaf.js +1 -0
- zenml/zen_server/dashboard/assets/index-DlGvJQPn.css +1 -0
- zenml/zen_server/dashboard/assets/{index-BVJ8n2-j.js → index-Uu49AX48.js} +1 -1
- zenml/zen_server/dashboard/assets/{index.esm-cuVep_NJ.js → index.esm-Dy6Z9Ung.js} +1 -1
- zenml/zen_server/dashboard/assets/{kubernetes--g7r02Zu.js → kubernetes-B2wmAJ1d.js} +1 -1
- zenml/zen_server/dashboard/assets/{layout-DCSYN7-C.js → layout-BtHBmE4w.js} +1 -1
- zenml/zen_server/dashboard/assets/{link-external-CBEk6kEG.js → link-external-b9AXw_sW.js} +1 -1
- zenml/zen_server/dashboard/assets/{login-mutation-DTcAFP1l.js → login-mutation-hf-lK87O.js} +1 -1
- zenml/zen_server/dashboard/assets/{logs-D5bdJGur.js → logs-WMSM52RF.js} +1 -1
- zenml/zen_server/dashboard/assets/{not-found-Cc-JkRH2.js → not-found-BGirLjU-.js} +1 -1
- zenml/zen_server/dashboard/assets/{package-Cs35Szwh.js → package-C6uypY4h.js} +1 -1
- zenml/zen_server/dashboard/assets/page-0JE_-Ec1.js +1 -0
- zenml/zen_server/dashboard/assets/{page-DH_Z7iW1.js → page-6m6yHHlE.js} +1 -1
- zenml/zen_server/dashboard/assets/page-BDigxVpo.js +1 -0
- zenml/zen_server/dashboard/assets/page-BR68V0V1.js +1 -0
- zenml/zen_server/dashboard/assets/page-BRLpxOt0.js +1 -0
- zenml/zen_server/dashboard/assets/{page-BQQKaabe.js → page-BU7huvKw.js} +3 -3
- zenml/zen_server/dashboard/assets/page-BvqLv2Ky.js +1 -0
- zenml/zen_server/dashboard/assets/page-C00YAkaB.js +1 -0
- zenml/zen_server/dashboard/assets/{page-N4qoPHKb.js → page-CD-DcWoy.js} +1 -1
- zenml/zen_server/dashboard/assets/page-COXXJj1k.js +1 -0
- zenml/zen_server/dashboard/assets/page-CbpvrsDL.js +1 -0
- zenml/zen_server/dashboard/assets/page-CdMWnQak.js +1 -0
- zenml/zen_server/dashboard/assets/{page-ClUVkl-O.js → page-CjGdWY13.js} +1 -1
- zenml/zen_server/dashboard/assets/page-CwxrFarU.js +1 -0
- zenml/zen_server/dashboard/assets/{page-DLixvR-7.js → page-D01JhjQB.js} +1 -1
- zenml/zen_server/dashboard/assets/page-D6uU2ax4.js +1 -0
- zenml/zen_server/dashboard/assets/page-D7S3aCbF.js +1 -0
- zenml/zen_server/dashboard/assets/{page-9yplj5JT.js → page-DLC-bNBP.js} +1 -1
- zenml/zen_server/dashboard/assets/page-DXSTpqRD.js +1 -0
- zenml/zen_server/dashboard/assets/{page-DzpVUZ8f.js → page-DakHVWXF.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-DIOXwhiD.js → page-Df-Fw0aq.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-B-y2XKIc.js → page-DfbXf_8s.js} +1 -1
- zenml/zen_server/dashboard/assets/page-DjRJCGb3.js +1 -0
- zenml/zen_server/dashboard/assets/{page-C0N5q3l7.js → page-Djikxq_S.js} +1 -1
- zenml/zen_server/dashboard/assets/page-Dnovpa0i.js +3 -0
- zenml/zen_server/dashboard/assets/page-Dot3LPmL.js +1 -0
- zenml/zen_server/dashboard/assets/page-Vcxara9U.js +1 -0
- zenml/zen_server/dashboard/assets/page-Xynx4btY.js +14 -0
- zenml/zen_server/dashboard/assets/page-YpKAqVSa.js +1 -0
- zenml/zen_server/dashboard/assets/page-yYC9OI-E.js +1 -0
- zenml/zen_server/dashboard/assets/{persist-DNb5cdrU.js → persist-Coz7ZWvz.js} +1 -1
- zenml/zen_server/dashboard/assets/{persist-CP0JmYZ4.js → persist-GjC8PZoC.js} +1 -1
- zenml/zen_server/dashboard/assets/{plus-C9IxgN2M.js → plus-tf1V2hTJ.js} +1 -1
- zenml/zen_server/dashboard/assets/{refresh-BVu22P_C.js → refresh-BjOeWlEq.js} +1 -1
- zenml/zen_server/dashboard/assets/{rocket-CONEmRmB.js → rocket-DjT2cDvG.js} +1 -1
- zenml/zen_server/dashboard/assets/sharedSchema-CQb14VSr.js +14 -0
- zenml/zen_server/dashboard/assets/stack-detail-query-OPEW-cDJ.js +1 -0
- zenml/zen_server/dashboard/assets/{tick-circle-CM1ZScbQ.js → tick-circle-BEX_Tp4v.js} +1 -1
- zenml/zen_server/dashboard/assets/{trash-DkJHMOg7.js → trash-arLUMWMS.js} +1 -1
- zenml/zen_server/dashboard/assets/{update-server-settings-mutation-DsU8cNVl.js → update-server-settings-mutation-LwuQfHYn.js} +1 -1
- zenml/zen_server/dashboard/assets/upgrade-form-CwRHBuXB.webp +0 -0
- zenml/zen_server/dashboard/assets/url-CkvKAnwF.js +1 -0
- zenml/zen_server/dashboard/assets/{zod-D89GC_vc.js → zod-BwEbpOxH.js} +1 -1
- zenml/zen_server/dashboard/index.html +7 -7
- zenml/zen_server/deploy/helm/Chart.yaml +1 -1
- zenml/zen_server/deploy/helm/README.md +2 -2
- zenml/zen_server/exceptions.py +2 -0
- zenml/zen_server/jwt.py +30 -13
- zenml/zen_server/rbac/endpoint_utils.py +43 -1
- zenml/zen_server/rbac/utils.py +0 -2
- zenml/zen_server/routers/artifact_version_endpoints.py +27 -1
- zenml/zen_server/routers/auth_endpoints.py +134 -102
- zenml/zen_server/routers/logs_endpoints.py +66 -0
- zenml/zen_server/routers/workspaces_endpoints.py +3 -4
- zenml/zen_server/template_execution/utils.py +14 -16
- zenml/zen_server/utils.py +27 -0
- zenml/zen_server/zen_server_api.py +6 -3
- zenml/zen_stores/migrations/versions/0.70.0_release.py +23 -0
- zenml/zen_stores/migrations/versions/1cb6477f72d6_move_artifact_save_type.py +99 -0
- zenml/zen_stores/migrations/versions/904464ea4041_add_pipeline_model_run_unique_constraints.py +192 -0
- zenml/zen_stores/migrations/versions/b557b2871693_update_step_run_input_types.py +33 -0
- zenml/zen_stores/rest_zen_store.py +68 -64
- zenml/zen_stores/schemas/artifact_schemas.py +8 -1
- zenml/zen_stores/schemas/model_schemas.py +27 -3
- zenml/zen_stores/schemas/pipeline_run_schemas.py +6 -1
- zenml/zen_stores/schemas/pipeline_schemas.py +8 -2
- zenml/zen_stores/schemas/run_metadata_schemas.py +1 -48
- zenml/zen_stores/schemas/step_run_schemas.py +18 -10
- zenml/zen_stores/sql_zen_store.py +283 -219
- zenml/zen_stores/zen_store_interface.py +15 -42
- {zenml_nightly-0.68.1.dev20241106.dist-info → zenml_nightly-0.70.0.dev20241116.dist-info}/METADATA +2 -2
- {zenml_nightly-0.68.1.dev20241106.dist-info → zenml_nightly-0.70.0.dev20241116.dist-info}/RECORD +194 -179
- zenml/zen_server/dashboard/assets/AlertDialogDropdownItem-C6N2rGrB.js +0 -1
- zenml/zen_server/dashboard/assets/ComponentBadge-DUiEYJHu.js +0 -1
- zenml/zen_server/dashboard/assets/ComponentFallbackDialog-BFoH5K4V.js +0 -1
- zenml/zen_server/dashboard/assets/ComponentIcon-CAIoUis2.js +0 -1
- zenml/zen_server/dashboard/assets/Partials-YPBB3V4q.js +0 -1
- zenml/zen_server/dashboard/assets/ProviderIcon-Bb3Xha5A.js +0 -1
- zenml/zen_server/dashboard/assets/RunSelector-DCiL3M1c.js +0 -1
- zenml/zen_server/dashboard/assets/SearchField-DfUiGFVd.js +0 -1
- zenml/zen_server/dashboard/assets/Tick-CykQFPj2.js +0 -1
- zenml/zen_server/dashboard/assets/cloud-only-B-s_HMDm.js +0 -1
- zenml/zen_server/dashboard/assets/codespaces-BitYDX9d.gif +0 -0
- zenml/zen_server/dashboard/assets/create-stack-CEmaPZ4c.js +0 -1
- zenml/zen_server/dashboard/assets/delete-run-D-LKbGyz.js +0 -1
- zenml/zen_server/dashboard/assets/index-Bpmj40BI.js +0 -1
- zenml/zen_server/dashboard/assets/index-CbU4Ln_E.css +0 -1
- zenml/zen_server/dashboard/assets/index-DKPhqP2B.js +0 -1
- zenml/zen_server/dashboard/assets/page-BBpOxVcY.js +0 -1
- zenml/zen_server/dashboard/assets/page-BRInM1Lg.js +0 -1
- zenml/zen_server/dashboard/assets/page-BjjlMk7s.js +0 -1
- zenml/zen_server/dashboard/assets/page-Bvd7YH2A.js +0 -1
- zenml/zen_server/dashboard/assets/page-CT3Nep8W.js +0 -1
- zenml/zen_server/dashboard/assets/page-C_f47pBf.js +0 -1
- zenml/zen_server/dashboard/assets/page-Cmv8C_yM.js +0 -3
- zenml/zen_server/dashboard/assets/page-CyN2bdWG.js +0 -1
- zenml/zen_server/dashboard/assets/page-CzzXH4fs.js +0 -1
- zenml/zen_server/dashboard/assets/page-DTlGjgnG.js +0 -1
- zenml/zen_server/dashboard/assets/page-Dbpl86h0.js +0 -1
- zenml/zen_server/dashboard/assets/page-Ddgy6kDS.js +0 -1
- zenml/zen_server/dashboard/assets/page-DtCAfBLy.js +0 -9
- zenml/zen_server/dashboard/assets/page-Dx16z7nA.js +0 -1
- zenml/zen_server/dashboard/assets/page-McUyYbo1.js +0 -1
- zenml/zen_server/dashboard/assets/page-T1P3RyAR.js +0 -1
- zenml/zen_server/dashboard/assets/page-bKaULTGG.js +0 -1
- zenml/zen_server/dashboard/assets/page-sbXUJy9t.js +0 -1
- zenml/zen_server/dashboard/assets/sharedSchema-TMLu-nYQ.js +0 -14
- zenml/zen_server/dashboard/assets/stack-detail-query-xmYxSsUY.js +0 -1
- zenml/zen_server/dashboard/assets/url-D5le3J4q.js +0 -1
- zenml/zen_server/routers/run_metadata_endpoints.py +0 -96
- {zenml_nightly-0.68.1.dev20241106.dist-info → zenml_nightly-0.70.0.dev20241116.dist-info}/LICENSE +0 -0
- {zenml_nightly-0.68.1.dev20241106.dist-info → zenml_nightly-0.70.0.dev20241116.dist-info}/WHEEL +0 -0
- {zenml_nightly-0.68.1.dev20241106.dist-info → zenml_nightly-0.70.0.dev20241116.dist-info}/entry_points.txt +0 -0
@@ -87,41 +87,44 @@ class TensorboardVisualizer:
|
|
87
87
|
*args: Additional arguments.
|
88
88
|
**kwargs: Additional keyword arguments.
|
89
89
|
"""
|
90
|
-
for
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
return
|
101
|
-
|
102
|
-
if sys.platform == "win32":
|
103
|
-
# Daemon service functionality is currently not supported
|
104
|
-
# on Windows
|
105
|
-
print(
|
106
|
-
"You can run:\n"
|
107
|
-
f"[italic green] tensorboard --logdir {logdir}"
|
108
|
-
"[/italic green]\n"
|
109
|
-
"...to visualize the TensorBoard logs for your trained model."
|
90
|
+
for output in object.outputs.values():
|
91
|
+
for artifact_view in output:
|
92
|
+
# filter out anything but model artifacts
|
93
|
+
if artifact_view.type == ArtifactType.MODEL:
|
94
|
+
logdir = os.path.dirname(artifact_view.uri)
|
95
|
+
|
96
|
+
# first check if a TensorBoard server is already running for
|
97
|
+
# the same logdir location and use that one
|
98
|
+
running_server = self.find_running_tensorboard_server(
|
99
|
+
logdir
|
110
100
|
)
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
101
|
+
if running_server:
|
102
|
+
self.visualize_tensorboard(running_server.port, height)
|
103
|
+
return
|
104
|
+
|
105
|
+
if sys.platform == "win32":
|
106
|
+
# Daemon service functionality is currently not supported
|
107
|
+
# on Windows
|
108
|
+
print(
|
109
|
+
"You can run:\n"
|
110
|
+
f"[italic green] tensorboard --logdir {logdir}"
|
111
|
+
"[/italic green]\n"
|
112
|
+
"...to visualize the TensorBoard logs for your trained model."
|
117
113
|
)
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
114
|
+
else:
|
115
|
+
# start a new TensorBoard server
|
116
|
+
service = TensorboardService(
|
117
|
+
TensorboardServiceConfig(
|
118
|
+
logdir=logdir,
|
119
|
+
name=f"zenml-tensorboard-{logdir}",
|
120
|
+
)
|
123
121
|
)
|
124
|
-
|
122
|
+
service.start(timeout=60)
|
123
|
+
if service.endpoint.status.port:
|
124
|
+
self.visualize_tensorboard(
|
125
|
+
service.endpoint.status.port, height
|
126
|
+
)
|
127
|
+
return
|
125
128
|
|
126
129
|
def visualize_tensorboard(
|
127
130
|
self,
|
@@ -154,31 +157,34 @@ class TensorboardVisualizer:
|
|
154
157
|
Args:
|
155
158
|
object: StepRunResponseModel fetched from get_step().
|
156
159
|
"""
|
157
|
-
for
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
160
|
+
for output in object.outputs.values():
|
161
|
+
for artifact_view in output:
|
162
|
+
# filter out anything but model artifacts
|
163
|
+
if artifact_view.type == ArtifactType.MODEL:
|
164
|
+
logdir = os.path.dirname(artifact_view.uri)
|
165
|
+
|
166
|
+
# first check if a TensorBoard server is already running for
|
167
|
+
# the same logdir location and use that one
|
168
|
+
running_server = self.find_running_tensorboard_server(
|
169
|
+
logdir
|
170
|
+
)
|
171
|
+
if not running_server:
|
172
|
+
return
|
167
173
|
|
168
|
-
|
169
|
-
|
170
|
-
running_server.pid,
|
171
|
-
)
|
172
|
-
try:
|
173
|
-
p = psutil.Process(running_server.pid)
|
174
|
-
except psutil.Error:
|
175
|
-
logger.error(
|
176
|
-
"Could not find process for PID '%d' ...",
|
174
|
+
logger.debug(
|
175
|
+
"Stopping tensorboard server with PID '%d' ...",
|
177
176
|
running_server.pid,
|
178
177
|
)
|
179
|
-
|
180
|
-
|
181
|
-
|
178
|
+
try:
|
179
|
+
p = psutil.Process(running_server.pid)
|
180
|
+
except psutil.Error:
|
181
|
+
logger.error(
|
182
|
+
"Could not find process for PID '%d' ...",
|
183
|
+
running_server.pid,
|
184
|
+
)
|
185
|
+
continue
|
186
|
+
p.kill()
|
187
|
+
return
|
182
188
|
|
183
189
|
|
184
190
|
def get_step(pipeline_name: str, step_name: str) -> "StepRunResponse":
|
@@ -13,6 +13,7 @@
|
|
13
13
|
# permissions and limitations under the License.
|
14
14
|
"""Implementation of the vLLM Inference Server Service."""
|
15
15
|
|
16
|
+
import argparse
|
16
17
|
import os
|
17
18
|
from typing import Any, List, Optional, Union
|
18
19
|
|
@@ -137,15 +138,23 @@ class VLLMDeploymentService(LocalDaemonService, BaseDeploymentService):
|
|
137
138
|
self.endpoint.prepare_for_start()
|
138
139
|
|
139
140
|
import uvloop
|
140
|
-
from vllm.entrypoints.openai.api_server import
|
141
|
-
|
142
|
-
|
141
|
+
from vllm.entrypoints.openai.api_server import (
|
142
|
+
run_server,
|
143
|
+
)
|
144
|
+
from vllm.entrypoints.openai.cli_args import (
|
145
|
+
make_arg_parser,
|
146
|
+
)
|
147
|
+
from vllm.utils import (
|
148
|
+
FlexibleArgumentParser,
|
149
|
+
)
|
143
150
|
|
144
151
|
try:
|
145
|
-
parser = make_arg_parser(
|
146
|
-
|
152
|
+
parser: argparse.ArgumentParser = make_arg_parser(
|
153
|
+
FlexibleArgumentParser()
|
154
|
+
)
|
155
|
+
args: argparse.Namespace = parser.parse_args()
|
147
156
|
# Override port with the available port
|
148
|
-
self.config.port = self.endpoint.status.port
|
157
|
+
self.config.port = self.endpoint.status.port or self.config.port
|
149
158
|
# Update the arguments in place
|
150
159
|
args.__dict__.update(self.config.model_dump())
|
151
160
|
uvloop.run(run_server(args=args))
|
@@ -161,7 +170,7 @@ class VLLMDeploymentService(LocalDaemonService, BaseDeploymentService):
|
|
161
170
|
"""
|
162
171
|
if not self.is_running:
|
163
172
|
return None
|
164
|
-
return self.endpoint.
|
173
|
+
return self.endpoint.prediction_url
|
165
174
|
|
166
175
|
def predict(self, data: "Any") -> "Any":
|
167
176
|
"""Make a prediction using the service.
|
zenml/metadata/lazy_load.py
CHANGED
@@ -13,10 +13,25 @@
|
|
13
13
|
# permissions and limitations under the License.
|
14
14
|
"""Run Metadata Lazy Loader definition."""
|
15
15
|
|
16
|
-
from typing import
|
16
|
+
from typing import Optional
|
17
17
|
|
18
|
-
|
19
|
-
|
18
|
+
from pydantic import BaseModel
|
19
|
+
|
20
|
+
from zenml.metadata.metadata_types import MetadataType
|
21
|
+
|
22
|
+
|
23
|
+
class LazyRunMetadataResponse(BaseModel):
|
24
|
+
"""Lazy run metadata response.
|
25
|
+
|
26
|
+
Used if the run metadata is accessed from the model in
|
27
|
+
a pipeline context available only during pipeline compilation.
|
28
|
+
"""
|
29
|
+
|
30
|
+
lazy_load_artifact_name: Optional[str] = None
|
31
|
+
lazy_load_artifact_version: Optional[str] = None
|
32
|
+
lazy_load_metadata_name: Optional[str] = None
|
33
|
+
lazy_load_model_name: str
|
34
|
+
lazy_load_model_version: Optional[str] = None
|
20
35
|
|
21
36
|
|
22
37
|
class RunMetadataLazyGetter:
|
@@ -47,7 +62,7 @@ class RunMetadataLazyGetter:
|
|
47
62
|
self._lazy_load_artifact_name = _lazy_load_artifact_name
|
48
63
|
self._lazy_load_artifact_version = _lazy_load_artifact_version
|
49
64
|
|
50
|
-
def __getitem__(self, key: str) ->
|
65
|
+
def __getitem__(self, key: str) -> MetadataType:
|
51
66
|
"""Get the metadata for the given key.
|
52
67
|
|
53
68
|
Args:
|
@@ -56,9 +71,7 @@ class RunMetadataLazyGetter:
|
|
56
71
|
Returns:
|
57
72
|
The metadata lazy loader wrapper for the given key.
|
58
73
|
"""
|
59
|
-
|
60
|
-
|
61
|
-
return LazyRunMetadataResponse(
|
74
|
+
return LazyRunMetadataResponse( # type: ignore[return-value]
|
62
75
|
lazy_load_model_name=self._lazy_load_model_name,
|
63
76
|
lazy_load_model_version=self._lazy_load_model_version,
|
64
77
|
lazy_load_artifact_name=self._lazy_load_artifact_name,
|
zenml/model/model.py
CHANGED
@@ -14,7 +14,6 @@
|
|
14
14
|
"""Model user facing interface to pass into pipeline or step."""
|
15
15
|
|
16
16
|
import datetime
|
17
|
-
import time
|
18
17
|
from typing import (
|
19
18
|
TYPE_CHECKING,
|
20
19
|
Any,
|
@@ -28,7 +27,6 @@ from uuid import UUID
|
|
28
27
|
|
29
28
|
from pydantic import BaseModel, ConfigDict, Field, PrivateAttr, model_validator
|
30
29
|
|
31
|
-
from zenml.constants import MAX_RETRIES_FOR_VERSIONED_ENTITY_CREATION
|
32
30
|
from zenml.enums import MetadataResourceTypes, ModelStages
|
33
31
|
from zenml.exceptions import EntityExistsError
|
34
32
|
from zenml.logger import get_logger
|
@@ -43,7 +41,6 @@ if TYPE_CHECKING:
|
|
43
41
|
ModelResponse,
|
44
42
|
ModelVersionResponse,
|
45
43
|
PipelineRunResponse,
|
46
|
-
RunMetadataResponse,
|
47
44
|
StepRunResponse,
|
48
45
|
)
|
49
46
|
|
@@ -349,7 +346,7 @@ class Model(BaseModel):
|
|
349
346
|
)
|
350
347
|
|
351
348
|
@property
|
352
|
-
def run_metadata(self) -> Dict[str, "
|
349
|
+
def run_metadata(self) -> Dict[str, "MetadataType"]:
|
353
350
|
"""Get model version run metadata.
|
354
351
|
|
355
352
|
Returns:
|
@@ -528,14 +525,6 @@ class Model(BaseModel):
|
|
528
525
|
data["suppress_class_validation_warnings"] = True
|
529
526
|
return data
|
530
527
|
|
531
|
-
def _validate_config_in_runtime(self) -> "ModelVersionResponse":
|
532
|
-
"""Validate that config doesn't conflict with runtime environment.
|
533
|
-
|
534
|
-
Returns:
|
535
|
-
The model version based on configuration.
|
536
|
-
"""
|
537
|
-
return self._get_or_create_model_version()
|
538
|
-
|
539
528
|
def _get_or_create_model(self) -> "ModelResponse":
|
540
529
|
"""This method should get or create a model from Model Control Plane.
|
541
530
|
|
@@ -679,16 +668,6 @@ class Model(BaseModel):
|
|
679
668
|
if isinstance(self.version, str):
|
680
669
|
self.version = format_name_template(self.version)
|
681
670
|
|
682
|
-
zenml_client = Client()
|
683
|
-
model_version_request = ModelVersionRequest(
|
684
|
-
user=zenml_client.active_user.id,
|
685
|
-
workspace=zenml_client.active_workspace.id,
|
686
|
-
name=str(self.version) if self.version else None,
|
687
|
-
description=self.description,
|
688
|
-
model=model.id,
|
689
|
-
tags=self.tags,
|
690
|
-
)
|
691
|
-
mv_request = ModelVersionRequest.model_validate(model_version_request)
|
692
671
|
try:
|
693
672
|
if self.version or self.model_version_id:
|
694
673
|
model_version = self._get_model_version()
|
@@ -718,60 +697,34 @@ class Model(BaseModel):
|
|
718
697
|
" as an example. You can explore model versions using "
|
719
698
|
f"`zenml model version list -n {self.name}` CLI command."
|
720
699
|
)
|
721
|
-
|
722
|
-
|
723
|
-
|
724
|
-
|
725
|
-
|
726
|
-
|
727
|
-
|
728
|
-
|
729
|
-
|
730
|
-
|
731
|
-
|
732
|
-
|
733
|
-
|
734
|
-
|
735
|
-
f"in model `{self.name}`. Retried {retries_made} times. "
|
736
|
-
"This could be driven by exceptionally high concurrency of "
|
737
|
-
"pipeline runs. Please, reach out to us on ZenML Slack for support."
|
738
|
-
) from e
|
739
|
-
# smoothed exponential back-off, it will go as 0.2, 0.3,
|
740
|
-
# 0.45, 0.68, 1.01, 1.52, 2.28, 3.42, 5.13, 7.69, ...
|
741
|
-
sleep = 0.2 * 1.5**i
|
742
|
-
logger.debug(
|
743
|
-
f"Failed to create new model version for "
|
744
|
-
f"model `{self.name}`. Retrying in {sleep}..."
|
745
|
-
)
|
746
|
-
time.sleep(sleep)
|
747
|
-
retries_made += 1
|
748
|
-
self.version = model_version.name
|
700
|
+
|
701
|
+
client = Client()
|
702
|
+
model_version_request = ModelVersionRequest(
|
703
|
+
user=client.active_user.id,
|
704
|
+
workspace=client.active_workspace.id,
|
705
|
+
name=str(self.version) if self.version else None,
|
706
|
+
description=self.description,
|
707
|
+
model=model.id,
|
708
|
+
tags=self.tags,
|
709
|
+
)
|
710
|
+
model_version = client.zen_store.create_model_version(
|
711
|
+
model_version=model_version_request
|
712
|
+
)
|
713
|
+
|
749
714
|
self._created_model_version = True
|
750
715
|
|
751
716
|
logger.info(
|
752
717
|
"Created new model version `%s` for model `%s`.",
|
753
|
-
|
718
|
+
model_version.name,
|
754
719
|
self.name,
|
755
720
|
)
|
756
721
|
|
722
|
+
self.version = model_version.name
|
757
723
|
self.model_version_id = model_version.id
|
758
724
|
self._model_id = model_version.model.id
|
759
725
|
self._number = model_version.number
|
760
726
|
return model_version
|
761
727
|
|
762
|
-
def _merge(self, model: "Model") -> None:
|
763
|
-
self.license = self.license or model.license
|
764
|
-
self.description = self.description or model.description
|
765
|
-
self.audience = self.audience or model.audience
|
766
|
-
self.use_cases = self.use_cases or model.use_cases
|
767
|
-
self.limitations = self.limitations or model.limitations
|
768
|
-
self.trade_offs = self.trade_offs or model.trade_offs
|
769
|
-
self.ethics = self.ethics or model.ethics
|
770
|
-
if model.tags is not None:
|
771
|
-
self.tags = list(
|
772
|
-
{t for t in self.tags or []}.union(set(model.tags))
|
773
|
-
)
|
774
|
-
|
775
728
|
def __hash__(self) -> int:
|
776
729
|
"""Get hash of the `Model`.
|
777
730
|
|
zenml/model/utils.py
CHANGED
@@ -56,6 +56,11 @@ def log_model_metadata(
|
|
56
56
|
ValueError: If no model name/version is provided and the function is not
|
57
57
|
called inside a step with configured `model` in decorator.
|
58
58
|
"""
|
59
|
+
logger.warning(
|
60
|
+
"The `log_model_metadata` function is deprecated and will soon be "
|
61
|
+
"removed. Please use `log_metadata` instead."
|
62
|
+
)
|
63
|
+
|
59
64
|
if model_name and model_version:
|
60
65
|
from zenml import Model
|
61
66
|
|
zenml/models/__init__.py
CHANGED
@@ -239,12 +239,7 @@ from zenml.models.v2.core.run_template import (
|
|
239
239
|
)
|
240
240
|
from zenml.models.v2.base.base_plugin_flavor import BasePluginFlavorResponse
|
241
241
|
from zenml.models.v2.core.run_metadata import (
|
242
|
-
LazyRunMetadataResponse,
|
243
242
|
RunMetadataRequest,
|
244
|
-
RunMetadataFilter,
|
245
|
-
RunMetadataResponse,
|
246
|
-
RunMetadataResponseBody,
|
247
|
-
RunMetadataResponseMetadata,
|
248
243
|
)
|
249
244
|
from zenml.models.v2.core.schedule import (
|
250
245
|
ScheduleRequest,
|
@@ -418,7 +413,6 @@ EventSourceResponseResources.model_rebuild()
|
|
418
413
|
FlavorResponseBody.model_rebuild()
|
419
414
|
FlavorResponseMetadata.model_rebuild()
|
420
415
|
LazyArtifactVersionResponse.model_rebuild()
|
421
|
-
LazyRunMetadataResponse.model_rebuild()
|
422
416
|
ModelResponseBody.model_rebuild()
|
423
417
|
ModelResponseMetadata.model_rebuild()
|
424
418
|
ModelVersionResponseBody.model_rebuild()
|
@@ -444,8 +438,6 @@ RunTemplateResponseBody.model_rebuild()
|
|
444
438
|
RunTemplateResponseMetadata.model_rebuild()
|
445
439
|
RunTemplateResponseResources.model_rebuild()
|
446
440
|
RunTemplateResponseBody.model_rebuild()
|
447
|
-
RunMetadataResponseBody.model_rebuild()
|
448
|
-
RunMetadataResponseMetadata.model_rebuild()
|
449
441
|
ScheduleResponseBody.model_rebuild()
|
450
442
|
ScheduleResponseMetadata.model_rebuild()
|
451
443
|
SecretResponseBody.model_rebuild()
|
@@ -637,10 +629,6 @@ __all__ = [
|
|
637
629
|
"RunTemplateResponseResources",
|
638
630
|
"RunTemplateFilter",
|
639
631
|
"RunMetadataRequest",
|
640
|
-
"RunMetadataFilter",
|
641
|
-
"RunMetadataResponse",
|
642
|
-
"RunMetadataResponseBody",
|
643
|
-
"RunMetadataResponseMetadata",
|
644
632
|
"ScheduleRequest",
|
645
633
|
"ScheduleUpdate",
|
646
634
|
"ScheduleFilter",
|
zenml/models/v2/base/filter.py
CHANGED
@@ -13,6 +13,7 @@
|
|
13
13
|
# permissions and limitations under the License.
|
14
14
|
"""Base filter model definitions."""
|
15
15
|
|
16
|
+
import json
|
16
17
|
from abc import ABC, abstractmethod
|
17
18
|
from datetime import datetime
|
18
19
|
from typing import (
|
@@ -36,7 +37,7 @@ from pydantic import (
|
|
36
37
|
field_validator,
|
37
38
|
model_validator,
|
38
39
|
)
|
39
|
-
from sqlalchemy import asc, desc
|
40
|
+
from sqlalchemy import Float, and_, asc, cast, desc
|
40
41
|
from sqlmodel import SQLModel
|
41
42
|
|
42
43
|
from zenml.constants import (
|
@@ -63,6 +64,11 @@ logger = get_logger(__name__)
|
|
63
64
|
|
64
65
|
AnyQuery = TypeVar("AnyQuery", bound=Any)
|
65
66
|
|
67
|
+
ONEOF_ERROR = (
|
68
|
+
"When you are using the 'oneof:' filtering make sure that the "
|
69
|
+
"provided value is a json formatted list."
|
70
|
+
)
|
71
|
+
|
66
72
|
|
67
73
|
class Filter(BaseModel, ABC):
|
68
74
|
"""Filter for all fields.
|
@@ -171,8 +177,28 @@ class StrFilter(Filter):
|
|
171
177
|
GenericFilterOps.STARTSWITH,
|
172
178
|
GenericFilterOps.CONTAINS,
|
173
179
|
GenericFilterOps.ENDSWITH,
|
180
|
+
GenericFilterOps.ONEOF,
|
181
|
+
GenericFilterOps.GT,
|
182
|
+
GenericFilterOps.GTE,
|
183
|
+
GenericFilterOps.LT,
|
184
|
+
GenericFilterOps.LTE,
|
174
185
|
]
|
175
186
|
|
187
|
+
@model_validator(mode="after")
|
188
|
+
def check_value_if_operation_oneof(self) -> "StrFilter":
|
189
|
+
"""Validator to check if value is a list if oneof operation is used.
|
190
|
+
|
191
|
+
Raises:
|
192
|
+
ValueError: If the value is not a list
|
193
|
+
|
194
|
+
Returns:
|
195
|
+
self
|
196
|
+
"""
|
197
|
+
if self.operation == GenericFilterOps.ONEOF:
|
198
|
+
if not isinstance(self.value, list):
|
199
|
+
raise ValueError(ONEOF_ERROR)
|
200
|
+
return self
|
201
|
+
|
176
202
|
def generate_query_conditions_from_column(self, column: Any) -> Any:
|
177
203
|
"""Generate query conditions for a string column.
|
178
204
|
|
@@ -181,6 +207,9 @@ class StrFilter(Filter):
|
|
181
207
|
|
182
208
|
Returns:
|
183
209
|
A list of query conditions.
|
210
|
+
|
211
|
+
Raises:
|
212
|
+
ValueError: the comparison of the column to a numeric value fails.
|
184
213
|
"""
|
185
214
|
if self.operation == GenericFilterOps.CONTAINS:
|
186
215
|
return column.like(f"%{self.value}%")
|
@@ -190,6 +219,40 @@ class StrFilter(Filter):
|
|
190
219
|
return column.endswith(f"{self.value}")
|
191
220
|
if self.operation == GenericFilterOps.NOT_EQUALS:
|
192
221
|
return column != self.value
|
222
|
+
if self.operation == GenericFilterOps.ONEOF:
|
223
|
+
return column.in_(self.value)
|
224
|
+
if self.operation in {
|
225
|
+
GenericFilterOps.GT,
|
226
|
+
GenericFilterOps.LT,
|
227
|
+
GenericFilterOps.GTE,
|
228
|
+
GenericFilterOps.LTE,
|
229
|
+
}:
|
230
|
+
try:
|
231
|
+
numeric_column = cast(column, Float)
|
232
|
+
|
233
|
+
assert self.value is not None
|
234
|
+
|
235
|
+
if self.operation == GenericFilterOps.GT:
|
236
|
+
return and_(
|
237
|
+
numeric_column, numeric_column > float(self.value)
|
238
|
+
)
|
239
|
+
if self.operation == GenericFilterOps.LT:
|
240
|
+
return and_(
|
241
|
+
numeric_column, numeric_column < float(self.value)
|
242
|
+
)
|
243
|
+
if self.operation == GenericFilterOps.GTE:
|
244
|
+
return and_(
|
245
|
+
numeric_column, numeric_column >= float(self.value)
|
246
|
+
)
|
247
|
+
if self.operation == GenericFilterOps.LTE:
|
248
|
+
return and_(
|
249
|
+
numeric_column, numeric_column <= float(self.value)
|
250
|
+
)
|
251
|
+
except Exception as e:
|
252
|
+
raise ValueError(
|
253
|
+
f"Failed to compare the column '{column}' to the "
|
254
|
+
f"value '{self.value}' (must be numeric): {e}"
|
255
|
+
)
|
193
256
|
|
194
257
|
return column == self.value
|
195
258
|
|
@@ -211,6 +274,9 @@ class UUIDFilter(StrFilter):
|
|
211
274
|
if isinstance(value, str):
|
212
275
|
return value.replace("-", "")
|
213
276
|
|
277
|
+
if isinstance(value, list):
|
278
|
+
return [str(v).replace("-", "") for v in value]
|
279
|
+
|
214
280
|
return value
|
215
281
|
|
216
282
|
def generate_query_conditions_from_column(self, column: Any) -> Any:
|
@@ -588,6 +654,10 @@ class BaseFilter(BaseModel):
|
|
588
654
|
|
589
655
|
Returns:
|
590
656
|
A tuple of the filter value and the operator.
|
657
|
+
|
658
|
+
Raises:
|
659
|
+
ValueError: when we try to use the `oneof` operator with the wrong
|
660
|
+
value.
|
591
661
|
"""
|
592
662
|
operator = GenericFilterOps.EQUALS # Default operator
|
593
663
|
if isinstance(value, str):
|
@@ -598,6 +668,15 @@ class BaseFilter(BaseModel):
|
|
598
668
|
):
|
599
669
|
value = split_value[1]
|
600
670
|
operator = GenericFilterOps(split_value[0])
|
671
|
+
|
672
|
+
if operator == operator.ONEOF:
|
673
|
+
try:
|
674
|
+
value = json.loads(value)
|
675
|
+
if not isinstance(value, list):
|
676
|
+
raise ValueError
|
677
|
+
except ValueError:
|
678
|
+
raise ValueError(ONEOF_ERROR)
|
679
|
+
|
601
680
|
return value, operator
|
602
681
|
|
603
682
|
def generate_name_or_id_query_conditions(
|
@@ -648,8 +727,8 @@ class BaseFilter(BaseModel):
|
|
648
727
|
|
649
728
|
return or_(*conditions)
|
650
729
|
|
730
|
+
@staticmethod
|
651
731
|
def generate_custom_query_conditions_for_column(
|
652
|
-
self,
|
653
732
|
value: Any,
|
654
733
|
table: Type[SQLModel],
|
655
734
|
column: str,
|
@@ -833,16 +912,17 @@ class FilterGenerator:
|
|
833
912
|
|
834
913
|
# Create str filters
|
835
914
|
if self.is_str_field(column):
|
836
|
-
return
|
837
|
-
|
915
|
+
return self._define_str_filter(
|
916
|
+
operator=GenericFilterOps(operator),
|
838
917
|
column=column,
|
839
918
|
value=value,
|
840
919
|
)
|
841
920
|
|
842
921
|
# Handle unsupported datatypes
|
843
922
|
logger.warning(
|
844
|
-
f"The Datatype {self._model_class.model_fields[column].annotation}
|
845
|
-
"not be supported for filtering. Defaulting to a string
|
923
|
+
f"The Datatype {self._model_class.model_fields[column].annotation} "
|
924
|
+
"might not be supported for filtering. Defaulting to a string "
|
925
|
+
"filter."
|
846
926
|
)
|
847
927
|
return StrFilter(
|
848
928
|
operation=GenericFilterOps(operator),
|
@@ -1032,8 +1112,9 @@ class FilterGenerator:
|
|
1032
1112
|
"Invalid value passed as UUID query parameter."
|
1033
1113
|
) from e
|
1034
1114
|
|
1035
|
-
#
|
1036
|
-
|
1115
|
+
# For equality checks, ensure that the value is a valid UUID.
|
1116
|
+
if operator == GenericFilterOps.ONEOF and not isinstance(value, list):
|
1117
|
+
raise ValueError(ONEOF_ERROR)
|
1037
1118
|
|
1038
1119
|
# Generate the filter.
|
1039
1120
|
uuid_filter = UUIDFilter(
|
@@ -1043,6 +1124,38 @@ class FilterGenerator:
|
|
1043
1124
|
)
|
1044
1125
|
return uuid_filter
|
1045
1126
|
|
1127
|
+
@staticmethod
|
1128
|
+
def _define_str_filter(
|
1129
|
+
column: str, value: Any, operator: GenericFilterOps
|
1130
|
+
) -> StrFilter:
|
1131
|
+
"""Define a str filter for a given column.
|
1132
|
+
|
1133
|
+
Args:
|
1134
|
+
column: The column to filter on.
|
1135
|
+
value: The UUID value by which to filter.
|
1136
|
+
operator: The operator to use for filtering.
|
1137
|
+
|
1138
|
+
Returns:
|
1139
|
+
A Filter object.
|
1140
|
+
|
1141
|
+
Raises:
|
1142
|
+
ValueError: If the value is not a proper value.
|
1143
|
+
"""
|
1144
|
+
# For equality checks, ensure that the value is a valid UUID.
|
1145
|
+
if operator == GenericFilterOps.ONEOF and not isinstance(value, list):
|
1146
|
+
raise ValueError(
|
1147
|
+
"If you are using `oneof:` as a filtering op, the value needs "
|
1148
|
+
"to be a json formatted list string."
|
1149
|
+
)
|
1150
|
+
|
1151
|
+
# Generate the filter.
|
1152
|
+
str_filter = StrFilter(
|
1153
|
+
operation=GenericFilterOps(operator),
|
1154
|
+
column=column,
|
1155
|
+
value=value,
|
1156
|
+
)
|
1157
|
+
return str_filter
|
1158
|
+
|
1046
1159
|
@staticmethod
|
1047
1160
|
def _define_bool_filter(
|
1048
1161
|
column: str, value: Any, operator: GenericFilterOps
|