zenml-nightly 0.70.0.dev20241201__py3-none-any.whl → 0.71.0.dev20241220__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.
Files changed (193) hide show
  1. README.md +4 -4
  2. RELEASE_NOTES.md +112 -0
  3. zenml/VERSION +1 -1
  4. zenml/artifacts/artifact_config.py +8 -5
  5. zenml/artifacts/utils.py +3 -1
  6. zenml/cli/__init__.py +4 -4
  7. zenml/cli/base.py +1 -1
  8. zenml/cli/pipeline.py +48 -79
  9. zenml/cli/server.py +19 -19
  10. zenml/client.py +54 -2
  11. zenml/config/secret_reference_mixin.py +1 -1
  12. zenml/config/server_config.py +4 -0
  13. zenml/constants.py +10 -0
  14. zenml/image_builders/base_image_builder.py +5 -2
  15. zenml/image_builders/build_context.py +7 -16
  16. zenml/integrations/aws/__init__.py +3 -0
  17. zenml/integrations/aws/flavors/__init__.py +6 -0
  18. zenml/integrations/aws/flavors/aws_image_builder_flavor.py +146 -0
  19. zenml/integrations/aws/image_builders/__init__.py +20 -0
  20. zenml/integrations/aws/image_builders/aws_image_builder.py +307 -0
  21. zenml/integrations/gcp/orchestrators/vertex_orchestrator.py +1 -1
  22. zenml/integrations/kaniko/image_builders/kaniko_image_builder.py +2 -1
  23. zenml/integrations/kubernetes/flavors/kubernetes_orchestrator_flavor.py +11 -0
  24. zenml/integrations/kubernetes/step_operators/kubernetes_step_operator.py +0 -1
  25. zenml/integrations/lightning/flavors/lightning_orchestrator_flavor.py +11 -0
  26. zenml/integrations/neptune/experiment_trackers/neptune_experiment_tracker.py +7 -5
  27. zenml/integrations/neptune/experiment_trackers/run_state.py +69 -53
  28. zenml/integrations/registry.py +2 -2
  29. zenml/integrations/skypilot/flavors/skypilot_orchestrator_base_vm_config.py +12 -0
  30. zenml/integrations/wandb/flavors/wandb_experiment_tracker_flavor.py +13 -5
  31. zenml/materializers/built_in_materializer.py +1 -1
  32. zenml/model/model.py +12 -16
  33. zenml/model/utils.py +3 -1
  34. zenml/models/v2/base/filter.py +26 -30
  35. zenml/models/v2/base/scoped.py +258 -5
  36. zenml/models/v2/core/artifact_version.py +15 -26
  37. zenml/models/v2/core/code_repository.py +1 -12
  38. zenml/models/v2/core/component.py +5 -46
  39. zenml/models/v2/core/flavor.py +1 -11
  40. zenml/models/v2/core/model.py +1 -57
  41. zenml/models/v2/core/model_version.py +5 -33
  42. zenml/models/v2/core/model_version_artifact.py +11 -3
  43. zenml/models/v2/core/model_version_pipeline_run.py +14 -3
  44. zenml/models/v2/core/pipeline.py +47 -55
  45. zenml/models/v2/core/pipeline_build.py +67 -12
  46. zenml/models/v2/core/pipeline_deployment.py +0 -10
  47. zenml/models/v2/core/pipeline_run.py +91 -29
  48. zenml/models/v2/core/run_template.py +21 -29
  49. zenml/models/v2/core/schedule.py +0 -10
  50. zenml/models/v2/core/secret.py +0 -14
  51. zenml/models/v2/core/service.py +9 -16
  52. zenml/models/v2/core/service_connector.py +0 -11
  53. zenml/models/v2/core/stack.py +21 -30
  54. zenml/models/v2/core/step_run.py +18 -14
  55. zenml/models/v2/core/trigger.py +19 -3
  56. zenml/orchestrators/base_orchestrator.py +13 -1
  57. zenml/orchestrators/output_utils.py +5 -1
  58. zenml/orchestrators/step_launcher.py +9 -13
  59. zenml/orchestrators/step_run_utils.py +8 -204
  60. zenml/orchestrators/utils.py +55 -27
  61. zenml/pipelines/build_utils.py +12 -0
  62. zenml/service_connectors/service_connector_utils.py +3 -9
  63. zenml/stack/stack_component.py +1 -1
  64. zenml/stack_deployments/aws_stack_deployment.py +22 -0
  65. zenml/utils/archivable.py +65 -36
  66. zenml/utils/code_utils.py +8 -4
  67. zenml/utils/docker_utils.py +9 -0
  68. zenml/zen_server/auth.py +9 -10
  69. zenml/zen_server/dashboard/assets/{404-NVXKFp-x.js → 404-Cqu3EDCm.js} +1 -1
  70. zenml/zen_server/dashboard/assets/{@reactflow-CK0KJUen.js → @reactflow-D2Y7BWwz.js} +1 -1
  71. zenml/zen_server/dashboard/assets/{AlertDialogDropdownItem-DezXKmDf.js → AlertDialogDropdownItem-BHd71pVS.js} +1 -1
  72. zenml/zen_server/dashboard/assets/{CodeSnippet-JzR8CEtw.js → CodeSnippet-DIonwetW.js} +1 -1
  73. zenml/zen_server/dashboard/assets/{CollapsibleCard-DQW_ktMO.js → CollapsibleCard-CDnC97pB.js} +1 -1
  74. zenml/zen_server/dashboard/assets/{Commands-DL2kwkRd.js → Commands-BVEXKAOj.js} +1 -1
  75. zenml/zen_server/dashboard/assets/{ComponentBadge-D_g62Wv8.js → ComponentBadge-CrRvovox.js} +1 -1
  76. zenml/zen_server/dashboard/assets/{CopyButton-LNcWaa14.js → CopyButton-B6wGAhQv.js} +1 -1
  77. zenml/zen_server/dashboard/assets/{CsvVizualization-DknpE5ej.js → CsvVizualization-CjcT7LMm.js} +5 -5
  78. zenml/zen_server/dashboard/assets/DeleteAlertDialog-D2ELtM2W.js +1 -0
  79. zenml/zen_server/dashboard/assets/{DialogItem-Bxf8FuAT.js → DialogItem-DXIMhBgU.js} +1 -1
  80. zenml/zen_server/dashboard/assets/{Error-DYflYyps.js → Error-B8uUfTpL.js} +1 -1
  81. zenml/zen_server/dashboard/assets/{ExecutionStatus-C7zyIQKZ.js → ExecutionStatus-ibAdY-dG.js} +1 -1
  82. zenml/zen_server/dashboard/assets/{Helpbox-oYSGpLqd.js → Helpbox-BfAfhKHw.js} +1 -1
  83. zenml/zen_server/dashboard/assets/{Infobox-Cx4xGoXR.js → Infobox-M_SMOu96.js} +1 -1
  84. zenml/zen_server/dashboard/assets/{InlineAvatar-DiGOWNKF.js → InlineAvatar-DBA0a0-a.js} +1 -1
  85. zenml/zen_server/dashboard/assets/{NestedCollapsible-DYbgyKxK.js → NestedCollapsible-DpgmEFKw.js} +1 -1
  86. zenml/zen_server/dashboard/assets/{Partials-03iZf8-N.js → Partials-D_ldD9if.js} +1 -1
  87. zenml/zen_server/dashboard/assets/{ProBadge-D_EB8HNo.js → ProBadge-DQbfFotM.js} +1 -1
  88. zenml/zen_server/dashboard/assets/{ProCta-DqNS4v3x.js → ProCta-Bcpb4rcY.js} +1 -1
  89. zenml/zen_server/dashboard/assets/{ProviderIcon-Bki2aw8w.js → ProviderIcon-BZpgPigN.js} +1 -1
  90. zenml/zen_server/dashboard/assets/{ProviderRadio-8f43sPD4.js → ProviderRadio-DWPnMuQ1.js} +1 -1
  91. zenml/zen_server/dashboard/assets/RunSelector-DgRGaAc6.js +1 -0
  92. zenml/zen_server/dashboard/assets/{RunsBody-07YEO7qI.js → RunsBody-KecfSkjY.js} +1 -1
  93. zenml/zen_server/dashboard/assets/{SearchField-lp1KgU4e.js → SearchField-n-ILHnaP.js} +1 -1
  94. zenml/zen_server/dashboard/assets/{SecretTooltip-CgnbyeOx.js → SecretTooltip-B8MrX5yu.js} +1 -1
  95. zenml/zen_server/dashboard/assets/{SetPassword-CpP418A2.js → SetPassword-B_IVq_wg.js} +1 -1
  96. zenml/zen_server/dashboard/assets/StackList-TWPBYnkF.js +1 -0
  97. zenml/zen_server/dashboard/assets/{Tabs-BktHkCJJ.js → Tabs-Rg857zmd.js} +1 -1
  98. zenml/zen_server/dashboard/assets/{Tick-BlMoIlJT.js → Tick-COg4A-xo.js} +1 -1
  99. zenml/zen_server/dashboard/assets/{UpdatePasswordSchemas-Sc0A0pP-.js → UpdatePasswordSchemas-C6Aj3hm6.js} +1 -1
  100. zenml/zen_server/dashboard/assets/{UsageReason-YYduL4fj.js → UsageReason-BTLbx7w4.js} +1 -1
  101. zenml/zen_server/dashboard/assets/{WizardFooter-dgmizSJC.js → WizardFooter-BCAj69Vj.js} +1 -1
  102. zenml/zen_server/dashboard/assets/{all-pipeline-runs-query-D-c2G6lV.js → all-pipeline-runs-query-DMXkDrV2.js} +1 -1
  103. zenml/zen_server/dashboard/assets/code-snippets-CqONne41.js +13 -0
  104. zenml/zen_server/dashboard/assets/{create-stack-DM_JPgef.js → create-stack-HfdbhLs4.js} +1 -1
  105. zenml/zen_server/dashboard/assets/dates-3pMLCNrD.js +1 -0
  106. zenml/zen_server/dashboard/assets/delete-run-DZ4hIXff.js +1 -0
  107. zenml/zen_server/dashboard/assets/{form-schemas-K6FYKjwa.js → form-schemas-B0AVEd9b.js} +1 -1
  108. zenml/zen_server/dashboard/assets/{index-BAkC7FXi.js → index-DPqSWjug.js} +1 -1
  109. zenml/zen_server/dashboard/assets/{index-CEV4Cvaf.js → index-DScjfBRb.js} +1 -1
  110. zenml/zen_server/dashboard/assets/index-DXvT1_Um.css +1 -0
  111. zenml/zen_server/dashboard/assets/{index-CCOPpudF.js → index-FO-p0GU7.js} +5 -5
  112. zenml/zen_server/dashboard/assets/{index-B1mVPYxf.js → index-I3bKUGUj.js} +1 -1
  113. zenml/zen_server/dashboard/assets/key-icon-aH-QIa5R.js +1 -0
  114. zenml/zen_server/dashboard/assets/login-command-CkqxPtV3.js +1 -0
  115. zenml/zen_server/dashboard/assets/{login-mutation-hf-lK87O.js → login-mutation-BQeo4wTY.js} +1 -1
  116. zenml/zen_server/dashboard/assets/{not-found-BGirLjU-.js → not-found-gAJ5aDdR.js} +1 -1
  117. zenml/zen_server/dashboard/assets/page-9Y9-gig0.js +1 -0
  118. zenml/zen_server/dashboard/assets/{page-DjRJCGb3.js → page-AUwiQ14W.js} +1 -1
  119. zenml/zen_server/dashboard/assets/page-B6XU7yYT.js +2 -0
  120. zenml/zen_server/dashboard/assets/{page-C00YAkaB.js → page-BKZYc2Zv.js} +1 -1
  121. zenml/zen_server/dashboard/assets/{page-CdMWnQak.js → page-BU9FG4sR.js} +1 -1
  122. zenml/zen_server/dashboard/assets/{page-D7S3aCbF.js → page-B_Apk3xg.js} +1 -1
  123. zenml/zen_server/dashboard/assets/{page-Djikxq_S.js → page-BdowiCbr.js} +1 -1
  124. zenml/zen_server/dashboard/assets/page-Bg8OjTRe.js +1 -0
  125. zenml/zen_server/dashboard/assets/page-BxL4qD4_.js +1 -0
  126. zenml/zen_server/dashboard/assets/{page-DakHVWXF.js → page-CWxT5K5J.js} +1 -1
  127. zenml/zen_server/dashboard/assets/page-CXuQufSe.js +1 -0
  128. zenml/zen_server/dashboard/assets/{page-DLC-bNBP.js → page-CcQr8CPP.js} +1 -1
  129. zenml/zen_server/dashboard/assets/{page-CD-DcWoy.js → page-Ce4Hrjnr.js} +1 -1
  130. zenml/zen_server/dashboard/assets/page-CiYxgZP_.js +1 -0
  131. zenml/zen_server/dashboard/assets/page-Cldq1mpe.js +1 -0
  132. zenml/zen_server/dashboard/assets/{page-BDigxVpo.js → page-D4wdonLm.js} +1 -1
  133. zenml/zen_server/dashboard/assets/{page-D6uU2ax4.js → page-D8ObrbH8.js} +1 -1
  134. zenml/zen_server/dashboard/assets/{page-DXSTpqRD.js → page-DFuAUGt4.js} +1 -1
  135. zenml/zen_server/dashboard/assets/{page-CbpvrsDL.js → page-DGazBpuP.js} +1 -1
  136. zenml/zen_server/dashboard/assets/{page-COXXJj1k.js → page-DO1UcqPX.js} +1 -1
  137. zenml/zen_server/dashboard/assets/page-DRYXdL5o.js +1 -0
  138. zenml/zen_server/dashboard/assets/{page-Df-Fw0aq.js → page-DYEquBC2.js} +1 -1
  139. zenml/zen_server/dashboard/assets/page-Dk32IeZm.js +1 -0
  140. zenml/zen_server/dashboard/assets/{page-yYC9OI-E.js → page-I3nKFGie.js} +1 -1
  141. zenml/zen_server/dashboard/assets/{page-6m6yHHlE.js → page-M0w-n6vn.js} +1 -1
  142. zenml/zen_server/dashboard/assets/{page-Vcxara9U.js → page-R5dx3xGF.js} +1 -1
  143. zenml/zen_server/dashboard/assets/{page-BR68V0V1.js → page-bT5pOvcB.js} +1 -1
  144. zenml/zen_server/dashboard/assets/page-hUqK889I.js +6 -0
  145. zenml/zen_server/dashboard/assets/{page-CjGdWY13.js → page-h_Stveon.js} +1 -1
  146. zenml/zen_server/dashboard/assets/{page-D01JhjQB.js → page-r8XK5vR7.js} +1 -1
  147. zenml/zen_server/dashboard/assets/page-u_-ZXBKb.js +1 -0
  148. zenml/zen_server/dashboard/assets/page-zaMqB_ao.js +1 -0
  149. zenml/zen_server/dashboard/assets/{persist-GjC8PZoC.js → persist-AppN1B0J.js} +1 -1
  150. zenml/zen_server/dashboard/assets/{persist-Coz7ZWvz.js → persist-DAUi_3za.js} +1 -1
  151. zenml/zen_server/dashboard/assets/service-BqqeXLEe.js +2 -0
  152. zenml/zen_server/dashboard/assets/{sharedSchema-CQb14VSr.js → sharedSchema-uXN9FLLk.js} +1 -1
  153. zenml/zen_server/dashboard/assets/{stack-detail-query-OPEW-cDJ.js → stack-detail-query-XfZBiBP2.js} +1 -1
  154. zenml/zen_server/dashboard/assets/{update-server-settings-mutation-LwuQfHYn.js → update-server-settings-mutation-BWmgVJwA.js} +1 -1
  155. zenml/zen_server/dashboard/assets/{url-CkvKAnwF.js → url-BLwMbzES.js} +1 -1
  156. zenml/zen_server/dashboard/index.html +4 -4
  157. zenml/zen_server/deploy/helm/Chart.yaml +1 -1
  158. zenml/zen_server/deploy/helm/README.md +2 -2
  159. zenml/zen_server/rbac/rbac_sql_zen_store.py +173 -0
  160. zenml/zen_server/routers/auth_endpoints.py +22 -11
  161. zenml/zen_server/routers/steps_endpoints.py +7 -1
  162. zenml/zen_server/template_execution/utils.py +3 -1
  163. zenml/zen_server/utils.py +4 -3
  164. zenml/zen_stores/base_zen_store.py +10 -2
  165. zenml/zen_stores/migrations/versions/0.71.0_release.py +23 -0
  166. zenml/zen_stores/migrations/versions/26351d482b9e_add_step_run_unique_constraint.py +37 -0
  167. zenml/zen_stores/migrations/versions/a1237ba94fd8_add_model_version_producer_run_unique_.py +68 -0
  168. zenml/zen_stores/rest_zen_store.py +76 -43
  169. zenml/zen_stores/schemas/model_schemas.py +42 -6
  170. zenml/zen_stores/schemas/pipeline_deployment_schemas.py +7 -7
  171. zenml/zen_stores/schemas/pipeline_run_schemas.py +12 -6
  172. zenml/zen_stores/schemas/pipeline_schemas.py +5 -0
  173. zenml/zen_stores/schemas/step_run_schemas.py +8 -1
  174. zenml/zen_stores/sql_zen_store.py +332 -100
  175. {zenml_nightly-0.70.0.dev20241201.dist-info → zenml_nightly-0.71.0.dev20241220.dist-info}/METADATA +5 -5
  176. {zenml_nightly-0.70.0.dev20241201.dist-info → zenml_nightly-0.71.0.dev20241220.dist-info}/RECORD +179 -164
  177. zenml/zen_server/dashboard/assets/RunSelector-DkPiIiNr.js +0 -1
  178. zenml/zen_server/dashboard/assets/StackList-WvuKQusZ.js +0 -1
  179. zenml/zen_server/dashboard/assets/delete-run-CJdh1P_h.js +0 -1
  180. zenml/zen_server/dashboard/assets/index-DlGvJQPn.css +0 -1
  181. zenml/zen_server/dashboard/assets/page-0JE_-Ec1.js +0 -1
  182. zenml/zen_server/dashboard/assets/page-BRLpxOt0.js +0 -1
  183. zenml/zen_server/dashboard/assets/page-BU7huvKw.js +0 -6
  184. zenml/zen_server/dashboard/assets/page-BvqLv2Ky.js +0 -1
  185. zenml/zen_server/dashboard/assets/page-CwxrFarU.js +0 -1
  186. zenml/zen_server/dashboard/assets/page-DfbXf_8s.js +0 -1
  187. zenml/zen_server/dashboard/assets/page-Dnovpa0i.js +0 -3
  188. zenml/zen_server/dashboard/assets/page-Dot3LPmL.js +0 -1
  189. zenml/zen_server/dashboard/assets/page-Xynx4btY.js +0 -14
  190. zenml/zen_server/dashboard/assets/page-YpKAqVSa.js +0 -1
  191. {zenml_nightly-0.70.0.dev20241201.dist-info → zenml_nightly-0.71.0.dev20241220.dist-info}/LICENSE +0 -0
  192. {zenml_nightly-0.70.0.dev20241201.dist-info → zenml_nightly-0.71.0.dev20241220.dist-info}/WHEEL +0 -0
  193. {zenml_nightly-0.70.0.dev20241201.dist-info → zenml_nightly-0.71.0.dev20241220.dist-info}/entry_points.txt +0 -0
@@ -77,10 +77,6 @@ class ModelVersionRequest(WorkspaceScopedRequest):
77
77
  default=None,
78
78
  )
79
79
 
80
- number: Optional[int] = Field(
81
- description="The number of the model version",
82
- default=None,
83
- )
84
80
  model: UUID = Field(
85
81
  description="The ID of the model containing version",
86
82
  )
@@ -585,7 +581,6 @@ class ModelVersionFilter(WorkspaceScopedTaggableFilter):
585
581
 
586
582
  FILTER_EXCLUDE_FIELDS: ClassVar[List[str]] = [
587
583
  *WorkspaceScopedTaggableFilter.FILTER_EXCLUDE_FIELDS,
588
- "user",
589
584
  "run_metadata",
590
585
  ]
591
586
 
@@ -597,25 +592,11 @@ class ModelVersionFilter(WorkspaceScopedTaggableFilter):
597
592
  default=None,
598
593
  description="The number of the Model Version",
599
594
  )
600
- workspace_id: Optional[Union[UUID, str]] = Field(
601
- default=None,
602
- description="The workspace of the Model Version",
603
- union_mode="left_to_right",
604
- )
605
- user_id: Optional[Union[UUID, str]] = Field(
606
- default=None,
607
- description="The user of the Model Version",
608
- union_mode="left_to_right",
609
- )
610
595
  stage: Optional[Union[str, ModelStages]] = Field(
611
596
  description="The model version stage",
612
597
  default=None,
613
598
  union_mode="left_to_right",
614
599
  )
615
- user: Optional[Union[UUID, str]] = Field(
616
- default=None,
617
- description="Name/ID of the user that created the model version.",
618
- )
619
600
  run_metadata: Optional[Dict[str, str]] = Field(
620
601
  default=None,
621
602
  description="The run_metadata to filter the model versions by.",
@@ -639,14 +620,17 @@ class ModelVersionFilter(WorkspaceScopedTaggableFilter):
639
620
  self._model_id = model_id
640
621
 
641
622
  def get_custom_filters(
642
- self,
623
+ self, table: Type["AnySchema"]
643
624
  ) -> List["ColumnElement[bool]"]:
644
625
  """Get custom filters.
645
626
 
627
+ Args:
628
+ table: The query table.
629
+
646
630
  Returns:
647
631
  A list of custom filters.
648
632
  """
649
- custom_filters = super().get_custom_filters()
633
+ custom_filters = super().get_custom_filters(table)
650
634
 
651
635
  from sqlmodel import and_
652
636
 
@@ -654,20 +638,8 @@ class ModelVersionFilter(WorkspaceScopedTaggableFilter):
654
638
  ModelVersionSchema,
655
639
  RunMetadataResourceSchema,
656
640
  RunMetadataSchema,
657
- UserSchema,
658
641
  )
659
642
 
660
- if self.user:
661
- user_filter = and_(
662
- ModelVersionSchema.user_id == UserSchema.id,
663
- self.generate_name_or_id_query_conditions(
664
- value=self.user,
665
- table=UserSchema,
666
- additional_columns=["full_name"],
667
- ),
668
- )
669
- custom_filters.append(user_filter)
670
-
671
643
  if self.run_metadata is not None:
672
644
  from zenml.enums import MetadataResourceTypes
673
645
 
@@ -13,7 +13,7 @@
13
13
  # permissions and limitations under the License.
14
14
  """Models representing the link between model versions and artifacts."""
15
15
 
16
- from typing import TYPE_CHECKING, List, Optional, Union
16
+ from typing import TYPE_CHECKING, List, Optional, Type, TypeVar, Union
17
17
  from uuid import UUID
18
18
 
19
19
  from pydantic import ConfigDict, Field
@@ -32,6 +32,9 @@ if TYPE_CHECKING:
32
32
  from sqlalchemy.sql.elements import ColumnElement
33
33
 
34
34
  from zenml.models.v2.core.artifact_version import ArtifactVersionResponse
35
+ from zenml.zen_stores.schemas import BaseSchema
36
+
37
+ AnySchema = TypeVar("AnySchema", bound=BaseSchema)
35
38
 
36
39
 
37
40
  # ------------------ Request Model ------------------
@@ -164,13 +167,18 @@ class ModelVersionArtifactFilter(BaseFilter):
164
167
  # careful we might overwrite some fields protected by pydantic.
165
168
  model_config = ConfigDict(protected_namespaces=())
166
169
 
167
- def get_custom_filters(self) -> List[Union["ColumnElement[bool]"]]:
170
+ def get_custom_filters(
171
+ self, table: Type["AnySchema"]
172
+ ) -> List[Union["ColumnElement[bool]"]]:
168
173
  """Get custom filters.
169
174
 
175
+ Args:
176
+ table: The query table.
177
+
170
178
  Returns:
171
179
  A list of custom filters.
172
180
  """
173
- custom_filters = super().get_custom_filters()
181
+ custom_filters = super().get_custom_filters(table)
174
182
 
175
183
  from sqlmodel import and_, col
176
184
 
@@ -13,7 +13,7 @@
13
13
  # permissions and limitations under the License.
14
14
  """Models representing the link between model versions and pipeline runs."""
15
15
 
16
- from typing import List, Optional, Union
16
+ from typing import TYPE_CHECKING, List, Optional, Type, TypeVar, Union
17
17
  from uuid import UUID
18
18
 
19
19
  from pydantic import ConfigDict, Field
@@ -30,6 +30,12 @@ from zenml.models.v2.base.base import (
30
30
  from zenml.models.v2.base.filter import BaseFilter, StrFilter
31
31
  from zenml.models.v2.core.pipeline_run import PipelineRunResponse
32
32
 
33
+ if TYPE_CHECKING:
34
+ from zenml.zen_stores.schemas import BaseSchema
35
+
36
+ AnySchema = TypeVar("AnySchema", bound=BaseSchema)
37
+
38
+
33
39
  # ------------------ Request Model ------------------
34
40
 
35
41
 
@@ -147,13 +153,18 @@ class ModelVersionPipelineRunFilter(BaseFilter):
147
153
  # careful we might overwrite some fields protected by pydantic.
148
154
  model_config = ConfigDict(protected_namespaces=())
149
155
 
150
- def get_custom_filters(self) -> List["ColumnElement[bool]"]:
156
+ def get_custom_filters(
157
+ self, table: Type["AnySchema"]
158
+ ) -> List["ColumnElement[bool]"]:
151
159
  """Get custom filters.
152
160
 
161
+ Args:
162
+ table: The query table.
163
+
153
164
  Returns:
154
165
  A list of custom filters.
155
166
  """
156
- custom_filters = super().get_custom_filters()
167
+ custom_filters = super().get_custom_filters(table)
157
168
 
158
169
  from sqlmodel import and_
159
170
 
@@ -21,7 +21,6 @@ from typing import (
21
21
  Optional,
22
22
  Type,
23
23
  TypeVar,
24
- Union,
25
24
  )
26
25
  from uuid import UUID
27
26
 
@@ -45,9 +44,7 @@ from zenml.models.v2.base.scoped import (
45
44
  from zenml.models.v2.core.tag import TagResponse
46
45
 
47
46
  if TYPE_CHECKING:
48
- from sqlalchemy.sql.elements import ColumnElement
49
-
50
- from zenml.models.v2.core.pipeline_run import PipelineRunResponse
47
+ from zenml.models import PipelineRunResponse, UserResponse
51
48
  from zenml.zen_stores.schemas import BaseSchema
52
49
 
53
50
  AnySchema = TypeVar("AnySchema", bound=BaseSchema)
@@ -122,6 +119,10 @@ class PipelineResponseMetadata(WorkspaceScopedResponseMetadata):
122
119
  class PipelineResponseResources(WorkspaceScopedResponseResources):
123
120
  """Class for all resource models associated with the pipeline entity."""
124
121
 
122
+ latest_run_user: Optional["UserResponse"] = Field(
123
+ default=None,
124
+ title="The user that created the latest run of this pipeline.",
125
+ )
125
126
  tags: List[TagResponse] = Field(
126
127
  title="Tags associated with the pipeline.",
127
128
  )
@@ -258,10 +259,12 @@ class PipelineResponse(
258
259
  class PipelineFilter(WorkspaceScopedTaggableFilter):
259
260
  """Pipeline filter model."""
260
261
 
261
- CUSTOM_SORTING_OPTIONS = [SORT_PIPELINES_BY_LATEST_RUN_KEY]
262
+ CUSTOM_SORTING_OPTIONS: ClassVar[List[str]] = [
263
+ *WorkspaceScopedTaggableFilter.CUSTOM_SORTING_OPTIONS,
264
+ SORT_PIPELINES_BY_LATEST_RUN_KEY,
265
+ ]
262
266
  FILTER_EXCLUDE_FIELDS: ClassVar[List[str]] = [
263
267
  *WorkspaceScopedTaggableFilter.FILTER_EXCLUDE_FIELDS,
264
- "user",
265
268
  "latest_run_status",
266
269
  ]
267
270
 
@@ -274,20 +277,6 @@ class PipelineFilter(WorkspaceScopedTaggableFilter):
274
277
  description="Filter by the status of the latest run of a pipeline. "
275
278
  "This will always be applied as an `AND` filter for now.",
276
279
  )
277
- workspace_id: Optional[Union[UUID, str]] = Field(
278
- default=None,
279
- description="Workspace of the Pipeline",
280
- union_mode="left_to_right",
281
- )
282
- user_id: Optional[Union[UUID, str]] = Field(
283
- default=None,
284
- description="User of the Pipeline",
285
- union_mode="left_to_right",
286
- )
287
- user: Optional[Union[UUID, str]] = Field(
288
- default=None,
289
- description="Name/ID of the user that created the pipeline.",
290
- )
291
280
 
292
281
  def apply_filter(
293
282
  self, query: AnyQuery, table: Type["AnySchema"]
@@ -343,36 +332,6 @@ class PipelineFilter(WorkspaceScopedTaggableFilter):
343
332
 
344
333
  return query
345
334
 
346
- def get_custom_filters(
347
- self,
348
- ) -> List["ColumnElement[bool]"]:
349
- """Get custom filters.
350
-
351
- Returns:
352
- A list of custom filters.
353
- """
354
- custom_filters = super().get_custom_filters()
355
-
356
- from sqlmodel import and_
357
-
358
- from zenml.zen_stores.schemas import (
359
- PipelineSchema,
360
- UserSchema,
361
- )
362
-
363
- if self.user:
364
- user_filter = and_(
365
- PipelineSchema.user_id == UserSchema.id,
366
- self.generate_name_or_id_query_conditions(
367
- value=self.user,
368
- table=UserSchema,
369
- additional_columns=["full_name"],
370
- ),
371
- )
372
- custom_filters.append(user_filter)
373
-
374
- return custom_filters
375
-
376
335
  def apply_sorting(
377
336
  self,
378
337
  query: AnyQuery,
@@ -387,12 +346,45 @@ class PipelineFilter(WorkspaceScopedTaggableFilter):
387
346
  Returns:
388
347
  The query with sorting applied.
389
348
  """
390
- column, _ = self.sorting_params
349
+ from sqlmodel import asc, case, col, desc, func, select
350
+
351
+ from zenml.enums import SorterOps
352
+ from zenml.zen_stores.schemas import PipelineRunSchema, PipelineSchema
353
+
354
+ sort_by, operand = self.sorting_params
355
+
356
+ if sort_by == SORT_PIPELINES_BY_LATEST_RUN_KEY:
357
+ # Subquery to find the latest run per pipeline
358
+ latest_run_subquery = (
359
+ select(
360
+ PipelineRunSchema.pipeline_id,
361
+ case(
362
+ (
363
+ func.max(PipelineRunSchema.created).is_(None),
364
+ PipelineSchema.created,
365
+ ),
366
+ else_=func.max(PipelineRunSchema.created),
367
+ ).label("latest_run"),
368
+ )
369
+ .group_by(col(PipelineRunSchema.pipeline_id))
370
+ .subquery()
371
+ )
372
+
373
+ # Join the subquery with the pipelines
374
+ query = query.outerjoin(
375
+ latest_run_subquery,
376
+ PipelineSchema.id == latest_run_subquery.c.pipeline_id,
377
+ )
378
+
379
+ if operand == SorterOps.ASCENDING:
380
+ query = query.order_by(
381
+ asc(latest_run_subquery.c.latest_run)
382
+ ).order_by(col(PipelineSchema.id))
383
+ else:
384
+ query = query.order_by(
385
+ desc(latest_run_subquery.c.latest_run)
386
+ ).order_by(col(PipelineSchema.id))
391
387
 
392
- if column == SORT_PIPELINES_BY_LATEST_RUN_KEY:
393
- # If sorting by the latest run, the sorting is already done in the
394
- # base query in `SqlZenStore.list_pipelines(...)` and we don't need
395
- # to to anything here
396
388
  return query
397
389
  else:
398
390
  return super().apply_sorting(query=query, table=table)
@@ -14,7 +14,17 @@
14
14
  """Models representing pipeline builds."""
15
15
 
16
16
  import json
17
- from typing import TYPE_CHECKING, Any, Dict, Optional, Union
17
+ from typing import (
18
+ TYPE_CHECKING,
19
+ Any,
20
+ ClassVar,
21
+ Dict,
22
+ List,
23
+ Optional,
24
+ Type,
25
+ TypeVar,
26
+ Union,
27
+ )
18
28
  from uuid import UUID
19
29
 
20
30
  from pydantic import Field
@@ -31,8 +41,13 @@ from zenml.models.v2.base.scoped import (
31
41
  from zenml.models.v2.misc.build_item import BuildItem
32
42
 
33
43
  if TYPE_CHECKING:
44
+ from sqlalchemy.sql.elements import ColumnElement
45
+
34
46
  from zenml.models.v2.core.pipeline import PipelineResponse
35
47
  from zenml.models.v2.core.stack import StackResponse
48
+ from zenml.zen_stores.schemas import BaseSchema
49
+
50
+ AnySchema = TypeVar("AnySchema", bound=BaseSchema)
36
51
 
37
52
 
38
53
  # ------------------ Request Model ------------------
@@ -446,23 +461,23 @@ class PipelineBuildResponse(
446
461
  class PipelineBuildFilter(WorkspaceScopedFilter):
447
462
  """Model to enable advanced filtering of all pipeline builds."""
448
463
 
449
- workspace_id: Optional[Union[UUID, str]] = Field(
450
- description="Workspace for this pipeline build.",
451
- default=None,
452
- union_mode="left_to_right",
453
- )
454
- user_id: Optional[Union[UUID, str]] = Field(
455
- description="User that produced this pipeline build.",
456
- default=None,
457
- union_mode="left_to_right",
458
- )
464
+ FILTER_EXCLUDE_FIELDS: ClassVar[List[str]] = [
465
+ *WorkspaceScopedFilter.FILTER_EXCLUDE_FIELDS,
466
+ "container_registry_id",
467
+ ]
468
+
459
469
  pipeline_id: Optional[Union[UUID, str]] = Field(
460
470
  description="Pipeline associated with the pipeline build.",
461
471
  default=None,
462
472
  union_mode="left_to_right",
463
473
  )
464
474
  stack_id: Optional[Union[UUID, str]] = Field(
465
- description="Stack used for the Pipeline Run",
475
+ description="Stack associated with the pipeline build.",
476
+ default=None,
477
+ union_mode="left_to_right",
478
+ )
479
+ container_registry_id: Optional[Union[UUID, str]] = Field(
480
+ description="Container registry associated with the pipeline build.",
466
481
  default=None,
467
482
  union_mode="left_to_right",
468
483
  )
@@ -484,3 +499,43 @@ class PipelineBuildFilter(WorkspaceScopedFilter):
484
499
  checksum: Optional[str] = Field(
485
500
  description="The build checksum.", default=None
486
501
  )
502
+ stack_checksum: Optional[str] = Field(
503
+ description="The stack checksum.", default=None
504
+ )
505
+
506
+ def get_custom_filters(
507
+ self,
508
+ table: Type["AnySchema"],
509
+ ) -> List["ColumnElement[bool]"]:
510
+ """Get custom filters.
511
+
512
+ Args:
513
+ table: The query table.
514
+
515
+ Returns:
516
+ A list of custom filters.
517
+ """
518
+ custom_filters = super().get_custom_filters(table)
519
+
520
+ from sqlmodel import and_
521
+
522
+ from zenml.enums import StackComponentType
523
+ from zenml.zen_stores.schemas import (
524
+ PipelineBuildSchema,
525
+ StackComponentSchema,
526
+ StackCompositionSchema,
527
+ StackSchema,
528
+ )
529
+
530
+ if self.container_registry_id:
531
+ container_registry_filter = and_(
532
+ PipelineBuildSchema.stack_id == StackSchema.id,
533
+ StackSchema.id == StackCompositionSchema.stack_id,
534
+ StackCompositionSchema.component_id == StackComponentSchema.id,
535
+ StackComponentSchema.type
536
+ == StackComponentType.CONTAINER_REGISTRY.value,
537
+ StackComponentSchema.id == self.container_registry_id,
538
+ )
539
+ custom_filters.append(container_registry_filter)
540
+
541
+ return custom_filters
@@ -358,16 +358,6 @@ class PipelineDeploymentResponse(
358
358
  class PipelineDeploymentFilter(WorkspaceScopedFilter):
359
359
  """Model to enable advanced filtering of all pipeline deployments."""
360
360
 
361
- workspace_id: Optional[Union[UUID, str]] = Field(
362
- default=None,
363
- description="Workspace for this deployment.",
364
- union_mode="left_to_right",
365
- )
366
- user_id: Optional[Union[UUID, str]] = Field(
367
- default=None,
368
- description="User that created this deployment.",
369
- union_mode="left_to_right",
370
- )
371
361
  pipeline_id: Optional[Union[UUID, str]] = Field(
372
362
  default=None,
373
363
  description="Pipeline associated with the deployment.",
@@ -16,10 +16,13 @@
16
16
  from datetime import datetime
17
17
  from typing import (
18
18
  TYPE_CHECKING,
19
+ Any,
19
20
  ClassVar,
20
21
  Dict,
21
22
  List,
22
23
  Optional,
24
+ Type,
25
+ TypeVar,
23
26
  Union,
24
27
  cast,
25
28
  )
@@ -55,6 +58,11 @@ if TYPE_CHECKING:
55
58
  from zenml.models.v2.core.schedule import ScheduleResponse
56
59
  from zenml.models.v2.core.stack import StackResponse
57
60
  from zenml.models.v2.core.step_run import StepRunResponse
61
+ from zenml.zen_stores.schemas.base_schemas import BaseSchema
62
+
63
+ AnySchema = TypeVar("AnySchema", bound=BaseSchema)
64
+
65
+ AnyQuery = TypeVar("AnyQuery", bound=Any)
58
66
 
59
67
 
60
68
  # ------------------ Request Model ------------------
@@ -584,6 +592,15 @@ class PipelineRunResponse(
584
592
  class PipelineRunFilter(WorkspaceScopedTaggableFilter):
585
593
  """Model to enable advanced filtering of all Workspaces."""
586
594
 
595
+ CUSTOM_SORTING_OPTIONS: ClassVar[List[str]] = [
596
+ *WorkspaceScopedTaggableFilter.CUSTOM_SORTING_OPTIONS,
597
+ "tag",
598
+ "stack",
599
+ "pipeline",
600
+ "model",
601
+ "model_version",
602
+ ]
603
+
587
604
  FILTER_EXCLUDE_FIELDS: ClassVar[List[str]] = [
588
605
  *WorkspaceScopedTaggableFilter.FILTER_EXCLUDE_FIELDS,
589
606
  "unlisted",
@@ -592,7 +609,6 @@ class PipelineRunFilter(WorkspaceScopedTaggableFilter):
592
609
  "schedule_id",
593
610
  "stack_id",
594
611
  "template_id",
595
- "user",
596
612
  "pipeline",
597
613
  "stack",
598
614
  "code_repository",
@@ -615,16 +631,6 @@ class PipelineRunFilter(WorkspaceScopedTaggableFilter):
615
631
  description="Pipeline associated with the Pipeline Run",
616
632
  union_mode="left_to_right",
617
633
  )
618
- workspace_id: Optional[Union[UUID, str]] = Field(
619
- default=None,
620
- description="Workspace of the Pipeline Run",
621
- union_mode="left_to_right",
622
- )
623
- user_id: Optional[Union[UUID, str]] = Field(
624
- default=None,
625
- description="User that created the Pipeline Run",
626
- union_mode="left_to_right",
627
- )
628
634
  stack_id: Optional[Union[UUID, str]] = Field(
629
635
  default=None,
630
636
  description="Stack used for the Pipeline Run",
@@ -675,16 +681,12 @@ class PipelineRunFilter(WorkspaceScopedTaggableFilter):
675
681
  union_mode="left_to_right",
676
682
  )
677
683
  unlisted: Optional[bool] = None
678
- user: Optional[Union[UUID, str]] = Field(
679
- default=None,
680
- description="Name/ID of the user that created the run.",
681
- )
682
684
  run_metadata: Optional[Dict[str, str]] = Field(
683
685
  default=None,
684
686
  description="The run_metadata to filter the pipeline runs by.",
685
687
  )
686
688
  # TODO: Remove once frontend is ready for it. This is replaced by the more
687
- # generic `pipeline` filter below.
689
+ # generic `pipeline` filter below.
688
690
  pipeline_name: Optional[str] = Field(
689
691
  default=None,
690
692
  description="Name of the pipeline associated with the run",
@@ -716,13 +718,17 @@ class PipelineRunFilter(WorkspaceScopedTaggableFilter):
716
718
 
717
719
  def get_custom_filters(
718
720
  self,
721
+ table: Type["AnySchema"],
719
722
  ) -> List["ColumnElement[bool]"]:
720
723
  """Get custom filters.
721
724
 
725
+ Args:
726
+ table: The query table.
727
+
722
728
  Returns:
723
729
  A list of custom filters.
724
730
  """
725
- custom_filters = super().get_custom_filters()
731
+ custom_filters = super().get_custom_filters(table)
726
732
 
727
733
  from sqlmodel import and_, col, or_
728
734
 
@@ -741,7 +747,6 @@ class PipelineRunFilter(WorkspaceScopedTaggableFilter):
741
747
  StackComponentSchema,
742
748
  StackCompositionSchema,
743
749
  StackSchema,
744
- UserSchema,
745
750
  )
746
751
 
747
752
  if self.unlisted is not None:
@@ -792,17 +797,6 @@ class PipelineRunFilter(WorkspaceScopedTaggableFilter):
792
797
  )
793
798
  custom_filters.append(run_template_filter)
794
799
 
795
- if self.user:
796
- user_filter = and_(
797
- PipelineRunSchema.user_id == UserSchema.id,
798
- self.generate_name_or_id_query_conditions(
799
- value=self.user,
800
- table=UserSchema,
801
- additional_columns=["full_name"],
802
- ),
803
- )
804
- custom_filters.append(user_filter)
805
-
806
800
  if self.pipeline:
807
801
  pipeline_filter = and_(
808
802
  PipelineRunSchema.pipeline_id == PipelineSchema.id,
@@ -926,3 +920,71 @@ class PipelineRunFilter(WorkspaceScopedTaggableFilter):
926
920
  custom_filters.append(additional_filter)
927
921
 
928
922
  return custom_filters
923
+
924
+ def apply_sorting(
925
+ self,
926
+ query: AnyQuery,
927
+ table: Type["AnySchema"],
928
+ ) -> AnyQuery:
929
+ """Apply sorting to the query.
930
+
931
+ Args:
932
+ query: The query to which to apply the sorting.
933
+ table: The query table.
934
+
935
+ Returns:
936
+ The query with sorting applied.
937
+ """
938
+ from sqlmodel import asc, desc
939
+
940
+ from zenml.enums import SorterOps
941
+ from zenml.zen_stores.schemas import (
942
+ ModelSchema,
943
+ ModelVersionSchema,
944
+ PipelineDeploymentSchema,
945
+ PipelineRunSchema,
946
+ PipelineSchema,
947
+ StackSchema,
948
+ )
949
+
950
+ sort_by, operand = self.sorting_params
951
+
952
+ if sort_by == "pipeline":
953
+ query = query.join(
954
+ PipelineSchema,
955
+ PipelineRunSchema.pipeline_id == PipelineSchema.id,
956
+ )
957
+ column = PipelineSchema.name
958
+ elif sort_by == "stack":
959
+ query = query.join(
960
+ PipelineDeploymentSchema,
961
+ PipelineRunSchema.deployment_id == PipelineDeploymentSchema.id,
962
+ ).join(
963
+ StackSchema,
964
+ PipelineDeploymentSchema.stack_id == StackSchema.id,
965
+ )
966
+ column = StackSchema.name
967
+ elif sort_by == "model":
968
+ query = query.join(
969
+ ModelVersionSchema,
970
+ PipelineRunSchema.model_version_id == ModelVersionSchema.id,
971
+ ).join(
972
+ ModelSchema,
973
+ ModelVersionSchema.model_id == ModelSchema.id,
974
+ )
975
+ column = ModelSchema.name
976
+ elif sort_by == "model_version":
977
+ query = query.join(
978
+ ModelVersionSchema,
979
+ PipelineRunSchema.model_version_id == ModelVersionSchema.id,
980
+ )
981
+ column = ModelVersionSchema.name
982
+ else:
983
+ return super().apply_sorting(query=query, table=table)
984
+
985
+ if operand == SorterOps.ASCENDING:
986
+ query = query.order_by(asc(column))
987
+ else:
988
+ query = query.order_by(desc(column))
989
+
990
+ return query