mlrun 1.7.2rc3__py3-none-any.whl → 1.8.0rc2__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.

Potentially problematic release.


This version of mlrun might be problematic. Click here for more details.

Files changed (250) hide show
  1. mlrun/__init__.py +18 -18
  2. mlrun/__main__.py +3 -3
  3. mlrun/alerts/alert.py +19 -12
  4. mlrun/artifacts/__init__.py +0 -2
  5. mlrun/artifacts/base.py +34 -11
  6. mlrun/artifacts/dataset.py +16 -16
  7. mlrun/artifacts/manager.py +13 -13
  8. mlrun/artifacts/model.py +66 -53
  9. mlrun/common/constants.py +6 -0
  10. mlrun/common/formatters/__init__.py +1 -0
  11. mlrun/common/formatters/feature_set.py +1 -0
  12. mlrun/common/formatters/function.py +1 -0
  13. mlrun/common/formatters/model_endpoint.py +30 -0
  14. mlrun/common/formatters/pipeline.py +1 -2
  15. mlrun/common/formatters/project.py +9 -0
  16. mlrun/common/model_monitoring/__init__.py +0 -3
  17. mlrun/common/model_monitoring/helpers.py +1 -1
  18. mlrun/common/runtimes/constants.py +1 -2
  19. mlrun/common/schemas/__init__.py +7 -2
  20. mlrun/common/schemas/alert.py +31 -18
  21. mlrun/common/schemas/api_gateway.py +3 -3
  22. mlrun/common/schemas/artifact.py +7 -13
  23. mlrun/common/schemas/auth.py +6 -4
  24. mlrun/common/schemas/background_task.py +7 -7
  25. mlrun/common/schemas/client_spec.py +2 -2
  26. mlrun/common/schemas/clusterization_spec.py +2 -2
  27. mlrun/common/schemas/common.py +53 -3
  28. mlrun/common/schemas/datastore_profile.py +1 -1
  29. mlrun/common/schemas/feature_store.py +9 -9
  30. mlrun/common/schemas/frontend_spec.py +4 -4
  31. mlrun/common/schemas/function.py +10 -10
  32. mlrun/common/schemas/hub.py +1 -1
  33. mlrun/common/schemas/k8s.py +3 -3
  34. mlrun/common/schemas/memory_reports.py +3 -3
  35. mlrun/common/schemas/model_monitoring/__init__.py +8 -1
  36. mlrun/common/schemas/model_monitoring/constants.py +62 -12
  37. mlrun/common/schemas/model_monitoring/grafana.py +1 -1
  38. mlrun/common/schemas/model_monitoring/model_endpoint_v2.py +149 -0
  39. mlrun/common/schemas/model_monitoring/model_endpoints.py +22 -6
  40. mlrun/common/schemas/notification.py +18 -3
  41. mlrun/common/schemas/object.py +1 -1
  42. mlrun/common/schemas/pagination.py +4 -4
  43. mlrun/common/schemas/partition.py +137 -0
  44. mlrun/common/schemas/pipeline.py +2 -2
  45. mlrun/common/schemas/project.py +22 -17
  46. mlrun/common/schemas/runs.py +2 -2
  47. mlrun/common/schemas/runtime_resource.py +5 -5
  48. mlrun/common/schemas/schedule.py +1 -1
  49. mlrun/common/schemas/secret.py +1 -1
  50. mlrun/common/schemas/tag.py +3 -3
  51. mlrun/common/schemas/workflow.py +5 -5
  52. mlrun/config.py +65 -15
  53. mlrun/data_types/__init__.py +0 -2
  54. mlrun/data_types/data_types.py +0 -1
  55. mlrun/data_types/infer.py +3 -1
  56. mlrun/data_types/spark.py +4 -4
  57. mlrun/data_types/to_pandas.py +2 -11
  58. mlrun/datastore/__init__.py +0 -2
  59. mlrun/datastore/alibaba_oss.py +4 -1
  60. mlrun/datastore/azure_blob.py +4 -1
  61. mlrun/datastore/base.py +12 -4
  62. mlrun/datastore/datastore.py +9 -3
  63. mlrun/datastore/datastore_profile.py +20 -20
  64. mlrun/datastore/dbfs_store.py +4 -1
  65. mlrun/datastore/filestore.py +4 -1
  66. mlrun/datastore/google_cloud_storage.py +4 -1
  67. mlrun/datastore/hdfs.py +4 -1
  68. mlrun/datastore/inmem.py +4 -1
  69. mlrun/datastore/redis.py +4 -1
  70. mlrun/datastore/s3.py +4 -1
  71. mlrun/datastore/sources.py +51 -49
  72. mlrun/datastore/store_resources.py +0 -2
  73. mlrun/datastore/targets.py +22 -23
  74. mlrun/datastore/utils.py +2 -2
  75. mlrun/datastore/v3io.py +4 -1
  76. mlrun/datastore/wasbfs/fs.py +13 -12
  77. mlrun/db/base.py +170 -64
  78. mlrun/db/factory.py +3 -0
  79. mlrun/db/httpdb.py +986 -238
  80. mlrun/db/nopdb.py +155 -57
  81. mlrun/errors.py +2 -2
  82. mlrun/execution.py +55 -29
  83. mlrun/feature_store/__init__.py +0 -2
  84. mlrun/feature_store/api.py +40 -40
  85. mlrun/feature_store/common.py +9 -9
  86. mlrun/feature_store/feature_set.py +20 -18
  87. mlrun/feature_store/feature_vector.py +27 -24
  88. mlrun/feature_store/retrieval/base.py +14 -9
  89. mlrun/feature_store/retrieval/job.py +2 -1
  90. mlrun/feature_store/steps.py +2 -2
  91. mlrun/features.py +30 -13
  92. mlrun/frameworks/__init__.py +1 -2
  93. mlrun/frameworks/_common/__init__.py +1 -2
  94. mlrun/frameworks/_common/artifacts_library.py +2 -2
  95. mlrun/frameworks/_common/mlrun_interface.py +10 -6
  96. mlrun/frameworks/_common/model_handler.py +29 -27
  97. mlrun/frameworks/_common/producer.py +3 -1
  98. mlrun/frameworks/_dl_common/__init__.py +1 -2
  99. mlrun/frameworks/_dl_common/loggers/__init__.py +1 -2
  100. mlrun/frameworks/_dl_common/loggers/mlrun_logger.py +4 -4
  101. mlrun/frameworks/_dl_common/loggers/tensorboard_logger.py +3 -3
  102. mlrun/frameworks/_ml_common/__init__.py +1 -2
  103. mlrun/frameworks/_ml_common/loggers/__init__.py +1 -2
  104. mlrun/frameworks/_ml_common/model_handler.py +21 -21
  105. mlrun/frameworks/_ml_common/plans/__init__.py +1 -2
  106. mlrun/frameworks/_ml_common/plans/confusion_matrix_plan.py +3 -1
  107. mlrun/frameworks/_ml_common/plans/dataset_plan.py +3 -3
  108. mlrun/frameworks/_ml_common/plans/roc_curve_plan.py +4 -4
  109. mlrun/frameworks/auto_mlrun/__init__.py +1 -2
  110. mlrun/frameworks/auto_mlrun/auto_mlrun.py +22 -15
  111. mlrun/frameworks/huggingface/__init__.py +1 -2
  112. mlrun/frameworks/huggingface/model_server.py +9 -9
  113. mlrun/frameworks/lgbm/__init__.py +47 -44
  114. mlrun/frameworks/lgbm/callbacks/__init__.py +1 -2
  115. mlrun/frameworks/lgbm/callbacks/logging_callback.py +4 -2
  116. mlrun/frameworks/lgbm/callbacks/mlrun_logging_callback.py +4 -2
  117. mlrun/frameworks/lgbm/mlrun_interfaces/__init__.py +1 -2
  118. mlrun/frameworks/lgbm/mlrun_interfaces/mlrun_interface.py +5 -5
  119. mlrun/frameworks/lgbm/model_handler.py +15 -11
  120. mlrun/frameworks/lgbm/model_server.py +11 -7
  121. mlrun/frameworks/lgbm/utils.py +2 -2
  122. mlrun/frameworks/onnx/__init__.py +1 -2
  123. mlrun/frameworks/onnx/dataset.py +3 -3
  124. mlrun/frameworks/onnx/mlrun_interface.py +2 -2
  125. mlrun/frameworks/onnx/model_handler.py +7 -5
  126. mlrun/frameworks/onnx/model_server.py +8 -6
  127. mlrun/frameworks/parallel_coordinates.py +11 -11
  128. mlrun/frameworks/pytorch/__init__.py +22 -23
  129. mlrun/frameworks/pytorch/callbacks/__init__.py +1 -2
  130. mlrun/frameworks/pytorch/callbacks/callback.py +2 -1
  131. mlrun/frameworks/pytorch/callbacks/logging_callback.py +15 -8
  132. mlrun/frameworks/pytorch/callbacks/mlrun_logging_callback.py +19 -12
  133. mlrun/frameworks/pytorch/callbacks/tensorboard_logging_callback.py +22 -15
  134. mlrun/frameworks/pytorch/callbacks_handler.py +36 -30
  135. mlrun/frameworks/pytorch/mlrun_interface.py +17 -17
  136. mlrun/frameworks/pytorch/model_handler.py +21 -17
  137. mlrun/frameworks/pytorch/model_server.py +13 -9
  138. mlrun/frameworks/sklearn/__init__.py +19 -18
  139. mlrun/frameworks/sklearn/estimator.py +2 -2
  140. mlrun/frameworks/sklearn/metric.py +3 -3
  141. mlrun/frameworks/sklearn/metrics_library.py +8 -6
  142. mlrun/frameworks/sklearn/mlrun_interface.py +3 -2
  143. mlrun/frameworks/sklearn/model_handler.py +4 -3
  144. mlrun/frameworks/tf_keras/__init__.py +11 -12
  145. mlrun/frameworks/tf_keras/callbacks/__init__.py +1 -2
  146. mlrun/frameworks/tf_keras/callbacks/logging_callback.py +17 -14
  147. mlrun/frameworks/tf_keras/callbacks/mlrun_logging_callback.py +15 -12
  148. mlrun/frameworks/tf_keras/callbacks/tensorboard_logging_callback.py +21 -18
  149. mlrun/frameworks/tf_keras/model_handler.py +17 -13
  150. mlrun/frameworks/tf_keras/model_server.py +12 -8
  151. mlrun/frameworks/xgboost/__init__.py +19 -18
  152. mlrun/frameworks/xgboost/model_handler.py +13 -9
  153. mlrun/launcher/base.py +3 -4
  154. mlrun/launcher/local.py +1 -1
  155. mlrun/launcher/remote.py +1 -1
  156. mlrun/lists.py +4 -3
  157. mlrun/model.py +110 -46
  158. mlrun/model_monitoring/__init__.py +1 -2
  159. mlrun/model_monitoring/api.py +6 -6
  160. mlrun/model_monitoring/applications/_application_steps.py +13 -15
  161. mlrun/model_monitoring/applications/histogram_data_drift.py +41 -15
  162. mlrun/model_monitoring/applications/results.py +55 -3
  163. mlrun/model_monitoring/controller.py +185 -223
  164. mlrun/model_monitoring/db/_schedules.py +156 -0
  165. mlrun/model_monitoring/db/_stats.py +189 -0
  166. mlrun/model_monitoring/db/stores/__init__.py +1 -1
  167. mlrun/model_monitoring/db/stores/base/store.py +6 -65
  168. mlrun/model_monitoring/db/stores/sqldb/models/__init__.py +0 -25
  169. mlrun/model_monitoring/db/stores/sqldb/models/base.py +0 -97
  170. mlrun/model_monitoring/db/stores/sqldb/models/mysql.py +2 -58
  171. mlrun/model_monitoring/db/stores/sqldb/models/sqlite.py +0 -15
  172. mlrun/model_monitoring/db/stores/sqldb/sql_store.py +6 -257
  173. mlrun/model_monitoring/db/stores/v3io_kv/kv_store.py +9 -271
  174. mlrun/model_monitoring/db/tsdb/base.py +76 -24
  175. mlrun/model_monitoring/db/tsdb/tdengine/schemas.py +61 -6
  176. mlrun/model_monitoring/db/tsdb/tdengine/stream_graph_steps.py +33 -0
  177. mlrun/model_monitoring/db/tsdb/tdengine/tdengine_connector.py +253 -28
  178. mlrun/model_monitoring/db/tsdb/v3io/stream_graph_steps.py +1 -0
  179. mlrun/model_monitoring/db/tsdb/v3io/v3io_connector.py +35 -17
  180. mlrun/model_monitoring/helpers.py +91 -1
  181. mlrun/model_monitoring/model_endpoint.py +4 -2
  182. mlrun/model_monitoring/stream_processing.py +16 -13
  183. mlrun/model_monitoring/tracking_policy.py +10 -3
  184. mlrun/model_monitoring/writer.py +47 -26
  185. mlrun/package/__init__.py +3 -6
  186. mlrun/package/context_handler.py +1 -1
  187. mlrun/package/packager.py +12 -9
  188. mlrun/package/packagers/__init__.py +0 -2
  189. mlrun/package/packagers/default_packager.py +14 -11
  190. mlrun/package/packagers/numpy_packagers.py +16 -7
  191. mlrun/package/packagers/pandas_packagers.py +18 -18
  192. mlrun/package/packagers/python_standard_library_packagers.py +25 -11
  193. mlrun/package/packagers_manager.py +31 -14
  194. mlrun/package/utils/__init__.py +0 -3
  195. mlrun/package/utils/_pickler.py +6 -6
  196. mlrun/platforms/__init__.py +3 -16
  197. mlrun/platforms/iguazio.py +4 -1
  198. mlrun/projects/operations.py +27 -27
  199. mlrun/projects/pipelines.py +34 -35
  200. mlrun/projects/project.py +535 -182
  201. mlrun/run.py +13 -10
  202. mlrun/runtimes/__init__.py +1 -3
  203. mlrun/runtimes/base.py +15 -11
  204. mlrun/runtimes/daskjob.py +9 -9
  205. mlrun/runtimes/generators.py +2 -1
  206. mlrun/runtimes/kubejob.py +4 -5
  207. mlrun/runtimes/mounts.py +572 -0
  208. mlrun/runtimes/mpijob/__init__.py +0 -2
  209. mlrun/runtimes/mpijob/abstract.py +7 -6
  210. mlrun/runtimes/nuclio/api_gateway.py +7 -7
  211. mlrun/runtimes/nuclio/application/application.py +11 -11
  212. mlrun/runtimes/nuclio/function.py +13 -13
  213. mlrun/runtimes/nuclio/serving.py +9 -9
  214. mlrun/runtimes/pod.py +154 -45
  215. mlrun/runtimes/remotesparkjob.py +3 -2
  216. mlrun/runtimes/sparkjob/__init__.py +0 -2
  217. mlrun/runtimes/sparkjob/spark3job.py +21 -11
  218. mlrun/runtimes/utils.py +6 -5
  219. mlrun/serving/merger.py +6 -4
  220. mlrun/serving/remote.py +18 -17
  221. mlrun/serving/routers.py +27 -27
  222. mlrun/serving/server.py +1 -1
  223. mlrun/serving/states.py +76 -71
  224. mlrun/serving/utils.py +13 -2
  225. mlrun/serving/v1_serving.py +3 -2
  226. mlrun/serving/v2_serving.py +4 -4
  227. mlrun/track/__init__.py +1 -1
  228. mlrun/track/tracker.py +2 -2
  229. mlrun/track/trackers/mlflow_tracker.py +6 -5
  230. mlrun/utils/async_http.py +1 -1
  231. mlrun/utils/helpers.py +70 -16
  232. mlrun/utils/logger.py +106 -4
  233. mlrun/utils/notifications/notification/__init__.py +22 -19
  234. mlrun/utils/notifications/notification/base.py +33 -14
  235. mlrun/utils/notifications/notification/console.py +6 -6
  236. mlrun/utils/notifications/notification/git.py +11 -11
  237. mlrun/utils/notifications/notification/ipython.py +10 -9
  238. mlrun/utils/notifications/notification/mail.py +149 -0
  239. mlrun/utils/notifications/notification/slack.py +6 -6
  240. mlrun/utils/notifications/notification/webhook.py +18 -22
  241. mlrun/utils/notifications/notification_pusher.py +43 -31
  242. mlrun/utils/regex.py +3 -1
  243. mlrun/utils/version/version.json +2 -2
  244. {mlrun-1.7.2rc3.dist-info → mlrun-1.8.0rc2.dist-info}/METADATA +18 -14
  245. mlrun-1.8.0rc2.dist-info/RECORD +358 -0
  246. {mlrun-1.7.2rc3.dist-info → mlrun-1.8.0rc2.dist-info}/WHEEL +1 -1
  247. mlrun-1.7.2rc3.dist-info/RECORD +0 -351
  248. {mlrun-1.7.2rc3.dist-info → mlrun-1.8.0rc2.dist-info}/LICENSE +0 -0
  249. {mlrun-1.7.2rc3.dist-info → mlrun-1.8.0rc2.dist-info}/entry_points.txt +0 -0
  250. {mlrun-1.7.2rc3.dist-info → mlrun-1.8.0rc2.dist-info}/top_level.txt +0 -0
mlrun/db/httpdb.py CHANGED
@@ -22,17 +22,20 @@ import warnings
22
22
  from copy import deepcopy
23
23
  from datetime import datetime, timedelta
24
24
  from os import path, remove
25
- from typing import Optional, Union
25
+ from typing import Literal, Optional, Union
26
26
  from urllib.parse import urlparse
27
27
 
28
+ import pydantic.v1
28
29
  import requests
29
30
  import semver
30
- from mlrun_pipelines.utils import compile_pipeline
31
+ from pydantic import parse_obj_as
31
32
 
32
33
  import mlrun
34
+ import mlrun.common.constants
33
35
  import mlrun.common.formatters
34
36
  import mlrun.common.runtimes
35
37
  import mlrun.common.schemas
38
+ import mlrun.common.schemas.model_monitoring.model_endpoints as mm_endpoints
36
39
  import mlrun.common.types
37
40
  import mlrun.model_monitoring.model_endpoint
38
41
  import mlrun.platforms
@@ -43,6 +46,7 @@ import mlrun.utils
43
46
  from mlrun.alerts.alert import AlertConfig
44
47
  from mlrun.db.auth_utils import OAuthClientIDTokenProvider, StaticTokenProvider
45
48
  from mlrun.errors import MLRunInvalidArgumentError, err_to_str
49
+ from mlrun_pipelines.utils import compile_pipeline
46
50
 
47
51
  from ..artifacts import Artifact
48
52
  from ..config import config
@@ -169,7 +173,7 @@ class HTTPRunDB(RunDBInterface):
169
173
  return f"{cls}({self.base_url!r})"
170
174
 
171
175
  @staticmethod
172
- def get_api_path_prefix(version: str = None) -> str:
176
+ def get_api_path_prefix(version: Optional[str] = None) -> str:
173
177
  """
174
178
  :param version: API version to use, None (the default) will mean to use the default value from mlrun.config,
175
179
  for un-versioned api set an empty string.
@@ -182,7 +186,7 @@ class HTTPRunDB(RunDBInterface):
182
186
  )
183
187
  return api_version_path
184
188
 
185
- def get_base_api_url(self, path: str, version: str = None) -> str:
189
+ def get_base_api_url(self, path: str, version: Optional[str] = None) -> str:
186
190
  path_prefix = self.get_api_path_prefix(version)
187
191
  url = f"{self.base_url}/{path_prefix}/{path}"
188
192
  return url
@@ -310,9 +314,26 @@ class HTTPRunDB(RunDBInterface):
310
314
  headers=None,
311
315
  timeout=45,
312
316
  version=None,
317
+ return_all=False,
313
318
  ) -> typing.Generator[requests.Response, None, None]:
314
319
  """
315
- Calls the api with pagination, yielding each page of the response
320
+ Calls the API with pagination and yields each page of the response.
321
+
322
+ Depending on the `return_all` parameter:
323
+ - If `return_all` is `True`, fetches and yields all pages of results.
324
+ - If `return_all` is False, only a single page of results is fetched and yielded.
325
+
326
+ :param method: The HTTP method (GET, POST, etc.).
327
+ :param path: The API endpoint path.
328
+ :param error: Error message used for debugging if the request fails.
329
+ :param params: The parameters to pass for the API request, including filters.
330
+ :param body: The body of the request.
331
+ :param json: The JSON payload for the request.
332
+ :param headers: Custom headers for the request.
333
+ :param timeout: Timeout for the request.
334
+ :param version: API version, optional.
335
+ :param return_all: If `True`, fetches all pages and returns them in one shot. If `False`, returns only
336
+ the requested page or the next page.
316
337
  """
317
338
 
318
339
  def _api_call(_params):
@@ -328,38 +349,50 @@ class HTTPRunDB(RunDBInterface):
328
349
  version=version,
329
350
  )
330
351
 
331
- first_page_params = deepcopy(params) or {}
332
- first_page_params["page"] = 1
333
- first_page_params["page-size"] = config.httpdb.pagination.default_page_size
334
- response = _api_call(first_page_params)
335
- page_token = response.json().get("pagination", {}).get("page-token")
336
- if not page_token:
337
- yield response
338
- return
352
+ page_params = deepcopy(params) or {}
353
+
354
+ if page_params.get("page-token") is None and page_params.get("page") is None:
355
+ page_params["page"] = 1
356
+
357
+ if page_params.get("page-size") is None:
358
+ page_params["page-size"] = config.httpdb.pagination.default_page_size
359
+
360
+ response = _api_call(page_params)
339
361
 
340
- params_with_page_token = deepcopy(params) or {}
341
- params_with_page_token["page-token"] = page_token
342
- while page_token:
343
- yield response
344
- try:
345
- response = _api_call(params_with_page_token)
346
- except mlrun.errors.MLRunNotFoundError:
347
- # pagination token expired
348
- break
362
+ # Yield only a single page of results
363
+ yield response
349
364
 
365
+ if return_all:
350
366
  page_token = response.json().get("pagination", {}).get("page-token", None)
351
367
 
368
+ while page_token:
369
+ try:
370
+ # Use the page token to get the next page.
371
+ # No need to supply any other parameters as the token informs the pagination cache
372
+ # which parameters to use.
373
+ response = _api_call({"page-token": page_token})
374
+ except mlrun.errors.MLRunNotFoundError:
375
+ # pagination token expired, we've reached the last page
376
+ break
377
+
378
+ yield response
379
+ page_token = (
380
+ response.json().get("pagination", {}).get("page-token", None)
381
+ )
382
+
352
383
  @staticmethod
353
384
  def process_paginated_responses(
354
385
  responses: typing.Generator[requests.Response, None, None], key: str = "data"
355
- ) -> list[typing.Any]:
386
+ ) -> tuple[list[typing.Any], Optional[str]]:
356
387
  """
357
388
  Processes the paginated responses and returns the combined data
358
389
  """
359
390
  data = []
391
+ page_token = None
360
392
  for response in responses:
393
+ page_token = response.json().get("pagination", {}).get("page-token", None)
361
394
  data.extend(response.json().get(key, []))
362
- return data
395
+ return data, page_token
363
396
 
364
397
  def _init_session(self, retry_on_post: bool = False):
365
398
  return mlrun.utils.HTTPSessionWithRetry(
@@ -768,7 +801,7 @@ class HTTPRunDB(RunDBInterface):
768
801
  name: Optional[str] = None,
769
802
  uid: Optional[Union[str, list[str]]] = None,
770
803
  project: Optional[str] = None,
771
- labels: Optional[Union[str, list[str]]] = None,
804
+ labels: Optional[Union[str, dict[str, Optional[str]], list[str]]] = None,
772
805
  state: Optional[
773
806
  mlrun.common.runtimes.constants.RunStates
774
807
  ] = None, # Backward compatibility
@@ -807,9 +840,13 @@ class HTTPRunDB(RunDBInterface):
807
840
  :param name: Name of the run to retrieve.
808
841
  :param uid: Unique ID of the run, or a list of run UIDs.
809
842
  :param project: Project that the runs belongs to.
810
- :param labels: A list of labels to filter by. Label filters work by either filtering a specific value
811
- of a label (i.e. list("key=value")) or by looking for the existence of a given
812
- key (i.e. "key").
843
+ :param labels: Filter runs by label key-value pairs or key existence. This can be provided as:
844
+ - A dictionary in the format `{"label": "value"}` to match specific label key-value pairs,
845
+ or `{"label": None}` to check for key existence.
846
+ - A list of strings formatted as `"label=value"` to match specific label key-value pairs,
847
+ or just `"label"` for key existence.
848
+ - A comma-separated string formatted as `"label1=value1,label2"` to match entities with
849
+ the specified key-value pairs or key existence.
813
850
  :param state: Deprecated - List only runs whose state is specified (will be removed in 1.9.0)
814
851
  :param states: List only runs whose state is one of the provided states.
815
852
  :param sort: Whether to sort the result according to their start time. Otherwise, results will be
@@ -832,81 +869,95 @@ class HTTPRunDB(RunDBInterface):
832
869
  limit.
833
870
  :param with_notifications: Return runs with notifications, and join them to the response. Default is `False`.
834
871
  """
872
+ runs, _ = self._list_runs(
873
+ name=name,
874
+ uid=uid,
875
+ project=project,
876
+ labels=labels,
877
+ state=state,
878
+ states=states,
879
+ sort=sort,
880
+ last=last,
881
+ iter=iter,
882
+ start_time_from=start_time_from,
883
+ start_time_to=start_time_to,
884
+ last_update_time_from=last_update_time_from,
885
+ last_update_time_to=last_update_time_to,
886
+ partition_by=partition_by,
887
+ rows_per_partition=rows_per_partition,
888
+ partition_sort_by=partition_sort_by,
889
+ partition_order=partition_order,
890
+ max_partitions=max_partitions,
891
+ with_notifications=with_notifications,
892
+ return_all=True,
893
+ )
894
+ return runs
835
895
 
836
- project = project or config.default_project
837
- if with_notifications:
838
- logger.warning(
839
- "Local run notifications are not persisted in the DB, therefore local runs will not be returned when "
840
- "using the `with_notifications` flag."
841
- )
842
-
843
- if last:
844
- # TODO: Remove this in 1.8.0
845
- warnings.warn(
846
- "'last' is deprecated and will be removed in 1.8.0.",
847
- FutureWarning,
848
- )
896
+ def paginated_list_runs(
897
+ self,
898
+ *args,
899
+ page: Optional[int] = None,
900
+ page_size: Optional[int] = None,
901
+ page_token: Optional[str] = None,
902
+ **kwargs,
903
+ ) -> tuple[RunList, Optional[str]]:
904
+ """List runs with support for pagination and various filtering options.
849
905
 
850
- if state:
851
- # TODO: Remove this in 1.9.0
852
- warnings.warn(
853
- "'state' is deprecated and will be removed in 1.9.0. Use 'states' instead.",
854
- FutureWarning,
855
- )
906
+ This method retrieves a paginated list of runs based on the specified filter parameters.
907
+ Pagination is controlled using the `page`, `page_size`, and `page_token` parameters. The method
908
+ will return a list of runs that match the filtering criteria provided.
856
909
 
857
- if (
858
- not name
859
- and not uid
860
- and not labels
861
- and not state
862
- and not states
863
- and not last
864
- and not start_time_from
865
- and not start_time_to
866
- and not last_update_time_from
867
- and not last_update_time_to
868
- and not partition_by
869
- and not partition_sort_by
870
- and not iter
871
- ):
872
- # default to last week on no filter
873
- start_time_from = datetime.now() - timedelta(days=7)
874
- partition_by = mlrun.common.schemas.RunPartitionByField.project_and_name
875
- partition_sort_by = mlrun.common.schemas.SortField.updated
910
+ For detailed information about the parameters, refer to the list_runs method:
911
+ See :py:func:`~list_runs` for more details.
876
912
 
877
- params = {
878
- "name": name,
879
- "uid": uid,
880
- "label": labels or [],
881
- "state": mlrun.utils.helpers.as_list(state)
882
- if state is not None
883
- else states or None,
884
- "sort": bool2str(sort),
885
- "iter": bool2str(iter),
886
- "start_time_from": datetime_to_iso(start_time_from),
887
- "start_time_to": datetime_to_iso(start_time_to),
888
- "last_update_time_from": datetime_to_iso(last_update_time_from),
889
- "last_update_time_to": datetime_to_iso(last_update_time_to),
890
- "with-notifications": with_notifications,
891
- }
913
+ Examples::
892
914
 
893
- if partition_by:
894
- params.update(
895
- self._generate_partition_by_params(
896
- mlrun.common.schemas.RunPartitionByField,
897
- partition_by,
898
- rows_per_partition,
899
- partition_sort_by,
900
- partition_order,
901
- max_partitions,
915
+ # Fetch first page of runs with page size of 5
916
+ runs, token = db.paginated_list_runs(project="my-project", page_size=5)
917
+ # Fetch next page using the pagination token from the previous response
918
+ runs, token = db.paginated_list_runs(project="my-project", page_token=token)
919
+ # Fetch runs for a specific page (e.g., page 3)
920
+ runs, token = db.paginated_list_runs(project="my-project", page=3, page_size=5)
921
+
922
+ # Automatically iterate over all pages without explicitly specifying the page number
923
+ runs = []
924
+ token = None
925
+ while True:
926
+ page_runs, token = db.paginated_list_runs(
927
+ project="my-project", page_token=token, page_size=5
902
928
  )
903
- )
904
- error = "list runs"
905
- _path = self._path_of("runs", project)
906
- responses = self.paginated_api_call("GET", _path, error, params=params)
907
- return RunList(self.process_paginated_responses(responses, "runs"))
929
+ runs.extend(page_runs)
930
+
931
+ # If token is None and page_runs is empty, we've reached the end (no more runs).
932
+ # If token is None and page_runs is not empty, we've fetched the last page of runs.
933
+ if not token:
934
+ break
935
+ print(f"Total runs retrieved: {len(runs)}")
936
+
937
+ :param page: The page number to retrieve. If not provided, the next page will be retrieved.
938
+ :param page_size: The number of items per page to retrieve. Up to `page_size` responses are expected.
939
+ :param page_token: A pagination token used to retrieve the next page of results. Should not be provided
940
+ for the first request.
941
+
942
+ :returns: A tuple containing the list of runs and an optional `page_token` for pagination.
943
+ """
944
+ return self._list_runs(
945
+ *args,
946
+ page=page,
947
+ page_size=page_size,
948
+ page_token=page_token,
949
+ return_all=False,
950
+ **kwargs,
951
+ )
908
952
 
909
- def del_runs(self, name=None, project=None, labels=None, state=None, days_ago=0):
953
+ def del_runs(
954
+ self,
955
+ name: Optional[str] = None,
956
+ project: Optional[str] = None,
957
+ labels: Optional[Union[str, dict[str, Optional[str]], list[str]]] = None,
958
+ state: Optional[mlrun.common.runtimes.constants.RunStates] = None,
959
+ days_ago: int = 0,
960
+ ):
910
961
  """Delete a group of runs identified by the parameters of the function.
911
962
 
912
963
  Example::
@@ -915,16 +966,23 @@ class HTTPRunDB(RunDBInterface):
915
966
 
916
967
  :param name: Name of the task which the runs belong to.
917
968
  :param project: Project to which the runs belong.
918
- :param labels: Filter runs that are labeled using these specific label values.
969
+ :param labels: Filter runs by label key-value pairs or key existence. This can be provided as:
970
+ - A dictionary in the format `{"label": "value"}` to match specific label key-value pairs,
971
+ or `{"label": None}` to check for key existence.
972
+ - A list of strings formatted as `"label=value"` to match specific label key-value pairs,
973
+ or just `"label"` for key existence.
974
+ - A comma-separated string formatted as `"label1=value1,label2"` to match entities with
975
+ the specified key-value pairs or key existence.
919
976
  :param state: Filter only runs which are in this state.
920
977
  :param days_ago: Filter runs whose start time is newer than this parameter.
921
978
  """
922
979
 
923
980
  project = project or config.default_project
981
+ labels = self._parse_labels(labels)
924
982
  params = {
925
983
  "name": name,
926
984
  "project": project,
927
- "label": labels or [],
985
+ "label": labels,
928
986
  "state": state,
929
987
  "days_ago": str(days_ago),
930
988
  }
@@ -1028,7 +1086,7 @@ class HTTPRunDB(RunDBInterface):
1028
1086
  deletion_strategy: mlrun.common.schemas.artifact.ArtifactsDeletionStrategies = (
1029
1087
  mlrun.common.schemas.artifact.ArtifactsDeletionStrategies.metadata_only
1030
1088
  ),
1031
- secrets: dict = None,
1089
+ secrets: Optional[dict] = None,
1032
1090
  iter=None,
1033
1091
  ):
1034
1092
  """Delete an artifact.
@@ -1063,29 +1121,29 @@ class HTTPRunDB(RunDBInterface):
1063
1121
 
1064
1122
  def list_artifacts(
1065
1123
  self,
1066
- name=None,
1067
- project=None,
1068
- tag=None,
1069
- labels: Optional[Union[dict[str, str], list[str]]] = None,
1124
+ name: Optional[str] = None,
1125
+ project: Optional[str] = None,
1126
+ tag: Optional[str] = None,
1127
+ labels: Optional[Union[str, dict[str, Optional[str]], list[str]]] = None,
1070
1128
  since: Optional[datetime] = None,
1071
1129
  until: Optional[datetime] = None,
1072
- iter: int = None,
1130
+ iter: Optional[int] = None,
1073
1131
  best_iteration: bool = False,
1074
- kind: str = None,
1132
+ kind: Optional[str] = None,
1075
1133
  category: Union[str, mlrun.common.schemas.ArtifactCategories] = None,
1076
- tree: str = None,
1077
- producer_uri: str = None,
1134
+ tree: Optional[str] = None,
1135
+ producer_uri: Optional[str] = None,
1078
1136
  format_: Optional[
1079
1137
  mlrun.common.formatters.ArtifactFormat
1080
1138
  ] = mlrun.common.formatters.ArtifactFormat.full,
1081
- limit: int = None,
1139
+ limit: Optional[int] = None,
1082
1140
  ) -> ArtifactList:
1083
1141
  """List artifacts filtered by various parameters.
1084
1142
 
1085
1143
  Examples::
1086
1144
 
1087
1145
  # Show latest version of all artifacts in project
1088
- latest_artifacts = db.list_artifacts("", tag="latest", project="iris")
1146
+ latest_artifacts = db.list_artifacts(tag="latest", project="iris")
1089
1147
  # check different artifact versions for a specific artifact
1090
1148
  result_versions = db.list_artifacts("results", tag="*", project="iris")
1091
1149
  # Show artifacts with label filters - both uploaded and of binary type
@@ -1098,8 +1156,13 @@ class HTTPRunDB(RunDBInterface):
1098
1156
  ``my_Name_1`` or ``surname``.
1099
1157
  :param project: Project name.
1100
1158
  :param tag: Return artifacts assigned this tag.
1101
- :param labels: Return artifacts that have these labels. Labels can either be a dictionary {"label": "value"} or
1102
- a list of "label=value" (match label key and value) or "label" (match just label key) strings.
1159
+ :param labels: Filter artifacts by label key-value pairs or key existence. This can be provided as:
1160
+ - A dictionary in the format `{"label": "value"}` to match specific label key-value pairs,
1161
+ or `{"label": None}` to check for key existence.
1162
+ - A list of strings formatted as `"label=value"` to match specific label key-value pairs,
1163
+ or just `"label"` for key existence.
1164
+ - A comma-separated string formatted as `"label1=value1,label2"` to match entities with
1165
+ the specified key-value pairs or key existence.
1103
1166
  :param since: Return artifacts updated after this date (as datetime object).
1104
1167
  :param until: Return artifacts updated before this date (as datetime object).
1105
1168
  :param iter: Return artifacts from a specific iteration (where ``iter=0`` means the root iteration). If
@@ -1117,36 +1180,97 @@ class HTTPRunDB(RunDBInterface):
1117
1180
  :param limit: Maximum number of artifacts to return.
1118
1181
  """
1119
1182
 
1120
- project = project or config.default_project
1183
+ artifacts, _ = self._list_artifacts(
1184
+ name=name,
1185
+ project=project,
1186
+ tag=tag,
1187
+ labels=labels,
1188
+ since=since,
1189
+ until=until,
1190
+ iter=iter,
1191
+ best_iteration=best_iteration,
1192
+ kind=kind,
1193
+ category=category,
1194
+ tree=tree,
1195
+ producer_uri=producer_uri,
1196
+ format_=format_,
1197
+ limit=limit,
1198
+ return_all=True,
1199
+ )
1200
+ return artifacts
1121
1201
 
1122
- labels = labels or []
1123
- if isinstance(labels, dict):
1124
- labels = [f"{key}={value}" for key, value in labels.items()]
1202
+ def paginated_list_artifacts(
1203
+ self,
1204
+ *args,
1205
+ page: Optional[int] = None,
1206
+ page_size: Optional[int] = None,
1207
+ page_token: Optional[str] = None,
1208
+ **kwargs,
1209
+ ) -> tuple[ArtifactList, Optional[str]]:
1210
+ """List artifacts with support for pagination and various filtering options.
1125
1211
 
1126
- params = {
1127
- "name": name,
1128
- "tag": tag,
1129
- "label": labels,
1130
- "iter": iter,
1131
- "best-iteration": best_iteration,
1132
- "kind": kind,
1133
- "category": category,
1134
- "tree": tree,
1135
- "format": format_,
1136
- "producer_uri": producer_uri,
1137
- "limit": limit,
1138
- "since": datetime_to_iso(since),
1139
- "until": datetime_to_iso(until),
1140
- }
1141
- error = "list artifacts"
1142
- endpoint_path = f"projects/{project}/artifacts"
1143
- resp = self.api_call("GET", endpoint_path, error, params=params, version="v2")
1144
- values = ArtifactList(resp.json()["artifacts"])
1145
- values.tag = tag
1146
- return values
1212
+ This method retrieves a paginated list of artifacts based on the specified filter parameters.
1213
+ Pagination is controlled using the `page`, `page_size`, and `page_token` parameters. The method
1214
+ will return a list of artifacts that match the filtering criteria provided.
1215
+
1216
+ For detailed information about the parameters, refer to the list_artifacts method:
1217
+ See :py:func:`~list_artifacts` for more details.
1218
+
1219
+ Examples::
1220
+
1221
+ # Fetch first page of artifacts with page size of 5
1222
+ artifacts, token = db.paginated_list_artifacts(
1223
+ project="my-project", page_size=5
1224
+ )
1225
+ # Fetch next page using the pagination token from the previous response
1226
+ artifacts, token = db.paginated_list_artifacts(
1227
+ project="my-project", page_token=token
1228
+ )
1229
+ # Fetch artifacts for a specific page (e.g., page 3)
1230
+ artifacts, token = db.paginated_list_artifacts(
1231
+ project="my-project", page=3, page_size=5
1232
+ )
1233
+
1234
+ # Automatically iterate over all pages without explicitly specifying the page number
1235
+ artifacts = []
1236
+ token = None
1237
+ while True:
1238
+ page_artifacts, token = db.paginated_list_artifacts(
1239
+ project="my-project", page_token=token, page_size=5
1240
+ )
1241
+ artifacts.extend(page_artifacts)
1242
+
1243
+ # If token is None and page_artifacts is empty, we've reached the end (no more artifacts).
1244
+ # If token is None and page_artifacts is not empty, we've fetched the last page of artifacts.
1245
+ if not token:
1246
+ break
1247
+ print(f"Total artifacts retrieved: {len(artifacts)}")
1248
+
1249
+ :param page: The page number to retrieve. If not provided, the next page will be retrieved.
1250
+ :param page_size: The number of items per page to retrieve. Up to `page_size` responses are expected.
1251
+ :param page_token: A pagination token used to retrieve the next page of results. Should not be provided
1252
+ for the first request.
1253
+
1254
+ :returns: A tuple containing the list of artifacts and an optional `page_token` for pagination.
1255
+ """
1256
+
1257
+ return self._list_artifacts(
1258
+ *args,
1259
+ page=page,
1260
+ page_size=page_size,
1261
+ page_token=page_token,
1262
+ return_all=False,
1263
+ **kwargs,
1264
+ )
1147
1265
 
1148
1266
  def del_artifacts(
1149
- self, name=None, project=None, tag=None, labels=None, days_ago=0, tree=None
1267
+ self,
1268
+ name: Optional[str] = None,
1269
+ project: Optional[str] = None,
1270
+ tag: Optional[str] = None,
1271
+ labels: Optional[Union[str, dict[str, Optional[str]], list[str]]] = None,
1272
+ days_ago=0,
1273
+ tree: Optional[str] = None,
1150
1274
  ):
1151
1275
  """Delete artifacts referenced by the parameters.
1152
1276
 
@@ -1154,15 +1278,24 @@ class HTTPRunDB(RunDBInterface):
1154
1278
  :py:func:`~list_artifacts` for more details.
1155
1279
  :param project: Project that artifacts belong to.
1156
1280
  :param tag: Choose artifacts who are assigned this tag.
1157
- :param labels: Choose artifacts which are labeled.
1281
+ :param labels: Filter artifacts by label key-value pairs or key existence. This can be provided as:
1282
+ - A dictionary in the format `{"label": "value"}` to match specific label key-value pairs,
1283
+ or `{"label": None}` to check for key existence.
1284
+ - A list of strings formatted as `"label=value"` to match specific label key-value pairs,
1285
+ or just `"label"` for key existence.
1286
+ - A comma-separated string formatted as `"label1=value1,label2"` to match entities with
1287
+ the specified key-value pairs or key existence.
1158
1288
  :param days_ago: This parameter is deprecated and not used.
1289
+ :param tree: Delete artifacts filtered by tree.
1159
1290
  """
1160
1291
  project = project or config.default_project
1292
+ labels = self._parse_labels(labels)
1293
+
1161
1294
  params = {
1162
1295
  "name": name,
1163
1296
  "tag": tag,
1164
1297
  "tree": tree,
1165
- "label": labels or [],
1298
+ "label": labels,
1166
1299
  "days_ago": str(days_ago),
1167
1300
  }
1168
1301
  error = "del artifacts"
@@ -1254,30 +1387,110 @@ class HTTPRunDB(RunDBInterface):
1254
1387
  )
1255
1388
 
1256
1389
  def list_functions(
1257
- self, name=None, project=None, tag=None, labels=None, since=None, until=None
1390
+ self,
1391
+ name: Optional[str] = None,
1392
+ project: Optional[str] = None,
1393
+ tag: Optional[str] = None,
1394
+ labels: Optional[Union[str, dict[str, Optional[str]], list[str]]] = None,
1395
+ since: Optional[datetime] = None,
1396
+ until: Optional[datetime] = None,
1397
+ kind: Optional[str] = None,
1398
+ format_: mlrun.common.formatters.FunctionFormat = mlrun.common.formatters.FunctionFormat.full,
1258
1399
  ):
1259
1400
  """Retrieve a list of functions, filtered by specific criteria.
1260
1401
 
1261
1402
  :param name: Return only functions with a specific name.
1262
1403
  :param project: Return functions belonging to this project. If not specified, the default project is used.
1263
1404
  :param tag: Return function versions with specific tags. To return only tagged functions, set tag to ``"*"``.
1264
- :param labels: Return functions that have specific labels assigned to them.
1405
+ :param labels: Filter functions by label key-value pairs or key existence. This can be provided as:
1406
+ - A dictionary in the format `{"label": "value"}` to match specific label key-value pairs,
1407
+ or `{"label": None}` to check for key existence.
1408
+ - A list of strings formatted as `"label=value"` to match specific label key-value pairs,
1409
+ or just `"label"` for key existence.
1410
+ - A comma-separated string formatted as `"label1=value1,label2"` to match entities with
1411
+ the specified key-value pairs or key existence.
1265
1412
  :param since: Return functions updated after this date (as datetime object).
1266
1413
  :param until: Return functions updated before this date (as datetime object).
1414
+ :param kind: Return only functions of a specific kind.
1415
+ :param format_: The format in which to return the functions. Default is 'full'.
1267
1416
  :returns: List of function objects (as dictionary).
1268
1417
  """
1269
- project = project or config.default_project
1270
- params = {
1271
- "name": name,
1272
- "tag": tag,
1273
- "label": labels or [],
1274
- "since": datetime_to_iso(since),
1275
- "until": datetime_to_iso(until),
1276
- }
1277
- error = "list functions"
1278
- path = f"projects/{project}/functions"
1279
- responses = self.paginated_api_call("GET", path, error, params=params)
1280
- return self.process_paginated_responses(responses, "funcs")
1418
+ functions, _ = self._list_functions(
1419
+ name=name,
1420
+ project=project,
1421
+ tag=tag,
1422
+ kind=kind,
1423
+ labels=labels,
1424
+ format_=format_,
1425
+ since=since,
1426
+ until=until,
1427
+ return_all=True,
1428
+ )
1429
+ return functions
1430
+
1431
+ def paginated_list_functions(
1432
+ self,
1433
+ *args,
1434
+ page: Optional[int] = None,
1435
+ page_size: Optional[int] = None,
1436
+ page_token: Optional[str] = None,
1437
+ **kwargs,
1438
+ ) -> tuple[list[dict], Optional[str]]:
1439
+ """List functions with support for pagination and various filtering options.
1440
+
1441
+ This method retrieves a paginated list of functions based on the specified filter parameters.
1442
+ Pagination is controlled using the `page`, `page_size`, and `page_token` parameters. The method
1443
+ will return a list of functions that match the filtering criteria provided.
1444
+
1445
+ For detailed information about the parameters, refer to the list_functions method:
1446
+ See :py:func:`~list_functions` for more details.
1447
+
1448
+ Examples::
1449
+
1450
+ # Fetch first page of functions with page size of 5
1451
+ functions, token = db.paginated_list_functions(
1452
+ project="my-project", page_size=5
1453
+ )
1454
+ # Fetch next page using the pagination token from the previous response
1455
+ functions, token = db.paginated_list_functions(
1456
+ project="my-project", page_token=token
1457
+ )
1458
+ # Fetch functions for a specific page (e.g., page 3)
1459
+ functions, token = db.paginated_list_functions(
1460
+ project="my-project", page=3, page_size=5
1461
+ )
1462
+
1463
+ # Automatically iterate over all pages without explicitly specifying the page number
1464
+ functions = []
1465
+ token = None
1466
+ while True:
1467
+ page_functions, token = db.paginated_list_functions(
1468
+ project="my-project", page_token=token, page_size=5
1469
+ )
1470
+ functions.extend(page_functions)
1471
+
1472
+ # If token is None and page_functions is empty, we've reached the end (no more functions).
1473
+ # If token is None and page_functions is not empty, we've fetched the last page of functions.
1474
+ if not token:
1475
+ break
1476
+ print(f"Total functions retrieved: {len(functions)}")
1477
+
1478
+ :param page: The page number to retrieve. If not provided, the next page will be retrieved.
1479
+ :param page_size: The number of items per page to retrieve. Up to `page_size` responses are expected.
1480
+ :param page_token: A pagination token used to retrieve the next page of results. Should not be provided
1481
+ for the first request.
1482
+
1483
+ :returns: A tuple containing the list of functions objects (as dictionary) and an optional
1484
+ `page_token` for pagination.
1485
+ """
1486
+ return self._list_functions(
1487
+ *args,
1488
+ page=page,
1489
+ page_size=page_size,
1490
+ page_token=page_token,
1491
+ return_all=False,
1492
+ **kwargs,
1493
+ )
1281
1494
 
1282
1495
  def list_runtime_resources(
1283
1496
  self,
@@ -1352,7 +1565,7 @@ class HTTPRunDB(RunDBInterface):
1352
1565
  kind: Optional[str] = None,
1353
1566
  object_id: Optional[str] = None,
1354
1567
  force: bool = False,
1355
- grace_period: int = None,
1568
+ grace_period: Optional[int] = None,
1356
1569
  ) -> mlrun.common.schemas.GroupedByProjectRuntimeResourcesOutput:
1357
1570
  """Delete all runtime resources which are in terminal state.
1358
1571
 
@@ -1464,7 +1677,7 @@ class HTTPRunDB(RunDBInterface):
1464
1677
  def list_schedules(
1465
1678
  self,
1466
1679
  project: str,
1467
- name: str = None,
1680
+ name: Optional[str] = None,
1468
1681
  kind: mlrun.common.schemas.ScheduleKinds = None,
1469
1682
  include_last_run: bool = False,
1470
1683
  ) -> mlrun.common.schemas.SchedulesOutput:
@@ -1636,6 +1849,7 @@ class HTTPRunDB(RunDBInterface):
1636
1849
  logs: bool = True,
1637
1850
  last_log_timestamp: float = 0.0,
1638
1851
  verbose: bool = False,
1852
+ events_offset: int = 0,
1639
1853
  ):
1640
1854
  """Retrieve the status of a build operation currently in progress.
1641
1855
 
@@ -1645,6 +1859,7 @@ class HTTPRunDB(RunDBInterface):
1645
1859
  :param last_log_timestamp: Last timestamp of logs that were already retrieved. Function will return only logs
1646
1860
  later than this parameter.
1647
1861
  :param verbose: Add verbose logs into the output.
1862
+ :param events_offset: Offset into the build events to retrieve events from.
1648
1863
 
1649
1864
  :returns: The following parameters:
1650
1865
 
@@ -1661,6 +1876,7 @@ class HTTPRunDB(RunDBInterface):
1661
1876
  "tag": func.metadata.tag,
1662
1877
  "logs": bool2str(logs),
1663
1878
  "offset": str(offset),
1879
+ "events_offset": str(events_offset),
1664
1880
  "last_log_timestamp": str(last_log_timestamp),
1665
1881
  "verbose": bool2str(verbose),
1666
1882
  }
@@ -1673,6 +1889,7 @@ class HTTPRunDB(RunDBInterface):
1673
1889
  logger.warning(f"failed resp, {resp.text}")
1674
1890
  raise RunDBError("bad function build response")
1675
1891
 
1892
+ deploy_status_text_kind = mlrun.common.constants.DeployStatusTextKind.logs
1676
1893
  if resp.headers:
1677
1894
  func.status.state = resp.headers.get("x-mlrun-function-status", "")
1678
1895
  last_log_timestamp = float(
@@ -1691,13 +1908,20 @@ class HTTPRunDB(RunDBInterface):
1691
1908
  if function_image:
1692
1909
  func.spec.image = function_image
1693
1910
 
1911
+ deploy_status_text_kind = resp.headers.get(
1912
+ "deploy_status_text_kind",
1913
+ mlrun.common.constants.DeployStatusTextKind.logs,
1914
+ )
1915
+
1694
1916
  text = ""
1695
1917
  if resp.content:
1696
1918
  text = resp.content.decode()
1697
- return text, last_log_timestamp
1919
+ return text, last_log_timestamp, deploy_status_text_kind
1698
1920
 
1699
1921
  def start_function(
1700
- self, func_url: str = None, function: "mlrun.runtimes.BaseRuntime" = None
1922
+ self,
1923
+ func_url: Optional[str] = None,
1924
+ function: "mlrun.runtimes.BaseRuntime" = None,
1701
1925
  ) -> mlrun.common.schemas.BackgroundTask:
1702
1926
  """Execute a function remotely, Used for ``dask`` functions.
1703
1927
 
@@ -1939,14 +2163,14 @@ class HTTPRunDB(RunDBInterface):
1939
2163
  def list_pipelines(
1940
2164
  self,
1941
2165
  project: str,
1942
- namespace: str = None,
2166
+ namespace: Optional[str] = None,
1943
2167
  sort_by: str = "",
1944
2168
  page_token: str = "",
1945
2169
  filter_: str = "",
1946
2170
  format_: Union[
1947
2171
  str, mlrun.common.formatters.PipelineFormat
1948
2172
  ] = mlrun.common.formatters.PipelineFormat.metadata_only,
1949
- page_size: int = None,
2173
+ page_size: Optional[int] = None,
1950
2174
  ) -> mlrun.common.schemas.PipelinesOutput:
1951
2175
  """Retrieve a list of KFP pipelines. This function can be invoked to get all pipelines from all projects,
1952
2176
  by specifying ``project=*``, in which case pagination can be used and the various sorting and pagination
@@ -1988,12 +2212,12 @@ class HTTPRunDB(RunDBInterface):
1988
2212
  def get_pipeline(
1989
2213
  self,
1990
2214
  run_id: str,
1991
- namespace: str = None,
2215
+ namespace: Optional[str] = None,
1992
2216
  timeout: int = 30,
1993
2217
  format_: Union[
1994
2218
  str, mlrun.common.formatters.PipelineFormat
1995
2219
  ] = mlrun.common.formatters.PipelineFormat.summary,
1996
- project: str = None,
2220
+ project: Optional[str] = None,
1997
2221
  ):
1998
2222
  """Retrieve details of a specific pipeline using its run ID (as provided when the pipeline was executed)."""
1999
2223
 
@@ -2061,7 +2285,11 @@ class HTTPRunDB(RunDBInterface):
2061
2285
  return resp.json()
2062
2286
 
2063
2287
  def get_feature_set(
2064
- self, name: str, project: str = "", tag: str = None, uid: str = None
2288
+ self,
2289
+ name: str,
2290
+ project: str = "",
2291
+ tag: Optional[str] = None,
2292
+ uid: Optional[str] = None,
2065
2293
  ) -> FeatureSet:
2066
2294
  """Retrieve a ~mlrun.feature_store.FeatureSet` object. If both ``tag`` and ``uid`` are not specified, then
2067
2295
  the object tagged ``latest`` will be retrieved.
@@ -2081,11 +2309,11 @@ class HTTPRunDB(RunDBInterface):
2081
2309
 
2082
2310
  def list_features(
2083
2311
  self,
2084
- project: str,
2085
- name: str = None,
2086
- tag: str = None,
2087
- entities: list[str] = None,
2088
- labels: list[str] = None,
2312
+ project: Optional[str] = None,
2313
+ name: Optional[str] = None,
2314
+ tag: Optional[str] = None,
2315
+ entities: Optional[list[str]] = None,
2316
+ labels: Optional[Union[str, dict[str, Optional[str]], list[str]]] = None,
2089
2317
  ) -> list[dict]:
2090
2318
  """List feature-sets which contain specific features. This function may return multiple versions of the same
2091
2319
  feature-set if a specific tag is not requested. Note that the various filters of this function actually
@@ -2096,18 +2324,25 @@ class HTTPRunDB(RunDBInterface):
2096
2324
  example, looking for ``feat`` will return features which are named ``MyFeature`` as well as ``defeat``.
2097
2325
  :param tag: Return feature-sets which contain the features looked for, and are tagged with the specific tag.
2098
2326
  :param entities: Return only feature-sets which contain an entity whose name is contained in this list.
2099
- :param labels: Return only feature-sets which are labeled as requested.
2327
+ :param labels: Filter feature-sets by label key-value pairs or key existence. This can be provided as:
2328
+ - A dictionary in the format `{"label": "value"}` to match specific label key-value pairs,
2329
+ or `{"label": None}` to check for key existence.
2330
+ - A list of strings formatted as `"label=value"` to match specific label key-value pairs,
2331
+ or just `"label"` for key existence.
2332
+ - A comma-separated string formatted as `"label1=value1,label2"` to match entities with
2333
+ the specified key-value pairs or key existence.
2100
2334
  :returns: A list of mapping from feature to a digest of the feature-set, which contains the feature-set
2101
2335
  meta-data. Multiple entries may be returned for any specific feature due to multiple tags or versions
2102
2336
  of the feature-set.
2103
2337
  """
2104
2338
 
2105
2339
  project = project or config.default_project
2340
+ labels = self._parse_labels(labels)
2106
2341
  params = {
2107
2342
  "name": name,
2108
2343
  "tag": tag,
2109
2344
  "entity": entities or [],
2110
- "label": labels or [],
2345
+ "label": labels,
2111
2346
  }
2112
2347
 
2113
2348
  path = f"projects/{project}/features"
@@ -2118,11 +2353,11 @@ class HTTPRunDB(RunDBInterface):
2118
2353
 
2119
2354
  def list_features_v2(
2120
2355
  self,
2121
- project: str,
2122
- name: str = None,
2123
- tag: str = None,
2124
- entities: list[str] = None,
2125
- labels: list[str] = None,
2356
+ project: Optional[str] = None,
2357
+ name: Optional[str] = None,
2358
+ tag: Optional[str] = None,
2359
+ entities: Optional[list[str]] = None,
2360
+ labels: Optional[Union[str, dict[str, Optional[str]], list[str]]] = None,
2126
2361
  ) -> dict[str, list[dict]]:
2127
2362
  """List feature-sets which contain specific features. This function may return multiple versions of the same
2128
2363
  feature-set if a specific tag is not requested. Note that the various filters of this function actually
@@ -2133,16 +2368,23 @@ class HTTPRunDB(RunDBInterface):
2133
2368
  example, looking for ``feat`` will return features which are named ``MyFeature`` as well as ``defeat``.
2134
2369
  :param tag: Return feature-sets which contain the features looked for, and are tagged with the specific tag.
2135
2370
  :param entities: Return only feature-sets which contain an entity whose name is contained in this list.
2136
- :param labels: Return only feature-sets which are labeled as requested.
2371
+ :param labels: Filter feature-sets by label key-value pairs or key existence. This can be provided as:
2372
+ - A dictionary in the format `{"label": "value"}` to match specific label key-value pairs,
2373
+ or `{"label": None}` to check for key existence.
2374
+ - A list of strings formatted as `"label=value"` to match specific label key-value pairs,
2375
+ or just `"label"` for key existence.
2376
+ - A comma-separated string formatted as `"label1=value1,label2"` to match entities with
2377
+ the specified key-value pairs or key existence.
2137
2378
  :returns: A list of features, and a list of their corresponding feature sets.
2138
2379
  """
2139
2380
 
2140
2381
  project = project or config.default_project
2382
+ labels = self._parse_labels(labels)
2141
2383
  params = {
2142
2384
  "name": name,
2143
2385
  "tag": tag,
2144
2386
  "entity": entities or [],
2145
- "label": labels or [],
2387
+ "label": labels,
2146
2388
  }
2147
2389
 
2148
2390
  path = f"projects/{project}/features"
@@ -2153,21 +2395,34 @@ class HTTPRunDB(RunDBInterface):
2153
2395
 
2154
2396
  def list_entities(
2155
2397
  self,
2156
- project: str,
2157
- name: str = None,
2158
- tag: str = None,
2159
- labels: list[str] = None,
2398
+ project: Optional[str] = None,
2399
+ name: Optional[str] = None,
2400
+ tag: Optional[str] = None,
2401
+ labels: Optional[Union[str, dict[str, Optional[str]], list[str]]] = None,
2160
2402
  ) -> list[dict]:
2161
2403
  """Retrieve a list of entities and their mapping to the containing feature-sets. This function is similar
2162
2404
  to the :py:func:`~list_features` function, and uses the same logic. However, the entities are matched
2163
2405
  against the name rather than the features.
2406
+
2407
+ :param project: The project containing the entities.
2408
+ :param name: The name of the entities to retrieve.
2409
+ :param tag: The tag of the specific entity version to retrieve.
2410
+ :param labels: Filter entities by label key-value pairs or key existence. This can be provided as:
2411
+ - A dictionary in the format `{"label": "value"}` to match specific label key-value pairs,
2412
+ or `{"label": None}` to check for key existence.
2413
+ - A list of strings formatted as `"label=value"` to match specific label key-value pairs,
2414
+ or just `"label"` for key existence.
2415
+ - A comma-separated string formatted as `"label1=value1,label2"` to match entities with
2416
+ the specified key-value pairs or key existence.
2417
+ :returns: A list of entities.
2164
2418
  """
2165
2419
 
2166
2420
  project = project or config.default_project
2421
+ labels = self._parse_labels(labels)
2167
2422
  params = {
2168
2423
  "name": name,
2169
2424
  "tag": tag,
2170
- "label": labels or [],
2425
+ "label": labels,
2171
2426
  }
2172
2427
 
2173
2428
  path = f"projects/{project}/entities"
@@ -2178,21 +2433,34 @@ class HTTPRunDB(RunDBInterface):
2178
2433
 
2179
2434
  def list_entities_v2(
2180
2435
  self,
2181
- project: str,
2182
- name: str = None,
2183
- tag: str = None,
2184
- labels: list[str] = None,
2436
+ project: Optional[str] = None,
2437
+ name: Optional[str] = None,
2438
+ tag: Optional[str] = None,
2439
+ labels: Optional[Union[str, dict[str, Optional[str]], list[str]]] = None,
2185
2440
  ) -> dict[str, list[dict]]:
2186
2441
  """Retrieve a list of entities and their mapping to the containing feature-sets. This function is similar
2187
2442
  to the :py:func:`~list_features_v2` function, and uses the same logic. However, the entities are matched
2188
2443
  against the name rather than the features.
2444
+
2445
+ :param project: The project containing the entities.
2446
+ :param name: The name of the entities to retrieve.
2447
+ :param tag: The tag of the specific entity version to retrieve.
2448
+ :param labels: Filter entities by label key-value pairs or key existence. This can be provided as:
2449
+ - A dictionary in the format `{"label": "value"}` to match specific label key-value pairs,
2450
+ or `{"label": None}` to check for key existence.
2451
+ - A list of strings formatted as `"label=value"` to match specific label key-value pairs,
2452
+ or just `"label"` for key existence.
2453
+ - A comma-separated string formatted as `"label1=value1,label2"` to match entities with
2454
+ the specified key-value pairs or key existence.
2455
+ :returns: A list of entities.
2189
2456
  """
2190
2457
 
2191
2458
  project = project or config.default_project
2459
+ labels = self._parse_labels(labels)
2192
2460
  params = {
2193
2461
  "name": name,
2194
2462
  "tag": tag,
2195
- "label": labels or [],
2463
+ "label": labels,
2196
2464
  }
2197
2465
 
2198
2466
  path = f"projects/{project}/entities"
@@ -2222,13 +2490,13 @@ class HTTPRunDB(RunDBInterface):
2222
2490
 
2223
2491
  def list_feature_sets(
2224
2492
  self,
2225
- project: str = "",
2226
- name: str = None,
2227
- tag: str = None,
2228
- state: str = None,
2229
- entities: list[str] = None,
2230
- features: list[str] = None,
2231
- labels: list[str] = None,
2493
+ project: Optional[str] = None,
2494
+ name: Optional[str] = None,
2495
+ tag: Optional[str] = None,
2496
+ state: Optional[str] = None,
2497
+ entities: Optional[list[str]] = None,
2498
+ features: Optional[list[str]] = None,
2499
+ labels: Optional[Union[str, dict[str, Optional[str]], list[str]]] = None,
2232
2500
  partition_by: Union[
2233
2501
  mlrun.common.schemas.FeatureStorePartitionByField, str
2234
2502
  ] = None,
@@ -2249,7 +2517,13 @@ class HTTPRunDB(RunDBInterface):
2249
2517
  :param state: Match feature-sets with a specific state.
2250
2518
  :param entities: Match feature-sets which contain entities whose name is in this list.
2251
2519
  :param features: Match feature-sets which contain features whose name is in this list.
2252
- :param labels: Match feature-sets which have these labels.
2520
+ :param labels: Filter feature-sets by label key-value pairs or key existence. This can be provided as:
2521
+ - A dictionary in the format `{"label": "value"}` to match specific label key-value pairs,
2522
+ or `{"label": None}` to check for key existence.
2523
+ - A list of strings formatted as `"label=value"` to match specific label key-value pairs,
2524
+ or just `"label"` for key existence.
2525
+ - A comma-separated string formatted as `"label1=value1,label2"` to match entities with
2526
+ the specified key-value pairs or key existence.
2253
2527
  :param partition_by: Field to group results by. Only allowed value is `name`. When `partition_by` is specified,
2254
2528
  the `partition_sort_by` parameter must be provided as well.
2255
2529
  :param rows_per_partition: How many top rows (per sorting defined by `partition_sort_by` and `partition_order`)
@@ -2264,14 +2538,14 @@ class HTTPRunDB(RunDBInterface):
2264
2538
  """
2265
2539
 
2266
2540
  project = project or config.default_project
2267
-
2541
+ labels = self._parse_labels(labels)
2268
2542
  params = {
2269
2543
  "name": name,
2270
2544
  "state": state,
2271
2545
  "tag": tag,
2272
2546
  "entity": entities or [],
2273
2547
  "feature": features or [],
2274
- "label": labels or [],
2548
+ "label": labels,
2275
2549
  "format": format_,
2276
2550
  }
2277
2551
  if partition_by:
@@ -2436,7 +2710,11 @@ class HTTPRunDB(RunDBInterface):
2436
2710
  return resp.json()
2437
2711
 
2438
2712
  def get_feature_vector(
2439
- self, name: str, project: str = "", tag: str = None, uid: str = None
2713
+ self,
2714
+ name: str,
2715
+ project: str = "",
2716
+ tag: Optional[str] = None,
2717
+ uid: Optional[str] = None,
2440
2718
  ) -> FeatureVector:
2441
2719
  """Return a specific feature-vector referenced by its tag or uid. If none are provided, ``latest`` tag will
2442
2720
  be used."""
@@ -2450,11 +2728,11 @@ class HTTPRunDB(RunDBInterface):
2450
2728
 
2451
2729
  def list_feature_vectors(
2452
2730
  self,
2453
- project: str = "",
2454
- name: str = None,
2455
- tag: str = None,
2456
- state: str = None,
2457
- labels: list[str] = None,
2731
+ project: Optional[str] = None,
2732
+ name: Optional[str] = None,
2733
+ tag: Optional[str] = None,
2734
+ state: Optional[str] = None,
2735
+ labels: Optional[Union[str, dict[str, Optional[str]], list[str]]] = None,
2458
2736
  partition_by: Union[
2459
2737
  mlrun.common.schemas.FeatureStorePartitionByField, str
2460
2738
  ] = None,
@@ -2470,7 +2748,13 @@ class HTTPRunDB(RunDBInterface):
2470
2748
  :param name: Name of feature-vector to match. This is a like query, and is case-insensitive.
2471
2749
  :param tag: Match feature-vectors with specific tag.
2472
2750
  :param state: Match feature-vectors with a specific state.
2473
- :param labels: Match feature-vectors which have these labels.
2751
+ :param labels: Filter feature-vectors by label key-value pairs or key existence. This can be provided as:
2752
+ - A dictionary in the format `{"label": "value"}` to match specific label key-value pairs,
2753
+ or `{"label": None}` to check for key existence.
2754
+ - A list of strings formatted as `"label=value"` to match specific label key-value pairs,
2755
+ or just `"label"` for key existence.
2756
+ - A comma-separated string formatted as `"label1=value1,label2"` to match entities with
2757
+ the specified key-value pairs or key existence.
2474
2758
  :param partition_by: Field to group results by. Only allowed value is `name`. When `partition_by` is specified,
2475
2759
  the `partition_sort_by` parameter must be provided as well.
2476
2760
  :param rows_per_partition: How many top rows (per sorting defined by `partition_sort_by` and `partition_order`)
@@ -2482,12 +2766,12 @@ class HTTPRunDB(RunDBInterface):
2482
2766
  """
2483
2767
 
2484
2768
  project = project or config.default_project
2485
-
2769
+ labels = self._parse_labels(labels)
2486
2770
  params = {
2487
2771
  "name": name,
2488
2772
  "state": state,
2489
2773
  "tag": tag,
2490
- "label": labels or [],
2774
+ "label": labels,
2491
2775
  }
2492
2776
  if partition_by:
2493
2777
  params.update(
@@ -2699,11 +2983,11 @@ class HTTPRunDB(RunDBInterface):
2699
2983
 
2700
2984
  def list_projects(
2701
2985
  self,
2702
- owner: str = None,
2986
+ owner: Optional[str] = None,
2703
2987
  format_: Union[
2704
2988
  str, mlrun.common.formatters.ProjectFormat
2705
2989
  ] = mlrun.common.formatters.ProjectFormat.name_only,
2706
- labels: list[str] = None,
2990
+ labels: Optional[Union[str, dict[str, Optional[str]], list[str]]] = None,
2707
2991
  state: Union[str, mlrun.common.schemas.ProjectState] = None,
2708
2992
  ) -> list[Union[mlrun.projects.MlrunProject, str]]:
2709
2993
  """Return a list of the existing projects, potentially filtered by specific criteria.
@@ -2715,15 +2999,22 @@ class HTTPRunDB(RunDBInterface):
2715
2999
  - ``minimal`` - Return minimal project objects (minimization happens in the BE).
2716
3000
  - ``full`` - Return full project objects.
2717
3001
 
2718
- :param labels: Filter by labels attached to the project.
3002
+ :param labels: Filter projects by label key-value pairs or key existence. This can be provided as:
3003
+ - A dictionary in the format `{"label": "value"}` to match specific label key-value pairs,
3004
+ or `{"label": None}` to check for key existence.
3005
+ - A list of strings formatted as `"label=value"` to match specific label key-value pairs,
3006
+ or just `"label"` for key existence.
3007
+ - A comma-separated string formatted as `"label1=value1,label2"` to match entities with
3008
+ the specified key-value pairs or key existence.
2719
3009
  :param state: Filter by project's state. Can be either ``online`` or ``archived``.
2720
3010
  """
3011
+ labels = self._parse_labels(labels)
2721
3012
 
2722
3013
  params = {
2723
3014
  "owner": owner,
2724
3015
  "state": state,
2725
3016
  "format": format_,
2726
- "label": labels or [],
3017
+ "label": labels,
2727
3018
  }
2728
3019
 
2729
3020
  error_message = f"Failed listing projects, query: {params}"
@@ -2919,7 +3210,7 @@ class HTTPRunDB(RunDBInterface):
2919
3210
  provider: Union[
2920
3211
  str, mlrun.common.schemas.SecretProviderName
2921
3212
  ] = mlrun.common.schemas.SecretProviderName.kubernetes,
2922
- secrets: dict = None,
3213
+ secrets: Optional[dict] = None,
2923
3214
  ):
2924
3215
  """Create project-context secrets using either ``vault`` or ``kubernetes`` provider.
2925
3216
  When using with Vault, this will create needed Vault structures for storing secrets in project-context, and
@@ -2963,11 +3254,11 @@ class HTTPRunDB(RunDBInterface):
2963
3254
  def list_project_secrets(
2964
3255
  self,
2965
3256
  project: str,
2966
- token: str = None,
3257
+ token: Optional[str] = None,
2967
3258
  provider: Union[
2968
3259
  str, mlrun.common.schemas.SecretProviderName
2969
3260
  ] = mlrun.common.schemas.SecretProviderName.kubernetes,
2970
- secrets: list[str] = None,
3261
+ secrets: Optional[list[str]] = None,
2971
3262
  ) -> mlrun.common.schemas.SecretsData:
2972
3263
  """Retrieve project-context secrets from Vault.
2973
3264
 
@@ -3010,7 +3301,7 @@ class HTTPRunDB(RunDBInterface):
3010
3301
  provider: Union[
3011
3302
  str, mlrun.common.schemas.SecretProviderName
3012
3303
  ] = mlrun.common.schemas.SecretProviderName.kubernetes,
3013
- token: str = None,
3304
+ token: Optional[str] = None,
3014
3305
  ) -> mlrun.common.schemas.SecretKeysData:
3015
3306
  """Retrieve project-context secret keys from Vault or Kubernetes.
3016
3307
 
@@ -3056,7 +3347,7 @@ class HTTPRunDB(RunDBInterface):
3056
3347
  provider: Union[
3057
3348
  str, mlrun.common.schemas.SecretProviderName
3058
3349
  ] = mlrun.common.schemas.SecretProviderName.kubernetes,
3059
- secrets: list[str] = None,
3350
+ secrets: Optional[list[str]] = None,
3060
3351
  ):
3061
3352
  """Delete project-context secrets from Kubernetes.
3062
3353
 
@@ -3076,13 +3367,44 @@ class HTTPRunDB(RunDBInterface):
3076
3367
  params=params,
3077
3368
  )
3078
3369
 
3370
+ def get_model_endpoint_monitoring_metrics(
3371
+ self,
3372
+ project: str,
3373
+ endpoint_id: str,
3374
+ type: Literal["results", "metrics", "all"] = "all",
3375
+ ) -> list[mm_endpoints.ModelEndpointMonitoringMetric]:
3376
+ """Get application metrics/results by endpoint id and project.
3377
+
3378
+ :param project: The name of the project.
3379
+ :param endpoint_id: The unique id of the model endpoint.
3380
+ :param type: The type of the metrics to return. "all" means "results" and "metrics".
3381
+
3382
+ :return: A list of the application metrics or/and results for this model endpoint.
3383
+ """
3384
+ path = f"projects/{project}/model-endpoints/{endpoint_id}/metrics"
3385
+ params = {"type": type}
3386
+ error_message = (
3387
+ f"Failed to get model endpoint monitoring metrics,"
3388
+ f" endpoint_id: {endpoint_id}, project: {project}"
3389
+ )
3390
+ response = self.api_call(
3391
+ mlrun.common.types.HTTPMethod.GET,
3392
+ path,
3393
+ error_message,
3394
+ params=params,
3395
+ )
3396
+ monitoring_metrics = response.json()
3397
+ return parse_obj_as(
3398
+ list[mm_endpoints.ModelEndpointMonitoringMetric], monitoring_metrics
3399
+ )
3400
+
3079
3401
  def create_user_secrets(
3080
3402
  self,
3081
3403
  user: str,
3082
3404
  provider: Union[
3083
3405
  str, mlrun.common.schemas.SecretProviderName
3084
3406
  ] = mlrun.common.schemas.SecretProviderName.vault,
3085
- secrets: dict = None,
3407
+ secrets: Optional[dict] = None,
3086
3408
  ):
3087
3409
  """Create user-context secret in Vault. Please refer to :py:func:`create_project_secrets` for more details
3088
3410
  and status of this functionality.
@@ -3213,7 +3535,7 @@ class HTTPRunDB(RunDBInterface):
3213
3535
  project: str,
3214
3536
  model: Optional[str] = None,
3215
3537
  function: Optional[str] = None,
3216
- labels: list[str] = None,
3538
+ labels: Optional[Union[str, dict[str, Optional[str]], list[str]]] = None,
3217
3539
  start: str = "now-1h",
3218
3540
  end: str = "now",
3219
3541
  metrics: Optional[list[str]] = None,
@@ -3237,8 +3559,13 @@ class HTTPRunDB(RunDBInterface):
3237
3559
  :param project: The name of the project
3238
3560
  :param model: The name of the model to filter by
3239
3561
  :param function: The name of the function to filter by
3240
- :param labels: A list of labels to filter by. Label filters work by either filtering a specific value of a
3241
- label (i.e. list("key=value")) or by looking for the existence of a given key (i.e. "key")
3562
+ :param labels: Filter model endpoints by label key-value pairs or key existence. This can be provided as:
3563
+ - A dictionary in the format `{"label": "value"}` to match specific label key-value pairs,
3564
+ or `{"label": None}` to check for key existence.
3565
+ - A list of strings formatted as `"label=value"` to match specific label key-value pairs,
3566
+ or just `"label"` for key existence.
3567
+ - A comma-separated string formatted as `"label1=value1,label2"` to match entities with
3568
+ the specified key-value pairs or key existence.
3242
3569
  :param metrics: A list of metrics to return for each endpoint, read more in 'TimeMetric'
3243
3570
  :param start: The start time of the metrics. Can be represented by a string containing an RFC 3339 time, a
3244
3571
  Unix timestamp in milliseconds, a relative time (`'now'` or `'now-[0-9]+[mhd]'`, where
@@ -3248,12 +3575,12 @@ class HTTPRunDB(RunDBInterface):
3248
3575
  `m` = minutes, `h` = hours, `'d'` = days, and `'s'` = seconds), or 0 for the earliest time.
3249
3576
  :param top_level: if true will return only routers and endpoint that are NOT children of any router
3250
3577
  :param uids: if passed will return a list `ModelEndpoint` object with uid in uids
3578
+
3579
+ :returns: Returns a list of `ModelEndpoint` objects.
3251
3580
  """
3252
3581
 
3253
3582
  path = f"projects/{project}/model-endpoints"
3254
-
3255
- if labels and isinstance(labels, dict):
3256
- labels = [f"{key}={value}" for key, value in labels.items()]
3583
+ labels = self._parse_labels(labels)
3257
3584
 
3258
3585
  response = self.api_call(
3259
3586
  method="GET",
@@ -3261,7 +3588,7 @@ class HTTPRunDB(RunDBInterface):
3261
3588
  params={
3262
3589
  "model": model,
3263
3590
  "function": function,
3264
- "label": labels or [],
3591
+ "label": labels,
3265
3592
  "start": start,
3266
3593
  "end": end,
3267
3594
  "metric": metrics or [],
@@ -3441,7 +3768,7 @@ class HTTPRunDB(RunDBInterface):
3441
3768
  delete_stream_function: bool = False,
3442
3769
  delete_histogram_data_drift_app: bool = True,
3443
3770
  delete_user_applications: bool = False,
3444
- user_application_list: list[str] = None,
3771
+ user_application_list: Optional[list[str]] = None,
3445
3772
  ) -> bool:
3446
3773
  """
3447
3774
  Disable model monitoring application controller, writer, stream, histogram data drift application
@@ -3714,8 +4041,8 @@ class HTTPRunDB(RunDBInterface):
3714
4041
  def get_hub_catalog(
3715
4042
  self,
3716
4043
  source_name: str,
3717
- version: str = None,
3718
- tag: str = None,
4044
+ version: Optional[str] = None,
4045
+ tag: Optional[str] = None,
3719
4046
  force_refresh: bool = False,
3720
4047
  ):
3721
4048
  """
@@ -3745,7 +4072,7 @@ class HTTPRunDB(RunDBInterface):
3745
4072
  self,
3746
4073
  source_name: str,
3747
4074
  item_name: str,
3748
- version: str = None,
4075
+ version: Optional[str] = None,
3749
4076
  tag: str = "latest",
3750
4077
  force_refresh: bool = False,
3751
4078
  ):
@@ -3775,7 +4102,7 @@ class HTTPRunDB(RunDBInterface):
3775
4102
  source_name: str,
3776
4103
  item_name: str,
3777
4104
  asset_name: str,
3778
- version: str = None,
4105
+ version: Optional[str] = None,
3779
4106
  tag: str = "latest",
3780
4107
  ):
3781
4108
  """
@@ -3897,18 +4224,27 @@ class HTTPRunDB(RunDBInterface):
3897
4224
  "operations/migrations",
3898
4225
  "Failed triggering migrations",
3899
4226
  )
3900
- if response.status_code == http.HTTPStatus.ACCEPTED:
3901
- background_task = mlrun.common.schemas.BackgroundTask(**response.json())
3902
- return self._wait_for_background_task_to_reach_terminal_state(
3903
- background_task.metadata.name
3904
- )
3905
- return None
4227
+ return self._wait_for_background_task_from_response(response)
4228
+
4229
+ def refresh_smtp_configuration(
4230
+ self,
4231
+ ) -> Optional[mlrun.common.schemas.BackgroundTask]:
4232
+ """Refresh smtp configuration and wait for the task to finish
4233
+
4234
+ :returns: :py:class:`~mlrun.common.schemas.BackgroundTask`.
4235
+ """
4236
+ response = self.api_call(
4237
+ "POST",
4238
+ "operations/refresh-smtp-configuration",
4239
+ "Failed refreshing smtp configuration",
4240
+ )
4241
+ return self._wait_for_background_task_from_response(response)
3906
4242
 
3907
4243
  def set_run_notifications(
3908
4244
  self,
3909
4245
  project: str,
3910
4246
  run_uid: str,
3911
- notifications: list[mlrun.model.Notification] = None,
4247
+ notifications: Optional[list[mlrun.model.Notification]] = None,
3912
4248
  ):
3913
4249
  """
3914
4250
  Set notifications on a run. This will override any existing notifications on the run.
@@ -3934,7 +4270,7 @@ class HTTPRunDB(RunDBInterface):
3934
4270
  self,
3935
4271
  project: str,
3936
4272
  schedule_name: str,
3937
- notifications: list[mlrun.model.Notification] = None,
4273
+ notifications: Optional[list[mlrun.model.Notification]] = None,
3938
4274
  ):
3939
4275
  """
3940
4276
  Set notifications on a schedule. This will override any existing notifications on the schedule.
@@ -3960,7 +4296,7 @@ class HTTPRunDB(RunDBInterface):
3960
4296
  self,
3961
4297
  notification_objects: list[mlrun.model.Notification],
3962
4298
  run_uid: str,
3963
- project: str = None,
4299
+ project: Optional[str] = None,
3964
4300
  mask_params: bool = True,
3965
4301
  ):
3966
4302
  """
@@ -3994,7 +4330,7 @@ class HTTPRunDB(RunDBInterface):
3994
4330
  source: Optional[str] = None,
3995
4331
  run_name: Optional[str] = None,
3996
4332
  namespace: Optional[str] = None,
3997
- notifications: list[mlrun.model.Notification] = None,
4333
+ notifications: Optional[list[mlrun.model.Notification]] = None,
3998
4334
  ) -> mlrun.common.schemas.WorkflowResponse:
3999
4335
  """
4000
4336
  Submitting workflow for a remote execution.
@@ -4216,6 +4552,7 @@ class HTTPRunDB(RunDBInterface):
4216
4552
  alert_name: str,
4217
4553
  alert_data: Union[dict, AlertConfig],
4218
4554
  project="",
4555
+ force_reset: bool = False,
4219
4556
  ) -> AlertConfig:
4220
4557
  """
4221
4558
  Create/modify an alert.
@@ -4223,6 +4560,7 @@ class HTTPRunDB(RunDBInterface):
4223
4560
  :param alert_name: The name of the alert.
4224
4561
  :param alert_data: The data of the alert.
4225
4562
  :param project: The project that the alert belongs to.
4563
+ :param force_reset: If True and the alert already exists, the alert would be reset.
4226
4564
  :returns: The created/modified alert.
4227
4565
  """
4228
4566
  if not alert_data:
@@ -4247,7 +4585,10 @@ class HTTPRunDB(RunDBInterface):
4247
4585
 
4248
4586
  alert_data = alert_instance.to_dict()
4249
4587
  body = _as_json(alert_data)
4250
- response = self.api_call("PUT", endpoint_path, error_message, body=body)
4588
+ params = {"force_reset": bool2str(force_reset)} if force_reset else {}
4589
+ response = self.api_call(
4590
+ "PUT", endpoint_path, error_message, params=params, body=body
4591
+ )
4251
4592
  return AlertConfig.from_dict(response.json())
4252
4593
 
4253
4594
  def get_alert_config(self, alert_name: str, project="") -> AlertConfig:
@@ -4334,6 +4675,413 @@ class HTTPRunDB(RunDBInterface):
4334
4675
  results.append(mlrun.common.schemas.AlertTemplate(**item))
4335
4676
  return results
4336
4677
 
4678
+ def list_alert_activations(
4679
+ self,
4680
+ project: Optional[str] = None,
4681
+ name: Optional[str] = None,
4682
+ since: Optional[datetime] = None,
4683
+ until: Optional[datetime] = None,
4684
+ entity: Optional[str] = None,
4685
+ severity: Optional[
4686
+ list[Union[mlrun.common.schemas.alert.AlertSeverity, str]]
4687
+ ] = None,
4688
+ entity_kind: Optional[
4689
+ Union[mlrun.common.schemas.alert.EventEntityKind, str]
4690
+ ] = None,
4691
+ event_kind: Optional[Union[mlrun.common.schemas.alert.EventKind, str]] = None,
4692
+ ) -> list[mlrun.common.schemas.AlertActivation]:
4693
+ """
4694
+ Retrieve a list of all alert activations.
4695
+
4696
+ :param project: The project name to filter by. If None, results are not filtered by project.
4697
+ :param name: The alert name to filter by. Supports exact matching or partial matching if prefixed with `~`.
4698
+ :param since: Filters for alert activations occurring after this timestamp.
4699
+ :param until: Filters for alert activations occurring before this timestamp.
4700
+ :param entity: The entity ID to filter by. Supports wildcard matching if prefixed with `~`.
4701
+ :param severity: A list of severity levels to filter by (e.g., ["high", "low"]).
4702
+ :param entity_kind: The kind of entity (e.g., "job", "endpoint") to filter by.
4703
+ :param event_kind: The kind of event (e.g., ""data-drift-detected"", "failed") to filter by.
4704
+
4705
+ :returns: A list of alert activations matching the provided filters.
4706
+ """
4707
+
4708
+ alert_activations, _ = self._list_alert_activations(
4709
+ project=project,
4710
+ name=name,
4711
+ since=since,
4712
+ until=until,
4713
+ entity=entity,
4714
+ severity=severity,
4715
+ entity_kind=entity_kind,
4716
+ event_kind=event_kind,
4717
+ return_all=True,
4718
+ )
4719
+ return alert_activations
4720
+
4721
+ def paginated_list_alert_activations(
4722
+ self,
4723
+ *args,
4724
+ page: Optional[int] = None,
4725
+ page_size: Optional[int] = None,
4726
+ page_token: Optional[str] = None,
4727
+ **kwargs,
4728
+ ) -> tuple[list, Optional[str]]:
4729
+ """List alerts activations with support for pagination and various filtering options.
4730
+
4731
+ This method retrieves a paginated list of alert activations based on the specified filter parameters.
4732
+ Pagination is controlled using the `page`, `page_size`, and `page_token` parameters. The method
4733
+ will return a list of alert activations that match the filtering criteria provided.
4734
+
4735
+ For detailed information about the parameters, refer to the list_alert_activations method:
4736
+ See :py:func:`~list_alert_activations` for more details.
4737
+
4738
+ Examples::
4739
+
4740
+ # Fetch first page of alert activations with page size of 5
4741
+ alert_activations, token = db.paginated_list_alert_activations(
4742
+ project="my-project", page_size=5
4743
+ )
4744
+ # Fetch next page using the pagination token from the previous response
4745
+ alert_activations, token = db.paginated_list_alert_activations(
4746
+ project="my-project", page_token=token
4747
+ )
4748
+ # Fetch alert activations for a specific page (e.g., page 3)
4749
+ alert_activations, token = db.paginated_list_alert_activations(
4750
+ project="my-project", page=3, page_size=5
4751
+ )
4752
+
4753
+ # Automatically iterate over all pages without explicitly specifying the page number
4754
+ alert_activations = []
4755
+ token = None
4756
+ while True:
4757
+ page_alert_activations, token = db.paginated_list_alert_activations(
4758
+ project="my-project", page_token=token, page_size=5
4759
+ )
4760
+ alert_activations.extend(page_alert_activations)
4761
+
4762
+ # If token is None and page_alert_activations is empty, we've reached the end (no more activations).
4763
+ # If token is None and page_alert_activations is not empty, we've fetched the last page of activations.
4764
+ if not token:
4765
+ break
4766
+ print(f"Total alert activations retrieved: {len(alert_activations)}")
4767
+
4768
+ :param page: The page number to retrieve. If not provided, the next page will be retrieved.
4769
+ :param page_size: The number of items per page to retrieve. Up to `page_size` responses are expected.
4770
+ :param page_token: A pagination token used to retrieve the next page of results. Should not be provided
4771
+ for the first request.
4772
+
4773
+ :returns: A tuple containing the list of alert activations and an optional `page_token` for pagination.
4774
+ """
4775
+ return self._list_alert_activations(
4776
+ *args,
4777
+ page=page,
4778
+ page_size=page_size,
4779
+ page_token=page_token,
4780
+ return_all=False,
4781
+ **kwargs,
4782
+ )
4783
+
4784
+ @staticmethod
4785
+ def _parse_labels(
4786
+ labels: Optional[Union[str, dict[str, Optional[str]], list[str]]],
4787
+ ):
4788
+ """
4789
+ Parse labels to support providing a dictionary from the SDK,
4790
+ which may not be directly supported in the endpoints.
4791
+
4792
+ :param labels: The labels to parse, which can be a dictionary, a list of strings,
4793
+ or a comma-separated string. This function converts them into a list
4794
+ of labels in the format 'key=value' or 'key'.
4795
+ :return: A list of parsed labels in the format 'key=value' or 'key'.
4796
+ :raises MLRunValueError: If the labels format is invalid.
4797
+ """
4798
+ try:
4799
+ return mlrun.common.schemas.common.LabelsModel(labels=labels).labels
4800
+ except pydantic.v1.error_wrappers.ValidationError as exc:
4801
+ raise mlrun.errors.MLRunValueError(
4802
+ "Invalid labels format. Must be a dictionary of strings, a list of strings, "
4803
+ "or a comma-separated string."
4804
+ ) from exc
4805
+
4806
+ def _list_artifacts(
4807
+ self,
4808
+ name: Optional[str] = None,
4809
+ project: Optional[str] = None,
4810
+ tag: Optional[str] = None,
4811
+ labels: Optional[Union[str, dict[str, Optional[str]], list[str]]] = None,
4812
+ since: Optional[datetime] = None,
4813
+ until: Optional[datetime] = None,
4814
+ iter: Optional[int] = None,
4815
+ best_iteration: bool = False,
4816
+ kind: Optional[str] = None,
4817
+ category: Union[str, mlrun.common.schemas.ArtifactCategories] = None,
4818
+ tree: Optional[str] = None,
4819
+ producer_uri: Optional[str] = None,
4820
+ format_: Optional[
4821
+ mlrun.common.formatters.ArtifactFormat
4822
+ ] = mlrun.common.formatters.ArtifactFormat.full,
4823
+ limit: Optional[int] = None,
4824
+ page: Optional[int] = None,
4825
+ page_size: Optional[int] = None,
4826
+ page_token: Optional[str] = None,
4827
+ return_all: bool = False,
4828
+ ) -> tuple[ArtifactList, Optional[str]]:
4829
+ """Handles list artifacts, both paginated and not."""
4830
+
4831
+ project = project or config.default_project
4832
+ labels = self._parse_labels(labels)
4833
+
4834
+ params = {
4835
+ "name": name,
4836
+ "tag": tag,
4837
+ "label": labels,
4838
+ "iter": iter,
4839
+ "best-iteration": best_iteration,
4840
+ "kind": kind,
4841
+ "category": category,
4842
+ "tree": tree,
4843
+ "format": format_,
4844
+ "producer_uri": producer_uri,
4845
+ "since": datetime_to_iso(since),
4846
+ "until": datetime_to_iso(until),
4847
+ "limit": limit,
4848
+ "page": page,
4849
+ "page-size": page_size,
4850
+ "page-token": page_token,
4851
+ }
4852
+
4853
+ error = "list artifacts"
4854
+ endpoint_path = f"projects/{project}/artifacts"
4855
+
4856
+ # Fetch the responses, either one page or all based on `return_all`
4857
+ responses = self.paginated_api_call(
4858
+ "GET",
4859
+ endpoint_path,
4860
+ error,
4861
+ params=params,
4862
+ version="v2",
4863
+ return_all=return_all,
4864
+ )
4865
+ paginated_responses, token = self.process_paginated_responses(
4866
+ responses, "artifacts"
4867
+ )
4868
+
4869
+ values = ArtifactList(paginated_responses)
4870
+ values.tag = tag
4871
+ return values, token
4872
+
4873
+ def _list_functions(
4874
+ self,
4875
+ name: Optional[str] = None,
4876
+ project: Optional[str] = None,
4877
+ tag: Optional[str] = None,
4878
+ kind: Optional[str] = None,
4879
+ labels: Optional[Union[str, dict[str, Optional[str]], list[str]]] = None,
4880
+ format_: Optional[str] = None,
4881
+ since: Optional[datetime] = None,
4882
+ until: Optional[datetime] = None,
4883
+ page: Optional[int] = None,
4884
+ page_size: Optional[int] = None,
4885
+ page_token: Optional[str] = None,
4886
+ return_all: bool = False,
4887
+ ) -> tuple[list, Optional[str]]:
4888
+ """Handles list functions, both paginated and not."""
4889
+
4890
+ project = project or config.default_project
4891
+ labels = self._parse_labels(labels)
4892
+ params = {
4893
+ "name": name,
4894
+ "tag": tag,
4895
+ "kind": kind,
4896
+ "label": labels,
4897
+ "since": datetime_to_iso(since),
4898
+ "until": datetime_to_iso(until),
4899
+ "format": format_,
4900
+ "page": page,
4901
+ "page-size": page_size,
4902
+ "page-token": page_token,
4903
+ }
4904
+ error = "list functions"
4905
+ path = f"projects/{project}/functions"
4906
+
4907
+ # Fetch the responses, either one page or all based on `return_all`
4908
+ responses = self.paginated_api_call(
4909
+ "GET", path, error, params=params, return_all=return_all
4910
+ )
4911
+ paginated_responses, token = self.process_paginated_responses(
4912
+ responses, "funcs"
4913
+ )
4914
+ return paginated_responses, token
4915
+
4916
+ def _list_runs(
4917
+ self,
4918
+ name: Optional[str] = None,
4919
+ uid: Optional[Union[str, list[str]]] = None,
4920
+ project: Optional[str] = None,
4921
+ labels: Optional[Union[str, dict[str, Optional[str]], list[str]]] = None,
4922
+ state: Optional[
4923
+ mlrun.common.runtimes.constants.RunStates
4924
+ ] = None, # Backward compatibility
4925
+ states: typing.Optional[list[mlrun.common.runtimes.constants.RunStates]] = None,
4926
+ sort: bool = True,
4927
+ last: int = 0,
4928
+ iter: bool = False,
4929
+ start_time_from: Optional[datetime] = None,
4930
+ start_time_to: Optional[datetime] = None,
4931
+ last_update_time_from: Optional[datetime] = None,
4932
+ last_update_time_to: Optional[datetime] = None,
4933
+ partition_by: Optional[
4934
+ Union[mlrun.common.schemas.RunPartitionByField, str]
4935
+ ] = None,
4936
+ rows_per_partition: int = 1,
4937
+ partition_sort_by: Optional[Union[mlrun.common.schemas.SortField, str]] = None,
4938
+ partition_order: Union[
4939
+ mlrun.common.schemas.OrderType, str
4940
+ ] = mlrun.common.schemas.OrderType.desc,
4941
+ max_partitions: int = 0,
4942
+ with_notifications: bool = False,
4943
+ page: Optional[int] = None,
4944
+ page_size: Optional[int] = None,
4945
+ page_token: Optional[str] = None,
4946
+ return_all: bool = False,
4947
+ ) -> tuple[RunList, Optional[str]]:
4948
+ """Handles list runs, both paginated and not."""
4949
+
4950
+ project = project or config.default_project
4951
+ if with_notifications:
4952
+ logger.warning(
4953
+ "Local run notifications are not persisted in the DB, therefore local runs will not be returned when "
4954
+ "using the `with_notifications` flag."
4955
+ )
4956
+
4957
+ if last:
4958
+ # TODO: Remove this in 1.8.0
4959
+ warnings.warn(
4960
+ "'last' is deprecated and will be removed in 1.8.0.",
4961
+ FutureWarning,
4962
+ )
4963
+
4964
+ if state:
4965
+ # TODO: Remove this in 1.9.0
4966
+ warnings.warn(
4967
+ "'state' is deprecated and will be removed in 1.9.0. Use 'states' instead.",
4968
+ FutureWarning,
4969
+ )
4970
+
4971
+ labels = self._parse_labels(labels)
4972
+
4973
+ if (
4974
+ not name
4975
+ and not uid
4976
+ and not labels
4977
+ and not state
4978
+ and not states
4979
+ and not last
4980
+ and not start_time_from
4981
+ and not start_time_to
4982
+ and not last_update_time_from
4983
+ and not last_update_time_to
4984
+ and not partition_by
4985
+ and not partition_sort_by
4986
+ and not iter
4987
+ ):
4988
+ # default to last week on no filter
4989
+ start_time_from = datetime.now() - timedelta(days=7)
4990
+ partition_by = mlrun.common.schemas.RunPartitionByField.project_and_name
4991
+ partition_sort_by = mlrun.common.schemas.SortField.updated
4992
+
4993
+ params = {
4994
+ "name": name,
4995
+ "uid": uid,
4996
+ "label": labels,
4997
+ "state": mlrun.utils.helpers.as_list(state)
4998
+ if state is not None
4999
+ else states or None,
5000
+ "sort": bool2str(sort),
5001
+ "iter": bool2str(iter),
5002
+ "start_time_from": datetime_to_iso(start_time_from),
5003
+ "start_time_to": datetime_to_iso(start_time_to),
5004
+ "last_update_time_from": datetime_to_iso(last_update_time_from),
5005
+ "last_update_time_to": datetime_to_iso(last_update_time_to),
5006
+ "with-notifications": with_notifications,
5007
+ "page": page,
5008
+ "page-size": page_size,
5009
+ "page-token": page_token,
5010
+ }
5011
+
5012
+ if partition_by:
5013
+ params.update(
5014
+ self._generate_partition_by_params(
5015
+ mlrun.common.schemas.RunPartitionByField,
5016
+ partition_by,
5017
+ rows_per_partition,
5018
+ partition_sort_by,
5019
+ partition_order,
5020
+ max_partitions,
5021
+ )
5022
+ )
5023
+ error = "list runs"
5024
+ _path = self._path_of("runs", project)
5025
+
5026
+ # Fetch the responses, either one page or all based on `return_all`
5027
+ responses = self.paginated_api_call(
5028
+ "GET", _path, error, params=params, return_all=return_all
5029
+ )
5030
+ paginated_responses, token = self.process_paginated_responses(responses, "runs")
5031
+ return RunList(paginated_responses), token
5032
+
5033
+ def _list_alert_activations(
5034
+ self,
5035
+ project: Optional[str] = None,
5036
+ name: Optional[str] = None,
5037
+ since: Optional[datetime] = None,
5038
+ until: Optional[datetime] = None,
5039
+ entity: Optional[str] = None,
5040
+ severity: Optional[
5041
+ list[Union[mlrun.common.schemas.alert.AlertSeverity, str]]
5042
+ ] = None,
5043
+ entity_kind: Optional[
5044
+ Union[mlrun.common.schemas.alert.EventEntityKind, str]
5045
+ ] = None,
5046
+ event_kind: Optional[Union[mlrun.common.schemas.alert.EventKind, str]] = None,
5047
+ page: Optional[int] = None,
5048
+ page_size: Optional[int] = None,
5049
+ page_token: Optional[str] = None,
5050
+ return_all: bool = False,
5051
+ ) -> tuple[list[mlrun.common.schemas.AlertActivation], Optional[str]]:
5052
+ project = project or config.default_project
5053
+ params = {
5054
+ "name": name,
5055
+ "since": datetime_to_iso(since),
5056
+ "until": datetime_to_iso(until),
5057
+ "entity": entity,
5058
+ "severity": severity,
5059
+ "entity-kind": entity_kind,
5060
+ "event-kind": event_kind,
5061
+ "page": page,
5062
+ "page-size": page_size,
5063
+ "page-token": page_token,
5064
+ }
5065
+ error = "list alert activations"
5066
+ path = f"projects/{project}/alert-activations"
5067
+
5068
+ # Fetch the responses, either one page or all based on `return_all`
5069
+ responses = self.paginated_api_call(
5070
+ "GET", path, error, params=params, return_all=return_all
5071
+ )
5072
+ paginated_responses, token = self.process_paginated_responses(
5073
+ responses, "activations"
5074
+ )
5075
+ return paginated_responses, token
5076
+
5077
+ def _wait_for_background_task_from_response(self, response):
5078
+ if response.status_code == http.HTTPStatus.ACCEPTED:
5079
+ background_task = mlrun.common.schemas.BackgroundTask(**response.json())
5080
+ return self._wait_for_background_task_to_reach_terminal_state(
5081
+ background_task.metadata.name
5082
+ )
5083
+ return None
5084
+
4337
5085
 
4338
5086
  def _as_json(obj):
4339
5087
  fn = getattr(obj, "to_json", None)