zenml-nightly 0.71.0.dev20250109__py3-none-any.whl → 0.71.0.dev20250110__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 (99) hide show
  1. zenml/VERSION +1 -1
  2. zenml/cli/base.py +1 -1
  3. zenml/constants.py +1 -0
  4. zenml/models/v2/base/scoped.py +32 -28
  5. zenml/models/v2/core/artifact.py +86 -2
  6. zenml/models/v2/core/model.py +81 -2
  7. zenml/models/v2/core/pipeline.py +15 -12
  8. zenml/models/v2/core/pipeline_run.py +2 -0
  9. zenml/zen_server/dashboard/assets/{404-Cqu3EDCm.js → 404-Dfq64Boz.js} +1 -1
  10. zenml/zen_server/dashboard/assets/{@reactflow-D2Y7BWwz.js → @reactflow-BUNIMFeC.js} +1 -1
  11. zenml/zen_server/dashboard/assets/{AlertDialogDropdownItem-BHd71pVS.js → AlertDialogDropdownItem-B73Vs10T.js} +1 -1
  12. zenml/zen_server/dashboard/assets/{CodeSnippet-DIonwetW.js → CodeSnippet-DIJRT2NT.js} +1 -1
  13. zenml/zen_server/dashboard/assets/{CollapsibleCard-CDnC97pB.js → CollapsibleCard-BzUHGZOU.js} +1 -1
  14. zenml/zen_server/dashboard/assets/{Commands-BVEXKAOj.js → Commands-BEGyld4c.js} +1 -1
  15. zenml/zen_server/dashboard/assets/{ComponentBadge-CrRvovox.js → ComponentBadge-xyKiek1s.js} +1 -1
  16. zenml/zen_server/dashboard/assets/{CopyButton-B6wGAhQv.js → CopyButton-DhW-mapu.js} +1 -1
  17. zenml/zen_server/dashboard/assets/{CsvVizualization-CjcT7LMm.js → CsvVizualization-D8oazBiE.js} +1 -1
  18. zenml/zen_server/dashboard/assets/{DeleteAlertDialog-D2ELtM2W.js → DeleteAlertDialog-WkSIIgfy.js} +1 -1
  19. zenml/zen_server/dashboard/assets/{DialogItem-DXIMhBgU.js → DialogItem-Bgroeg29.js} +1 -1
  20. zenml/zen_server/dashboard/assets/{Error-B8uUfTpL.js → Error-CY5tlu17.js} +1 -1
  21. zenml/zen_server/dashboard/assets/{ExecutionStatus-ibAdY-dG.js → ExecutionStatus-G8mjIaeA.js} +1 -1
  22. zenml/zen_server/dashboard/assets/{Helpbox-BfAfhKHw.js → Helpbox-Bb1ed--O.js} +1 -1
  23. zenml/zen_server/dashboard/assets/{Infobox-M_SMOu96.js → Infobox-Da6-76M2.js} +1 -1
  24. zenml/zen_server/dashboard/assets/{InlineAvatar-DBA0a0-a.js → InlineAvatar-DqnZaBNq.js} +1 -1
  25. zenml/zen_server/dashboard/assets/{NestedCollapsible-DpgmEFKw.js → NestedCollapsible-aK5ojKoF.js} +1 -1
  26. zenml/zen_server/dashboard/assets/{Partials-D_ldD9if.js → Partials-CqZp5NMX.js} +1 -1
  27. zenml/zen_server/dashboard/assets/{ProBadge-DQbfFotM.js → ProBadge-B4tRUYve.js} +1 -1
  28. zenml/zen_server/dashboard/assets/{ProCta-Bcpb4rcY.js → ProCta-CZuP29Qz.js} +1 -1
  29. zenml/zen_server/dashboard/assets/{ProviderIcon-BZpgPigN.js → ProviderIcon-Bd7GUQ1_.js} +1 -1
  30. zenml/zen_server/dashboard/assets/{ProviderRadio-DWPnMuQ1.js → ProviderRadio-mstdqzsS.js} +1 -1
  31. zenml/zen_server/dashboard/assets/{RunSelector-DgRGaAc6.js → RunSelector-CsruSB4i.js} +1 -1
  32. zenml/zen_server/dashboard/assets/{RunsBody-KecfSkjY.js → RunsBody-DxxtWVYz.js} +1 -1
  33. zenml/zen_server/dashboard/assets/{SearchField-n-ILHnaP.js → SearchField-D6tPxyqw.js} +1 -1
  34. zenml/zen_server/dashboard/assets/{SecretTooltip-B8MrX5yu.js → SecretTooltip-CLzJIYW_.js} +1 -1
  35. zenml/zen_server/dashboard/assets/{SetPassword-B_IVq_wg.js → SetPassword-Yn50ooBC.js} +1 -1
  36. zenml/zen_server/dashboard/assets/{StackList-TWPBYnkF.js → StackList-U537qoYd.js} +1 -1
  37. zenml/zen_server/dashboard/assets/{Tabs-Rg857zmd.js → Tabs-CNv-eTYM.js} +1 -1
  38. zenml/zen_server/dashboard/assets/{Tick-COg4A-xo.js → Tick-jEIevzVf.js} +1 -1
  39. zenml/zen_server/dashboard/assets/{UpdatePasswordSchemas-C6Aj3hm6.js → UpdatePasswordSchemas-C16GW-kX.js} +1 -1
  40. zenml/zen_server/dashboard/assets/{UsageReason-BTLbx7w4.js → UsageReason-Bf2tzhv1.js} +1 -1
  41. zenml/zen_server/dashboard/assets/{WizardFooter-BCAj69Vj.js → WizardFooter-D6i-AP1K.js} +1 -1
  42. zenml/zen_server/dashboard/assets/{all-pipeline-runs-query-DMXkDrV2.js → all-pipeline-runs-query-DUti43aF.js} +1 -1
  43. zenml/zen_server/dashboard/assets/{create-stack-HfdbhLs4.js → create-stack-Ch2WPs9U.js} +1 -1
  44. zenml/zen_server/dashboard/assets/{delete-run-DZ4hIXff.js → delete-run-Byf9hTjA.js} +1 -1
  45. zenml/zen_server/dashboard/assets/{form-schemas-B0AVEd9b.js → form-schemas-BZqKBPBF.js} +1 -1
  46. zenml/zen_server/dashboard/assets/{index-FO-p0GU7.js → index-CE0aQlv8.js} +3 -3
  47. zenml/zen_server/dashboard/assets/{index-DScjfBRb.js → index-CtdYkjUi.js} +1 -1
  48. zenml/zen_server/dashboard/assets/{index-DPqSWjug.js → index-CyBKZcpO.js} +1 -1
  49. zenml/zen_server/dashboard/assets/{index-I3bKUGUj.js → index-v6gQjDEo.js} +1 -1
  50. zenml/zen_server/dashboard/assets/{login-mutation-BQeo4wTY.js → login-mutation-DNDVp_2H.js} +1 -1
  51. zenml/zen_server/dashboard/assets/{not-found-gAJ5aDdR.js → not-found-Bmup4ctE.js} +1 -1
  52. zenml/zen_server/dashboard/assets/{page-I3nKFGie.js → page--XLMzHrn.js} +1 -1
  53. zenml/zen_server/dashboard/assets/{page-DO1UcqPX.js → page-ANYGfEUL.js} +1 -1
  54. zenml/zen_server/dashboard/assets/{page-AUwiQ14W.js → page-B5Sr8pib.js} +1 -1
  55. zenml/zen_server/dashboard/assets/{page-CcQr8CPP.js → page-BC27C_OI.js} +1 -1
  56. zenml/zen_server/dashboard/assets/{page-zaMqB_ao.js → page-BNxYrN0q.js} +1 -1
  57. zenml/zen_server/dashboard/assets/{page-CiYxgZP_.js → page-BYJfqgLN.js} +1 -1
  58. zenml/zen_server/dashboard/assets/{page-h_Stveon.js → page-B_0XkV48.js} +1 -1
  59. zenml/zen_server/dashboard/assets/{page-R5dx3xGF.js → page-BrmJp1Wt.js} +1 -1
  60. zenml/zen_server/dashboard/assets/page-C2nU3Gxn.js +1 -0
  61. zenml/zen_server/dashboard/assets/{page-Dk32IeZm.js → page-C70wZtV2.js} +1 -1
  62. zenml/zen_server/dashboard/assets/{page-CWxT5K5J.js → page-CHRn1fQm.js} +1 -1
  63. zenml/zen_server/dashboard/assets/{page-M0w-n6vn.js → page-CWr96ZKN.js} +1 -1
  64. zenml/zen_server/dashboard/assets/{page-Ce4Hrjnr.js → page-CXAbSyp9.js} +1 -1
  65. zenml/zen_server/dashboard/assets/{page-D8ObrbH8.js → page-CaeI9ptC.js} +1 -1
  66. zenml/zen_server/dashboard/assets/{page-B_Apk3xg.js → page-Cc8ZEuj4.js} +1 -1
  67. zenml/zen_server/dashboard/assets/{page-BxL4qD4_.js → page-CltCNL0T.js} +1 -1
  68. zenml/zen_server/dashboard/assets/{page-D4wdonLm.js → page-CmlYj7Nl.js} +1 -1
  69. zenml/zen_server/dashboard/assets/{page-DFuAUGt4.js → page-D6Ev5P8V.js} +1 -1
  70. zenml/zen_server/dashboard/assets/{page-u_-ZXBKb.js → page-D9Oh05fl.js} +1 -1
  71. zenml/zen_server/dashboard/assets/{page-DRYXdL5o.js → page-DGlm1RVc.js} +1 -1
  72. zenml/zen_server/dashboard/assets/{page-r8XK5vR7.js → page-DN4BVIOL.js} +1 -1
  73. zenml/zen_server/dashboard/assets/{page-DYEquBC2.js → page-Dif8CWyZ.js} +1 -1
  74. zenml/zen_server/dashboard/assets/{page-BdowiCbr.js → page-DlIi5ThM.js} +1 -1
  75. zenml/zen_server/dashboard/assets/{page-9Y9-gig0.js → page-DoW7YxTu.js} +1 -1
  76. zenml/zen_server/dashboard/assets/{page-BKZYc2Zv.js → page-Dth9X1Ih.js} +1 -1
  77. zenml/zen_server/dashboard/assets/{page-bT5pOvcB.js → page-DweqqCkF.js} +1 -1
  78. zenml/zen_server/dashboard/assets/{page-CXuQufSe.js → page-DyOJ_pq3.js} +1 -1
  79. zenml/zen_server/dashboard/assets/{page-DGazBpuP.js → page-Hn8q9iJZ.js} +1 -1
  80. zenml/zen_server/dashboard/assets/{page-hUqK889I.js → page-IhckKFnD.js} +1 -1
  81. zenml/zen_server/dashboard/assets/{page-BU9FG4sR.js → page-LyZ_l8vR.js} +1 -1
  82. zenml/zen_server/dashboard/assets/{page-Cldq1mpe.js → page-PamGpk0j.js} +1 -1
  83. zenml/zen_server/dashboard/assets/page-PxOWfKgF.js +2 -0
  84. zenml/zen_server/dashboard/assets/{persist-DAUi_3za.js → persist-DeXRG61d.js} +1 -1
  85. zenml/zen_server/dashboard/assets/{persist-AppN1B0J.js → persist-vP0-Xl4f.js} +1 -1
  86. zenml/zen_server/dashboard/assets/{service-BqqeXLEe.js → service-DH_oUqQj.js} +1 -1
  87. zenml/zen_server/dashboard/assets/{sharedSchema-uXN9FLLk.js → sharedSchema-Bw1_Wa7l.js} +1 -1
  88. zenml/zen_server/dashboard/assets/{stack-detail-query-XfZBiBP2.js → stack-detail-query-B_0R_fd6.js} +1 -1
  89. zenml/zen_server/dashboard/assets/{update-server-settings-mutation-BWmgVJwA.js → update-server-settings-mutation-D9qYhfaN.js} +1 -1
  90. zenml/zen_server/dashboard/assets/{url-BLwMbzES.js → url-Dh93fvh0.js} +1 -1
  91. zenml/zen_server/dashboard/index.html +3 -3
  92. zenml/zen_stores/sql_zen_store.py +7 -0
  93. {zenml_nightly-0.71.0.dev20250109.dist-info → zenml_nightly-0.71.0.dev20250110.dist-info}/METADATA +1 -1
  94. {zenml_nightly-0.71.0.dev20250109.dist-info → zenml_nightly-0.71.0.dev20250110.dist-info}/RECORD +97 -97
  95. zenml/zen_server/dashboard/assets/page-B6XU7yYT.js +0 -2
  96. zenml/zen_server/dashboard/assets/page-Bg8OjTRe.js +0 -1
  97. {zenml_nightly-0.71.0.dev20250109.dist-info → zenml_nightly-0.71.0.dev20250110.dist-info}/LICENSE +0 -0
  98. {zenml_nightly-0.71.0.dev20250109.dist-info → zenml_nightly-0.71.0.dev20250110.dist-info}/WHEEL +0 -0
  99. {zenml_nightly-0.71.0.dev20250109.dist-info → zenml_nightly-0.71.0.dev20250110.dist-info}/entry_points.txt +0 -0
zenml/VERSION CHANGED
@@ -1 +1 @@
1
- 0.71.0.dev20250109
1
+ 0.71.0.dev20250110
zenml/cli/base.py CHANGED
@@ -87,7 +87,7 @@ ZENML_PROJECT_TEMPLATES = dict(
87
87
  ),
88
88
  nlp=ZenMLProjectTemplateLocation(
89
89
  github_url="zenml-io/template-nlp",
90
- github_tag="2024.11.28", # Make sure it is aligned with .github/workflows/update-templates-to-examples.yml
90
+ github_tag="2025.01.08", # Make sure it is aligned with .github/workflows/update-templates-to-examples.yml
91
91
  ),
92
92
  llm_finetuning=ZenMLProjectTemplateLocation(
93
93
  github_url="zenml-io/template-llm-finetuning",
zenml/constants.py CHANGED
@@ -429,6 +429,7 @@ PAGE_SIZE_MAXIMUM: int = handle_int_env_var(
429
429
  )
430
430
  FILTERING_DATETIME_FORMAT: str = "%Y-%m-%d %H:%M:%S"
431
431
  SORT_PIPELINES_BY_LATEST_RUN_KEY = "latest_run"
432
+ SORT_BY_LATEST_VERSION_KEY = "latest_version"
432
433
 
433
434
  # Metadata constants
434
435
  METADATA_ORCHESTRATOR_URL = "orchestrator_url"
@@ -245,6 +245,8 @@ class UserScopedFilter(BaseFilter):
245
245
  UserSchema, getattr(table, "user_id") == UserSchema.id
246
246
  )
247
247
 
248
+ query = query.add_columns(UserSchema.name)
249
+
248
250
  if operand == SorterOps.ASCENDING:
249
251
  query = query.order_by(asc(column))
250
252
  else:
@@ -449,6 +451,8 @@ class WorkspaceScopedFilter(UserScopedFilter):
449
451
  getattr(table, "workspace_id") == WorkspaceSchema.id,
450
452
  )
451
453
 
454
+ query = query.add_columns(WorkspaceSchema.name)
455
+
452
456
  if operand == SorterOps.ASCENDING:
453
457
  query = query.order_by(asc(column))
454
458
  else:
@@ -470,10 +474,9 @@ class WorkspaceScopedTaggableFilter(WorkspaceScopedFilter):
470
474
  *WorkspaceScopedFilter.FILTER_EXCLUDE_FIELDS,
471
475
  "tag",
472
476
  ]
473
-
474
477
  CUSTOM_SORTING_OPTIONS: ClassVar[List[str]] = [
475
478
  *WorkspaceScopedFilter.CUSTOM_SORTING_OPTIONS,
476
- "tag",
479
+ "tags",
477
480
  ]
478
481
 
479
482
  def apply_filter(
@@ -540,8 +543,8 @@ class WorkspaceScopedTaggableFilter(WorkspaceScopedFilter):
540
543
  """
541
544
  sort_by, operand = self.sorting_params
542
545
 
543
- if sort_by == "tag":
544
- from sqlmodel import and_, asc, desc, func
546
+ if sort_by == "tags":
547
+ from sqlmodel import asc, desc, func, select
545
548
 
546
549
  from zenml.enums import SorterOps, TaggableResourceTypes
547
550
  from zenml.zen_stores.schemas import (
@@ -566,35 +569,36 @@ class WorkspaceScopedTaggableFilter(WorkspaceScopedFilter):
566
569
  RunTemplateSchema: TaggableResourceTypes.RUN_TEMPLATE,
567
570
  }
568
571
 
569
- query = (
570
- query.outerjoin(
571
- TagResourceSchema,
572
- and_(
573
- table.id == TagResourceSchema.resource_id,
574
- TagResourceSchema.resource_type
575
- == resource_type_mapping[table],
576
- ),
572
+ sorted_tags = (
573
+ select(TagResourceSchema.resource_id, TagSchema.name)
574
+ .join(TagSchema, TagResourceSchema.tag_id == TagSchema.id) # type: ignore[arg-type]
575
+ .filter(
576
+ TagResourceSchema.resource_type # type: ignore[arg-type]
577
+ == resource_type_mapping[table]
578
+ )
579
+ .order_by(
580
+ asc(TagResourceSchema.resource_id), asc(TagSchema.name)
577
581
  )
578
- .outerjoin(TagSchema, TagResourceSchema.tag_id == TagSchema.id)
579
- .group_by(table.id)
582
+ ).alias("sorted_tags")
583
+
584
+ tags_subquery = (
585
+ select(
586
+ sorted_tags.c.resource_id,
587
+ func.group_concat(sorted_tags.c.name, ", ").label(
588
+ "tags_list"
589
+ ),
590
+ ).group_by(sorted_tags.c.resource_id)
591
+ ).alias("tags_subquery")
592
+
593
+ query = query.add_columns(tags_subquery.c.tags_list).outerjoin(
594
+ tags_subquery, table.id == tags_subquery.c.resource_id
580
595
  )
581
596
 
597
+ # Apply ordering based on the tags list
582
598
  if operand == SorterOps.ASCENDING:
583
- query = query.order_by(
584
- asc(
585
- func.group_concat(TagSchema.name, ",").label(
586
- "tags_list"
587
- )
588
- )
589
- )
599
+ query = query.order_by(asc("tags_list"))
590
600
  else:
591
- query = query.order_by(
592
- desc(
593
- func.group_concat(TagSchema.name, ",").label(
594
- "tags_list"
595
- )
596
- )
597
- )
601
+ query = query.order_by(desc("tags_list"))
598
602
 
599
603
  return query
600
604
 
@@ -13,12 +13,21 @@
13
13
  # permissions and limitations under the License.
14
14
  """Models representing artifacts."""
15
15
 
16
- from typing import TYPE_CHECKING, Dict, List, Optional
16
+ from typing import (
17
+ TYPE_CHECKING,
18
+ Any,
19
+ ClassVar,
20
+ Dict,
21
+ List,
22
+ Optional,
23
+ Type,
24
+ TypeVar,
25
+ )
17
26
  from uuid import UUID
18
27
 
19
28
  from pydantic import BaseModel, Field
20
29
 
21
- from zenml.constants import STR_FIELD_MAX_LENGTH
30
+ from zenml.constants import SORT_BY_LATEST_VERSION_KEY, STR_FIELD_MAX_LENGTH
22
31
  from zenml.models.v2.base.base import (
23
32
  BaseDatedResponseBody,
24
33
  BaseIdentifiedResponse,
@@ -31,6 +40,11 @@ from zenml.models.v2.core.tag import TagResponse
31
40
 
32
41
  if TYPE_CHECKING:
33
42
  from zenml.models.v2.core.artifact_version import ArtifactVersionResponse
43
+ from zenml.zen_stores.schemas import BaseSchema
44
+
45
+ AnySchema = TypeVar("AnySchema", bound=BaseSchema)
46
+
47
+ AnyQuery = TypeVar("AnyQuery", bound=Any)
34
48
 
35
49
  # ------------------ Request Model ------------------
36
50
 
@@ -174,3 +188,73 @@ class ArtifactFilter(WorkspaceScopedTaggableFilter):
174
188
 
175
189
  name: Optional[str] = None
176
190
  has_custom_name: Optional[bool] = None
191
+
192
+ CUSTOM_SORTING_OPTIONS: ClassVar[List[str]] = [
193
+ *WorkspaceScopedTaggableFilter.CUSTOM_SORTING_OPTIONS,
194
+ SORT_BY_LATEST_VERSION_KEY,
195
+ ]
196
+
197
+ def apply_sorting(
198
+ self,
199
+ query: AnyQuery,
200
+ table: Type["AnySchema"],
201
+ ) -> AnyQuery:
202
+ """Apply sorting to the query for Artifacts.
203
+
204
+ Args:
205
+ query: The query to which to apply the sorting.
206
+ table: The query table.
207
+
208
+ Returns:
209
+ The query with sorting applied.
210
+ """
211
+ from sqlmodel import asc, case, col, desc, func, select
212
+
213
+ from zenml.enums import SorterOps
214
+ from zenml.zen_stores.schemas import (
215
+ ArtifactSchema,
216
+ ArtifactVersionSchema,
217
+ )
218
+
219
+ sort_by, operand = self.sorting_params
220
+
221
+ if sort_by == SORT_BY_LATEST_VERSION_KEY:
222
+ # Subquery to find the latest version per artifact
223
+ latest_version_subquery = (
224
+ select(
225
+ ArtifactSchema.id,
226
+ case(
227
+ (
228
+ func.max(ArtifactVersionSchema.created).is_(None),
229
+ ArtifactSchema.created,
230
+ ),
231
+ else_=func.max(ArtifactVersionSchema.created),
232
+ ).label("latest_version_created"),
233
+ )
234
+ .outerjoin(
235
+ ArtifactVersionSchema,
236
+ ArtifactSchema.id == ArtifactVersionSchema.artifact_id, # type: ignore[arg-type]
237
+ )
238
+ .group_by(col(ArtifactSchema.id))
239
+ .subquery()
240
+ )
241
+
242
+ query = query.add_columns(
243
+ latest_version_subquery.c.latest_version_created,
244
+ ).where(ArtifactSchema.id == latest_version_subquery.c.id)
245
+
246
+ # Apply sorting based on the operand
247
+ if operand == SorterOps.ASCENDING:
248
+ query = query.order_by(
249
+ asc(latest_version_subquery.c.latest_version_created),
250
+ asc(ArtifactSchema.id),
251
+ )
252
+ else:
253
+ query = query.order_by(
254
+ desc(latest_version_subquery.c.latest_version_created),
255
+ desc(ArtifactSchema.id),
256
+ )
257
+ return query
258
+
259
+ # For other sorting cases, delegate to the parent class
260
+ return super().apply_sorting(query=query, table=table)
@@ -13,12 +13,16 @@
13
13
  # permissions and limitations under the License.
14
14
  """Models representing models."""
15
15
 
16
- from typing import TYPE_CHECKING, List, Optional
16
+ from typing import TYPE_CHECKING, Any, ClassVar, List, Optional, Type, TypeVar
17
17
  from uuid import UUID
18
18
 
19
19
  from pydantic import BaseModel, Field
20
20
 
21
- from zenml.constants import STR_FIELD_MAX_LENGTH, TEXT_FIELD_MAX_LENGTH
21
+ from zenml.constants import (
22
+ SORT_BY_LATEST_VERSION_KEY,
23
+ STR_FIELD_MAX_LENGTH,
24
+ TEXT_FIELD_MAX_LENGTH,
25
+ )
22
26
  from zenml.models.v2.base.scoped import (
23
27
  WorkspaceScopedRequest,
24
28
  WorkspaceScopedResponse,
@@ -32,6 +36,11 @@ from zenml.utils.pagination_utils import depaginate
32
36
  if TYPE_CHECKING:
33
37
  from zenml.model.model import Model
34
38
  from zenml.models.v2.core.tag import TagResponse
39
+ from zenml.zen_stores.schemas import BaseSchema
40
+
41
+ AnySchema = TypeVar("AnySchema", bound=BaseSchema)
42
+
43
+ AnyQuery = TypeVar("AnyQuery", bound=Any)
35
44
 
36
45
  # ------------------ Request Model ------------------
37
46
 
@@ -320,3 +329,73 @@ class ModelFilter(WorkspaceScopedTaggableFilter):
320
329
  default=None,
321
330
  description="Name of the Model",
322
331
  )
332
+
333
+ CUSTOM_SORTING_OPTIONS: ClassVar[List[str]] = [
334
+ *WorkspaceScopedTaggableFilter.CUSTOM_SORTING_OPTIONS,
335
+ SORT_BY_LATEST_VERSION_KEY,
336
+ ]
337
+
338
+ def apply_sorting(
339
+ self,
340
+ query: AnyQuery,
341
+ table: Type["AnySchema"],
342
+ ) -> AnyQuery:
343
+ """Apply sorting to the query for Models.
344
+
345
+ Args:
346
+ query: The query to which to apply the sorting.
347
+ table: The query table.
348
+
349
+ Returns:
350
+ The query with sorting applied.
351
+ """
352
+ from sqlmodel import asc, case, col, desc, func, select
353
+
354
+ from zenml.enums import SorterOps
355
+ from zenml.zen_stores.schemas import (
356
+ ModelSchema,
357
+ ModelVersionSchema,
358
+ )
359
+
360
+ sort_by, operand = self.sorting_params
361
+
362
+ if sort_by == SORT_BY_LATEST_VERSION_KEY:
363
+ # Subquery to find the latest version per model
364
+ latest_version_subquery = (
365
+ select(
366
+ ModelSchema.id,
367
+ case(
368
+ (
369
+ func.max(ModelVersionSchema.created).is_(None),
370
+ ModelSchema.created,
371
+ ),
372
+ else_=func.max(ModelVersionSchema.created),
373
+ ).label("latest_version_created"),
374
+ )
375
+ .outerjoin(
376
+ ModelVersionSchema,
377
+ ModelSchema.id == ModelVersionSchema.model_id, # type: ignore[arg-type]
378
+ )
379
+ .group_by(col(ModelSchema.id))
380
+ .subquery()
381
+ )
382
+
383
+ query = query.add_columns(
384
+ latest_version_subquery.c.latest_version_created,
385
+ ).where(ModelSchema.id == latest_version_subquery.c.id)
386
+
387
+ # Apply sorting based on the operand
388
+ if operand == SorterOps.ASCENDING:
389
+ query = query.order_by(
390
+ asc(latest_version_subquery.c.latest_version_created),
391
+ asc(ModelSchema.id),
392
+ )
393
+ else:
394
+ query = query.order_by(
395
+ desc(latest_version_subquery.c.latest_version_created),
396
+ desc(ModelSchema.id),
397
+ )
398
+ return query
399
+
400
+ # For other sorting cases, delegate to the parent class
401
+ return super().apply_sorting(query=query, table=table)
@@ -357,7 +357,7 @@ class PipelineFilter(WorkspaceScopedTaggableFilter):
357
357
  # Subquery to find the latest run per pipeline
358
358
  latest_run_subquery = (
359
359
  select(
360
- PipelineRunSchema.pipeline_id,
360
+ PipelineSchema.id,
361
361
  case(
362
362
  (
363
363
  func.max(PipelineRunSchema.created).is_(None),
@@ -366,25 +366,28 @@ class PipelineFilter(WorkspaceScopedTaggableFilter):
366
366
  else_=func.max(PipelineRunSchema.created),
367
367
  ).label("latest_run"),
368
368
  )
369
- .group_by(col(PipelineRunSchema.pipeline_id))
369
+ .outerjoin(
370
+ PipelineRunSchema,
371
+ PipelineSchema.id == PipelineRunSchema.pipeline_id, # type: ignore[arg-type]
372
+ )
373
+ .group_by(col(PipelineSchema.id))
370
374
  .subquery()
371
375
  )
372
376
 
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
- )
377
+ query = query.add_columns(
378
+ latest_run_subquery.c.latest_run,
379
+ ).where(PipelineSchema.id == latest_run_subquery.c.id)
378
380
 
379
381
  if operand == SorterOps.ASCENDING:
380
382
  query = query.order_by(
381
- asc(latest_run_subquery.c.latest_run)
382
- ).order_by(col(PipelineSchema.id))
383
+ asc(latest_run_subquery.c.latest_run),
384
+ asc(PipelineSchema.id),
385
+ )
383
386
  else:
384
387
  query = query.order_by(
385
- desc(latest_run_subquery.c.latest_run)
386
- ).order_by(col(PipelineSchema.id))
387
-
388
+ desc(latest_run_subquery.c.latest_run),
389
+ desc(PipelineSchema.id),
390
+ )
388
391
  return query
389
392
  else:
390
393
  return super().apply_sorting(query=query, table=table)
@@ -982,6 +982,8 @@ class PipelineRunFilter(WorkspaceScopedTaggableFilter):
982
982
  else:
983
983
  return super().apply_sorting(query=query, table=table)
984
984
 
985
+ query = query.add_columns(column)
986
+
985
987
  if operand == SorterOps.ASCENDING:
986
988
  query = query.order_by(asc(column))
987
989
  else:
@@ -1 +1 @@
1
- import{j as e}from"./@radix-DeK6qiuw.js";import{f as s,r as t}from"./index-FO-p0GU7.js";import{E as r}from"./EmptyState-BzdlCwp3.js";import{S as a}from"./help-Cc9bBIJH.js";import{L as o}from"./@react-router-B3Z5rLr2.js";import"./@tanstack-DT5WLu9C.js";import"./@reactflow-D2Y7BWwz.js";function d(){return e.jsx("div",{className:"flex min-h-screen w-full flex-col",children:e.jsx(r,{icon:e.jsx(a,{className:"h-[120px] w-[120px] fill-neutral-300"}),children:e.jsxs("div",{className:"text-center",children:[e.jsx("h1",{className:"mb-2 text-display-xs font-semibold",children:"We can't find the page you are looking for"}),e.jsx("p",{className:"text-lg text-theme-text-secondary",children:"You can try typing a different URL or we can bring you back to your Homepage."}),e.jsx("div",{className:"mt-5 flex justify-center",children:e.jsx(s,{size:"md",asChild:!0,children:e.jsx(o,{className:"w-min self-center whitespace-nowrap",to:t.home,children:e.jsx("span",{className:"px-0.5",children:"Go to Home"})})})})]})})})}export{d as default};
1
+ import{j as e}from"./@radix-DeK6qiuw.js";import{f as s,r as t}from"./index-CE0aQlv8.js";import{E as r}from"./EmptyState-BzdlCwp3.js";import{S as a}from"./help-Cc9bBIJH.js";import{L as o}from"./@react-router-B3Z5rLr2.js";import"./@tanstack-DT5WLu9C.js";import"./@reactflow-BUNIMFeC.js";function d(){return e.jsx("div",{className:"flex min-h-screen w-full flex-col",children:e.jsx(r,{icon:e.jsx(a,{className:"h-[120px] w-[120px] fill-neutral-300"}),children:e.jsxs("div",{className:"text-center",children:[e.jsx("h1",{className:"mb-2 text-display-xs font-semibold",children:"We can't find the page you are looking for"}),e.jsx("p",{className:"text-lg text-theme-text-secondary",children:"You can try typing a different URL or we can bring you back to your Homepage."}),e.jsx("div",{className:"mt-5 flex justify-center",children:e.jsx(s,{size:"md",asChild:!0,children:e.jsx(o,{className:"w-min self-center whitespace-nowrap",to:t.home,children:e.jsx("span",{className:"px-0.5",children:"Go to Home"})})})})]})})})}export{d as default};