zenml-nightly 0.70.0.dev20241201__py3-none-any.whl → 0.71.0.dev20241223__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.dev20241223.dist-info}/METADATA +5 -5
  176. {zenml_nightly-0.70.0.dev20241201.dist-info → zenml_nightly-0.71.0.dev20241223.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.dev20241223.dist-info}/LICENSE +0 -0
  192. {zenml_nightly-0.70.0.dev20241201.dist-info → zenml_nightly-0.71.0.dev20241223.dist-info}/WHEEL +0 -0
  193. {zenml_nightly-0.70.0.dev20241201.dist-info → zenml_nightly-0.71.0.dev20241223.dist-info}/entry_points.txt +0 -0
@@ -23,6 +23,7 @@ from typing import (
23
23
  Optional,
24
24
  Type,
25
25
  TypeVar,
26
+ Union,
26
27
  )
27
28
  from uuid import UUID
28
29
 
@@ -151,16 +152,32 @@ class UserScopedFilter(BaseFilter):
151
152
 
152
153
  FILTER_EXCLUDE_FIELDS: ClassVar[List[str]] = [
153
154
  *BaseFilter.FILTER_EXCLUDE_FIELDS,
155
+ "user",
154
156
  "scope_user",
155
157
  ]
156
158
  CLI_EXCLUDE_FIELDS: ClassVar[List[str]] = [
157
159
  *BaseFilter.CLI_EXCLUDE_FIELDS,
160
+ "user_id",
158
161
  "scope_user",
159
162
  ]
163
+ CUSTOM_SORTING_OPTIONS: ClassVar[List[str]] = [
164
+ *BaseFilter.CUSTOM_SORTING_OPTIONS,
165
+ "user",
166
+ ]
167
+
160
168
  scope_user: Optional[UUID] = Field(
161
169
  default=None,
162
170
  description="The user to scope this query to.",
163
171
  )
172
+ user_id: Optional[Union[UUID, str]] = Field(
173
+ default=None,
174
+ description="UUID of the user that created the entity.",
175
+ union_mode="left_to_right",
176
+ )
177
+ user: Optional[Union[UUID, str]] = Field(
178
+ default=None,
179
+ description="Name/ID of the user that created the entity.",
180
+ )
164
181
 
165
182
  def set_scope_user(self, user_id: UUID) -> None:
166
183
  """Set the user that is performing the filtering to scope the response.
@@ -170,6 +187,73 @@ class UserScopedFilter(BaseFilter):
170
187
  """
171
188
  self.scope_user = user_id
172
189
 
190
+ def get_custom_filters(
191
+ self, table: Type["AnySchema"]
192
+ ) -> List["ColumnElement[bool]"]:
193
+ """Get custom filters.
194
+
195
+ Args:
196
+ table: The query table.
197
+
198
+ Returns:
199
+ A list of custom filters.
200
+ """
201
+ custom_filters = super().get_custom_filters(table)
202
+
203
+ from sqlmodel import and_
204
+
205
+ from zenml.zen_stores.schemas import UserSchema
206
+
207
+ if self.user:
208
+ user_filter = and_(
209
+ getattr(table, "user_id") == UserSchema.id,
210
+ self.generate_name_or_id_query_conditions(
211
+ value=self.user,
212
+ table=UserSchema,
213
+ additional_columns=["full_name"],
214
+ ),
215
+ )
216
+ custom_filters.append(user_filter)
217
+
218
+ return custom_filters
219
+
220
+ def apply_sorting(
221
+ self,
222
+ query: AnyQuery,
223
+ table: Type["AnySchema"],
224
+ ) -> AnyQuery:
225
+ """Apply sorting to the query.
226
+
227
+ Args:
228
+ query: The query to which to apply the sorting.
229
+ table: The query table.
230
+
231
+ Returns:
232
+ The query with sorting applied.
233
+ """
234
+ from sqlmodel import asc, desc
235
+
236
+ from zenml.enums import SorterOps
237
+ from zenml.zen_stores.schemas import UserSchema
238
+
239
+ sort_by, operand = self.sorting_params
240
+
241
+ if sort_by == "user":
242
+ column = UserSchema.name
243
+
244
+ query = query.join(
245
+ UserSchema, getattr(table, "user_id") == UserSchema.id
246
+ )
247
+
248
+ if operand == SorterOps.ASCENDING:
249
+ query = query.order_by(asc(column))
250
+ else:
251
+ query = query.order_by(desc(column))
252
+
253
+ return query
254
+
255
+ return super().apply_sorting(query=query, table=table)
256
+
173
257
  def apply_filter(
174
258
  self,
175
259
  query: AnyQuery,
@@ -240,21 +324,37 @@ class WorkspaceScopedResponse(
240
324
  return self.get_metadata().workspace
241
325
 
242
326
 
243
- class WorkspaceScopedFilter(BaseFilter):
327
+ class WorkspaceScopedFilter(UserScopedFilter):
244
328
  """Model to enable advanced scoping with workspace."""
245
329
 
246
330
  FILTER_EXCLUDE_FIELDS: ClassVar[List[str]] = [
247
- *BaseFilter.FILTER_EXCLUDE_FIELDS,
331
+ *UserScopedFilter.FILTER_EXCLUDE_FIELDS,
332
+ "workspace",
248
333
  "scope_workspace",
249
334
  ]
250
335
  CLI_EXCLUDE_FIELDS: ClassVar[List[str]] = [
251
- *BaseFilter.CLI_EXCLUDE_FIELDS,
336
+ *UserScopedFilter.CLI_EXCLUDE_FIELDS,
337
+ "workspace_id",
338
+ "workspace",
252
339
  "scope_workspace",
253
340
  ]
341
+ CUSTOM_SORTING_OPTIONS: ClassVar[List[str]] = [
342
+ *UserScopedFilter.CUSTOM_SORTING_OPTIONS,
343
+ "workspace",
344
+ ]
254
345
  scope_workspace: Optional[UUID] = Field(
255
346
  default=None,
256
347
  description="The workspace to scope this query to.",
257
348
  )
349
+ workspace_id: Optional[Union[UUID, str]] = Field(
350
+ default=None,
351
+ description="UUID of the workspace that this entity belongs to.",
352
+ union_mode="left_to_right",
353
+ )
354
+ workspace: Optional[Union[UUID, str]] = Field(
355
+ default=None,
356
+ description="Name/ID of the workspace that this entity belongs to.",
357
+ )
258
358
 
259
359
  def set_scope_workspace(self, workspace_id: UUID) -> None:
260
360
  """Set the workspace to scope this response.
@@ -264,6 +364,35 @@ class WorkspaceScopedFilter(BaseFilter):
264
364
  """
265
365
  self.scope_workspace = workspace_id
266
366
 
367
+ def get_custom_filters(
368
+ self, table: Type["AnySchema"]
369
+ ) -> List["ColumnElement[bool]"]:
370
+ """Get custom filters.
371
+
372
+ Args:
373
+ table: The query table.
374
+
375
+ Returns:
376
+ A list of custom filters.
377
+ """
378
+ custom_filters = super().get_custom_filters(table)
379
+
380
+ from sqlmodel import and_
381
+
382
+ from zenml.zen_stores.schemas import WorkspaceSchema
383
+
384
+ if self.workspace:
385
+ workspace_filter = and_(
386
+ getattr(table, "workspace_id") == WorkspaceSchema.id,
387
+ self.generate_name_or_id_query_conditions(
388
+ value=self.workspace,
389
+ table=WorkspaceSchema,
390
+ ),
391
+ )
392
+ custom_filters.append(workspace_filter)
393
+
394
+ return custom_filters
395
+
267
396
  def apply_filter(
268
397
  self,
269
398
  query: AnyQuery,
@@ -291,6 +420,44 @@ class WorkspaceScopedFilter(BaseFilter):
291
420
 
292
421
  return query
293
422
 
423
+ def apply_sorting(
424
+ self,
425
+ query: AnyQuery,
426
+ table: Type["AnySchema"],
427
+ ) -> AnyQuery:
428
+ """Apply sorting to the query.
429
+
430
+ Args:
431
+ query: The query to which to apply the sorting.
432
+ table: The query table.
433
+
434
+ Returns:
435
+ The query with sorting applied.
436
+ """
437
+ from sqlmodel import asc, desc
438
+
439
+ from zenml.enums import SorterOps
440
+ from zenml.zen_stores.schemas import WorkspaceSchema
441
+
442
+ sort_by, operand = self.sorting_params
443
+
444
+ if sort_by == "workspace":
445
+ column = WorkspaceSchema.name
446
+
447
+ query = query.join(
448
+ WorkspaceSchema,
449
+ getattr(table, "workspace_id") == WorkspaceSchema.id,
450
+ )
451
+
452
+ if operand == SorterOps.ASCENDING:
453
+ query = query.order_by(asc(column))
454
+ else:
455
+ query = query.order_by(desc(column))
456
+
457
+ return query
458
+
459
+ return super().apply_sorting(query=query, table=table)
460
+
294
461
 
295
462
  class WorkspaceScopedTaggableFilter(WorkspaceScopedFilter):
296
463
  """Model to enable advanced scoping with workspace and tagging."""
@@ -304,6 +471,11 @@ class WorkspaceScopedTaggableFilter(WorkspaceScopedFilter):
304
471
  "tag",
305
472
  ]
306
473
 
474
+ CUSTOM_SORTING_OPTIONS: ClassVar[List[str]] = [
475
+ *WorkspaceScopedFilter.CUSTOM_SORTING_OPTIONS,
476
+ "tag",
477
+ ]
478
+
307
479
  def apply_filter(
308
480
  self,
309
481
  query: AnyQuery,
@@ -330,15 +502,20 @@ class WorkspaceScopedTaggableFilter(WorkspaceScopedFilter):
330
502
 
331
503
  return query
332
504
 
333
- def get_custom_filters(self) -> List["ColumnElement[bool]"]:
505
+ def get_custom_filters(
506
+ self, table: Type["AnySchema"]
507
+ ) -> List["ColumnElement[bool]"]:
334
508
  """Get custom tag filters.
335
509
 
510
+ Args:
511
+ table: The query table.
512
+
336
513
  Returns:
337
514
  A list of custom filters.
338
515
  """
339
516
  from zenml.zen_stores.schemas import TagSchema
340
517
 
341
- custom_filters = super().get_custom_filters()
518
+ custom_filters = super().get_custom_filters(table)
342
519
  if self.tag:
343
520
  custom_filters.append(
344
521
  self.generate_custom_query_conditions_for_column(
@@ -347,3 +524,79 @@ class WorkspaceScopedTaggableFilter(WorkspaceScopedFilter):
347
524
  )
348
525
 
349
526
  return custom_filters
527
+
528
+ def apply_sorting(
529
+ self,
530
+ query: AnyQuery,
531
+ table: Type["AnySchema"],
532
+ ) -> AnyQuery:
533
+ """Apply sorting to the query.
534
+
535
+ Args:
536
+ query: The query to which to apply the sorting.
537
+ table: The query table.
538
+
539
+ Returns:
540
+ The query with sorting applied.
541
+ """
542
+ sort_by, operand = self.sorting_params
543
+
544
+ if sort_by == "tag":
545
+ from sqlmodel import and_, asc, desc, func
546
+
547
+ from zenml.enums import SorterOps, TaggableResourceTypes
548
+ from zenml.zen_stores.schemas import (
549
+ ArtifactSchema,
550
+ ArtifactVersionSchema,
551
+ ModelSchema,
552
+ ModelVersionSchema,
553
+ PipelineRunSchema,
554
+ PipelineSchema,
555
+ RunTemplateSchema,
556
+ TagResourceSchema,
557
+ TagSchema,
558
+ )
559
+
560
+ resource_type_mapping = {
561
+ ArtifactSchema: TaggableResourceTypes.ARTIFACT,
562
+ ArtifactVersionSchema: TaggableResourceTypes.ARTIFACT_VERSION,
563
+ ModelSchema: TaggableResourceTypes.MODEL,
564
+ ModelVersionSchema: TaggableResourceTypes.MODEL_VERSION,
565
+ PipelineSchema: TaggableResourceTypes.PIPELINE,
566
+ PipelineRunSchema: TaggableResourceTypes.PIPELINE_RUN,
567
+ RunTemplateSchema: TaggableResourceTypes.RUN_TEMPLATE,
568
+ }
569
+
570
+ query = (
571
+ query.outerjoin(
572
+ TagResourceSchema,
573
+ and_(
574
+ table.id == TagResourceSchema.resource_id,
575
+ TagResourceSchema.resource_type
576
+ == resource_type_mapping[table],
577
+ ),
578
+ )
579
+ .outerjoin(TagSchema, TagResourceSchema.tag_id == TagSchema.id)
580
+ .group_by(table.id)
581
+ )
582
+
583
+ if operand == SorterOps.ASCENDING:
584
+ query = query.order_by(
585
+ asc(
586
+ func.group_concat(TagSchema.name, ",").label(
587
+ "tags_list"
588
+ )
589
+ )
590
+ )
591
+ else:
592
+ query = query.order_by(
593
+ desc(
594
+ func.group_concat(TagSchema.name, ",").label(
595
+ "tags_list"
596
+ )
597
+ )
598
+ )
599
+
600
+ return query
601
+
602
+ return super().apply_sorting(query=query, table=table)
@@ -20,6 +20,8 @@ from typing import (
20
20
  Dict,
21
21
  List,
22
22
  Optional,
23
+ Type,
24
+ TypeVar,
23
25
  Union,
24
26
  )
25
27
  from uuid import UUID
@@ -58,6 +60,10 @@ if TYPE_CHECKING:
58
60
  )
59
61
  from zenml.models.v2.core.pipeline_run import PipelineRunResponse
60
62
  from zenml.models.v2.core.step_run import StepRunResponse
63
+ from zenml.zen_stores.schemas.base_schemas import BaseSchema
64
+
65
+ AnySchema = TypeVar("AnySchema", bound=BaseSchema)
66
+
61
67
 
62
68
  logger = get_logger(__name__)
63
69
 
@@ -471,7 +477,6 @@ class ArtifactVersionFilter(WorkspaceScopedTaggableFilter):
471
477
  "name",
472
478
  "only_unused",
473
479
  "has_custom_name",
474
- "user",
475
480
  "model",
476
481
  "pipeline_run",
477
482
  "model_version_id",
@@ -516,19 +521,10 @@ class ArtifactVersionFilter(WorkspaceScopedTaggableFilter):
516
521
  description="Artifact store for this artifact",
517
522
  union_mode="left_to_right",
518
523
  )
519
- workspace_id: Optional[Union[UUID, str]] = Field(
520
- default=None,
521
- description="Workspace for this artifact",
522
- union_mode="left_to_right",
523
- )
524
- user_id: Optional[Union[UUID, str]] = Field(
525
- default=None,
526
- description="User that produced this artifact",
527
- union_mode="left_to_right",
528
- )
529
524
  model_version_id: Optional[Union[UUID, str]] = Field(
530
525
  default=None,
531
- description="ID of the model version that is associated with this artifact version.",
526
+ description="ID of the model version that is associated with this "
527
+ "artifact version.",
532
528
  union_mode="left_to_right",
533
529
  )
534
530
  only_unused: Optional[bool] = Field(
@@ -559,13 +555,18 @@ class ArtifactVersionFilter(WorkspaceScopedTaggableFilter):
559
555
 
560
556
  model_config = ConfigDict(protected_namespaces=())
561
557
 
562
- def get_custom_filters(self) -> List[Union["ColumnElement[bool]"]]:
558
+ def get_custom_filters(
559
+ self, table: Type["AnySchema"]
560
+ ) -> List[Union["ColumnElement[bool]"]]:
563
561
  """Get custom filters.
564
562
 
563
+ Args:
564
+ table: The query table.
565
+
565
566
  Returns:
566
567
  A list of custom filters.
567
568
  """
568
- custom_filters = super().get_custom_filters()
569
+ custom_filters = super().get_custom_filters(table)
569
570
 
570
571
  from sqlmodel import and_, or_, select
571
572
 
@@ -581,7 +582,6 @@ class ArtifactVersionFilter(WorkspaceScopedTaggableFilter):
581
582
  StepRunInputArtifactSchema,
582
583
  StepRunOutputArtifactSchema,
583
584
  StepRunSchema,
584
- UserSchema,
585
585
  )
586
586
 
587
587
  if self.name:
@@ -629,17 +629,6 @@ class ArtifactVersionFilter(WorkspaceScopedTaggableFilter):
629
629
  )
630
630
  custom_filters.append(custom_name_filter)
631
631
 
632
- if self.user:
633
- user_filter = and_(
634
- ArtifactVersionSchema.user_id == UserSchema.id,
635
- self.generate_name_or_id_query_conditions(
636
- value=self.user,
637
- table=UserSchema,
638
- additional_columns=["full_name"],
639
- ),
640
- )
641
- custom_filters.append(user_filter)
642
-
643
632
  if self.model:
644
633
  model_filter = and_(
645
634
  ArtifactVersionSchema.id
@@ -13,8 +13,7 @@
13
13
  # permissions and limitations under the License.
14
14
  """Models representing code repositories."""
15
15
 
16
- from typing import Any, Dict, Optional, Union
17
- from uuid import UUID
16
+ from typing import Any, Dict, Optional
18
17
 
19
18
  from pydantic import Field
20
19
 
@@ -189,13 +188,3 @@ class CodeRepositoryFilter(WorkspaceScopedFilter):
189
188
  description="Name of the code repository.",
190
189
  default=None,
191
190
  )
192
- workspace_id: Optional[Union[UUID, str]] = Field(
193
- description="Workspace of the code repository.",
194
- default=None,
195
- union_mode="left_to_right",
196
- )
197
- user_id: Optional[Union[UUID, str]] = Field(
198
- description="User that created the code repository.",
199
- default=None,
200
- union_mode="left_to_right",
201
- )
@@ -21,6 +21,7 @@ from typing import (
21
21
  List,
22
22
  Optional,
23
23
  Type,
24
+ TypeVar,
24
25
  Union,
25
26
  )
26
27
  from uuid import UUID
@@ -42,9 +43,11 @@ from zenml.utils import secret_utils
42
43
 
43
44
  if TYPE_CHECKING:
44
45
  from sqlalchemy.sql.elements import ColumnElement
45
- from sqlmodel import SQLModel
46
46
 
47
47
  from zenml.models import FlavorResponse, ServiceConnectorResponse
48
+ from zenml.zen_stores.schemas.base_schemas import BaseSchema
49
+
50
+ AnySchema = TypeVar("AnySchema", bound=BaseSchema)
48
51
 
49
52
  # ------------------ Base Model ------------------
50
53
 
@@ -356,7 +359,6 @@ class ComponentFilter(WorkspaceScopedFilter):
356
359
  *WorkspaceScopedFilter.FILTER_EXCLUDE_FIELDS,
357
360
  "scope_type",
358
361
  "stack_id",
359
- "user",
360
362
  ]
361
363
  CLI_EXCLUDE_FIELDS: ClassVar[List[str]] = [
362
364
  *WorkspaceScopedFilter.CLI_EXCLUDE_FIELDS,
@@ -366,7 +368,6 @@ class ComponentFilter(WorkspaceScopedFilter):
366
368
  default=None,
367
369
  description="The type to scope this query to.",
368
370
  )
369
-
370
371
  name: Optional[str] = Field(
371
372
  default=None,
372
373
  description="Name of the stack component",
@@ -379,16 +380,6 @@ class ComponentFilter(WorkspaceScopedFilter):
379
380
  default=None,
380
381
  description="Type of the stack component",
381
382
  )
382
- workspace_id: Optional[Union[UUID, str]] = Field(
383
- default=None,
384
- description="Workspace of the stack component",
385
- union_mode="left_to_right",
386
- )
387
- user_id: Optional[Union[UUID, str]] = Field(
388
- default=None,
389
- description="User of the stack component",
390
- union_mode="left_to_right",
391
- )
392
383
  connector_id: Optional[Union[UUID, str]] = Field(
393
384
  default=None,
394
385
  description="Connector linked to the stack component",
@@ -399,10 +390,6 @@ class ComponentFilter(WorkspaceScopedFilter):
399
390
  description="Stack of the stack component",
400
391
  union_mode="left_to_right",
401
392
  )
402
- user: Optional[Union[UUID, str]] = Field(
403
- default=None,
404
- description="Name/ID of the user that created the component.",
405
- )
406
393
 
407
394
  def set_scope_type(self, component_type: str) -> None:
408
395
  """Set the type of component on which to perform the filtering to scope the response.
@@ -413,7 +400,7 @@ class ComponentFilter(WorkspaceScopedFilter):
413
400
  self.scope_type = component_type
414
401
 
415
402
  def generate_filter(
416
- self, table: Type["SQLModel"]
403
+ self, table: Type["AnySchema"]
417
404
  ) -> Union["ColumnElement[bool]"]:
418
405
  """Generate the filter for the query.
419
406
 
@@ -449,31 +436,3 @@ class ComponentFilter(WorkspaceScopedFilter):
449
436
  base_filter = operator(base_filter, stack_filter)
450
437
 
451
438
  return base_filter
452
-
453
- def get_custom_filters(self) -> List["ColumnElement[bool]"]:
454
- """Get custom filters.
455
-
456
- Returns:
457
- A list of custom filters.
458
- """
459
- from sqlmodel import and_
460
-
461
- from zenml.zen_stores.schemas import (
462
- StackComponentSchema,
463
- UserSchema,
464
- )
465
-
466
- custom_filters = super().get_custom_filters()
467
-
468
- if self.user:
469
- user_filter = and_(
470
- StackComponentSchema.user_id == UserSchema.id,
471
- self.generate_name_or_id_query_conditions(
472
- value=self.user,
473
- table=UserSchema,
474
- additional_columns=["full_name"],
475
- ),
476
- )
477
- custom_filters.append(user_filter)
478
-
479
- return custom_filters
@@ -13,7 +13,7 @@
13
13
  # permissions and limitations under the License.
14
14
  """Models representing flavors."""
15
15
 
16
- from typing import TYPE_CHECKING, Any, ClassVar, Dict, List, Optional, Union
16
+ from typing import TYPE_CHECKING, Any, ClassVar, Dict, List, Optional
17
17
  from uuid import UUID
18
18
 
19
19
  from pydantic import Field
@@ -428,13 +428,3 @@ class FlavorFilter(WorkspaceScopedFilter):
428
428
  default=None,
429
429
  description="Integration associated with the flavor",
430
430
  )
431
- workspace_id: Optional[Union[UUID, str]] = Field(
432
- default=None,
433
- description="Workspace of the stack",
434
- union_mode="left_to_right",
435
- )
436
- user_id: Optional[Union[UUID, str]] = Field(
437
- default=None,
438
- description="User of the stack",
439
- union_mode="left_to_right",
440
- )
@@ -13,7 +13,7 @@
13
13
  # permissions and limitations under the License.
14
14
  """Models representing models."""
15
15
 
16
- from typing import TYPE_CHECKING, ClassVar, List, Optional, Union
16
+ from typing import TYPE_CHECKING, List, Optional
17
17
  from uuid import UUID
18
18
 
19
19
  from pydantic import BaseModel, Field
@@ -30,8 +30,6 @@ from zenml.models.v2.base.scoped import (
30
30
  from zenml.utils.pagination_utils import depaginate
31
31
 
32
32
  if TYPE_CHECKING:
33
- from sqlalchemy.sql.elements import ColumnElement
34
-
35
33
  from zenml.model.model import Model
36
34
  from zenml.models.v2.core.tag import TagResponse
37
35
 
@@ -318,61 +316,7 @@ class ModelResponse(
318
316
  class ModelFilter(WorkspaceScopedTaggableFilter):
319
317
  """Model to enable advanced filtering of all Workspaces."""
320
318
 
321
- CLI_EXCLUDE_FIELDS: ClassVar[List[str]] = [
322
- *WorkspaceScopedTaggableFilter.CLI_EXCLUDE_FIELDS,
323
- "workspace_id",
324
- "user_id",
325
- ]
326
- FILTER_EXCLUDE_FIELDS: ClassVar[List[str]] = [
327
- *WorkspaceScopedTaggableFilter.FILTER_EXCLUDE_FIELDS,
328
- "user",
329
- ]
330
-
331
319
  name: Optional[str] = Field(
332
320
  default=None,
333
321
  description="Name of the Model",
334
322
  )
335
- workspace_id: Optional[Union[UUID, str]] = Field(
336
- default=None,
337
- description="Workspace of the Model",
338
- union_mode="left_to_right",
339
- )
340
- user_id: Optional[Union[UUID, str]] = Field(
341
- default=None,
342
- description="User of the Model",
343
- union_mode="left_to_right",
344
- )
345
- user: Optional[Union[UUID, str]] = Field(
346
- default=None,
347
- description="Name/ID of the user that created the model.",
348
- )
349
-
350
- def get_custom_filters(
351
- self,
352
- ) -> List["ColumnElement[bool]"]:
353
- """Get custom filters.
354
-
355
- Returns:
356
- A list of custom filters.
357
- """
358
- custom_filters = super().get_custom_filters()
359
-
360
- from sqlmodel import and_
361
-
362
- from zenml.zen_stores.schemas import (
363
- ModelSchema,
364
- UserSchema,
365
- )
366
-
367
- if self.user:
368
- user_filter = and_(
369
- ModelSchema.user_id == UserSchema.id,
370
- self.generate_name_or_id_query_conditions(
371
- value=self.user,
372
- table=UserSchema,
373
- additional_columns=["full_name"],
374
- ),
375
- )
376
- custom_filters.append(user_filter)
377
-
378
- return custom_filters