mlrun 1.6.4rc2__py3-none-any.whl → 1.7.0rc20__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 (291) hide show
  1. mlrun/__init__.py +11 -1
  2. mlrun/__main__.py +26 -112
  3. mlrun/alerts/__init__.py +15 -0
  4. mlrun/alerts/alert.py +144 -0
  5. mlrun/api/schemas/__init__.py +5 -4
  6. mlrun/artifacts/__init__.py +8 -3
  7. mlrun/artifacts/base.py +46 -257
  8. mlrun/artifacts/dataset.py +11 -192
  9. mlrun/artifacts/manager.py +47 -48
  10. mlrun/artifacts/model.py +31 -159
  11. mlrun/artifacts/plots.py +23 -380
  12. mlrun/common/constants.py +69 -0
  13. mlrun/common/db/sql_session.py +2 -3
  14. mlrun/common/formatters/__init__.py +19 -0
  15. mlrun/common/formatters/artifact.py +21 -0
  16. mlrun/common/formatters/base.py +78 -0
  17. mlrun/common/formatters/function.py +41 -0
  18. mlrun/common/formatters/pipeline.py +53 -0
  19. mlrun/common/formatters/project.py +51 -0
  20. mlrun/common/helpers.py +1 -2
  21. mlrun/common/model_monitoring/helpers.py +9 -5
  22. mlrun/{runtimes → common/runtimes}/constants.py +37 -9
  23. mlrun/common/schemas/__init__.py +24 -4
  24. mlrun/common/schemas/alert.py +203 -0
  25. mlrun/common/schemas/api_gateway.py +148 -0
  26. mlrun/common/schemas/artifact.py +18 -8
  27. mlrun/common/schemas/auth.py +11 -5
  28. mlrun/common/schemas/background_task.py +1 -1
  29. mlrun/common/schemas/client_spec.py +4 -1
  30. mlrun/common/schemas/feature_store.py +16 -16
  31. mlrun/common/schemas/frontend_spec.py +8 -7
  32. mlrun/common/schemas/function.py +5 -1
  33. mlrun/common/schemas/hub.py +11 -18
  34. mlrun/common/schemas/memory_reports.py +2 -2
  35. mlrun/common/schemas/model_monitoring/__init__.py +18 -3
  36. mlrun/common/schemas/model_monitoring/constants.py +83 -26
  37. mlrun/common/schemas/model_monitoring/grafana.py +13 -9
  38. mlrun/common/schemas/model_monitoring/model_endpoints.py +99 -16
  39. mlrun/common/schemas/notification.py +4 -4
  40. mlrun/common/schemas/object.py +2 -2
  41. mlrun/{runtimes/mpijob/v1alpha1.py → common/schemas/pagination.py} +10 -13
  42. mlrun/common/schemas/pipeline.py +1 -10
  43. mlrun/common/schemas/project.py +24 -23
  44. mlrun/common/schemas/runtime_resource.py +8 -12
  45. mlrun/common/schemas/schedule.py +3 -3
  46. mlrun/common/schemas/tag.py +1 -2
  47. mlrun/common/schemas/workflow.py +2 -2
  48. mlrun/common/types.py +7 -1
  49. mlrun/config.py +54 -17
  50. mlrun/data_types/to_pandas.py +10 -12
  51. mlrun/datastore/__init__.py +5 -8
  52. mlrun/datastore/alibaba_oss.py +130 -0
  53. mlrun/datastore/azure_blob.py +17 -5
  54. mlrun/datastore/base.py +62 -39
  55. mlrun/datastore/datastore.py +28 -9
  56. mlrun/datastore/datastore_profile.py +146 -20
  57. mlrun/datastore/filestore.py +0 -1
  58. mlrun/datastore/google_cloud_storage.py +6 -2
  59. mlrun/datastore/hdfs.py +56 -0
  60. mlrun/datastore/inmem.py +2 -2
  61. mlrun/datastore/redis.py +6 -2
  62. mlrun/datastore/s3.py +9 -0
  63. mlrun/datastore/snowflake_utils.py +43 -0
  64. mlrun/datastore/sources.py +201 -96
  65. mlrun/datastore/spark_utils.py +1 -2
  66. mlrun/datastore/store_resources.py +7 -7
  67. mlrun/datastore/targets.py +358 -104
  68. mlrun/datastore/utils.py +72 -58
  69. mlrun/datastore/v3io.py +5 -1
  70. mlrun/db/base.py +185 -35
  71. mlrun/db/factory.py +1 -1
  72. mlrun/db/httpdb.py +614 -179
  73. mlrun/db/nopdb.py +210 -26
  74. mlrun/errors.py +12 -1
  75. mlrun/execution.py +41 -24
  76. mlrun/feature_store/__init__.py +0 -2
  77. mlrun/feature_store/api.py +40 -72
  78. mlrun/feature_store/common.py +1 -1
  79. mlrun/feature_store/feature_set.py +76 -55
  80. mlrun/feature_store/feature_vector.py +28 -30
  81. mlrun/feature_store/ingestion.py +7 -6
  82. mlrun/feature_store/retrieval/base.py +16 -11
  83. mlrun/feature_store/retrieval/conversion.py +11 -13
  84. mlrun/feature_store/retrieval/dask_merger.py +2 -0
  85. mlrun/feature_store/retrieval/job.py +9 -3
  86. mlrun/feature_store/retrieval/local_merger.py +2 -0
  87. mlrun/feature_store/retrieval/spark_merger.py +34 -24
  88. mlrun/feature_store/steps.py +37 -34
  89. mlrun/features.py +9 -20
  90. mlrun/frameworks/_common/artifacts_library.py +9 -9
  91. mlrun/frameworks/_common/mlrun_interface.py +5 -5
  92. mlrun/frameworks/_common/model_handler.py +48 -48
  93. mlrun/frameworks/_common/plan.py +2 -3
  94. mlrun/frameworks/_common/producer.py +3 -4
  95. mlrun/frameworks/_common/utils.py +5 -5
  96. mlrun/frameworks/_dl_common/loggers/logger.py +6 -7
  97. mlrun/frameworks/_dl_common/loggers/mlrun_logger.py +9 -9
  98. mlrun/frameworks/_dl_common/loggers/tensorboard_logger.py +23 -47
  99. mlrun/frameworks/_ml_common/artifacts_library.py +1 -2
  100. mlrun/frameworks/_ml_common/loggers/logger.py +3 -4
  101. mlrun/frameworks/_ml_common/loggers/mlrun_logger.py +4 -5
  102. mlrun/frameworks/_ml_common/model_handler.py +24 -24
  103. mlrun/frameworks/_ml_common/pkl_model_server.py +2 -2
  104. mlrun/frameworks/_ml_common/plan.py +1 -1
  105. mlrun/frameworks/_ml_common/plans/calibration_curve_plan.py +2 -3
  106. mlrun/frameworks/_ml_common/plans/confusion_matrix_plan.py +2 -3
  107. mlrun/frameworks/_ml_common/plans/dataset_plan.py +3 -3
  108. mlrun/frameworks/_ml_common/plans/feature_importance_plan.py +3 -3
  109. mlrun/frameworks/_ml_common/plans/roc_curve_plan.py +4 -4
  110. mlrun/frameworks/_ml_common/utils.py +4 -4
  111. mlrun/frameworks/auto_mlrun/auto_mlrun.py +9 -9
  112. mlrun/frameworks/huggingface/model_server.py +4 -4
  113. mlrun/frameworks/lgbm/__init__.py +33 -33
  114. mlrun/frameworks/lgbm/callbacks/callback.py +2 -4
  115. mlrun/frameworks/lgbm/callbacks/logging_callback.py +4 -5
  116. mlrun/frameworks/lgbm/callbacks/mlrun_logging_callback.py +4 -5
  117. mlrun/frameworks/lgbm/mlrun_interfaces/booster_mlrun_interface.py +1 -3
  118. mlrun/frameworks/lgbm/mlrun_interfaces/mlrun_interface.py +6 -6
  119. mlrun/frameworks/lgbm/model_handler.py +10 -10
  120. mlrun/frameworks/lgbm/model_server.py +6 -6
  121. mlrun/frameworks/lgbm/utils.py +5 -5
  122. mlrun/frameworks/onnx/dataset.py +8 -8
  123. mlrun/frameworks/onnx/mlrun_interface.py +3 -3
  124. mlrun/frameworks/onnx/model_handler.py +6 -6
  125. mlrun/frameworks/onnx/model_server.py +7 -7
  126. mlrun/frameworks/parallel_coordinates.py +4 -3
  127. mlrun/frameworks/pytorch/__init__.py +18 -18
  128. mlrun/frameworks/pytorch/callbacks/callback.py +4 -5
  129. mlrun/frameworks/pytorch/callbacks/logging_callback.py +17 -17
  130. mlrun/frameworks/pytorch/callbacks/mlrun_logging_callback.py +11 -11
  131. mlrun/frameworks/pytorch/callbacks/tensorboard_logging_callback.py +23 -29
  132. mlrun/frameworks/pytorch/callbacks_handler.py +38 -38
  133. mlrun/frameworks/pytorch/mlrun_interface.py +20 -20
  134. mlrun/frameworks/pytorch/model_handler.py +17 -17
  135. mlrun/frameworks/pytorch/model_server.py +7 -7
  136. mlrun/frameworks/sklearn/__init__.py +13 -13
  137. mlrun/frameworks/sklearn/estimator.py +4 -4
  138. mlrun/frameworks/sklearn/metrics_library.py +14 -14
  139. mlrun/frameworks/sklearn/mlrun_interface.py +3 -6
  140. mlrun/frameworks/sklearn/model_handler.py +2 -2
  141. mlrun/frameworks/tf_keras/__init__.py +10 -7
  142. mlrun/frameworks/tf_keras/callbacks/logging_callback.py +15 -15
  143. mlrun/frameworks/tf_keras/callbacks/mlrun_logging_callback.py +11 -11
  144. mlrun/frameworks/tf_keras/callbacks/tensorboard_logging_callback.py +19 -23
  145. mlrun/frameworks/tf_keras/mlrun_interface.py +9 -11
  146. mlrun/frameworks/tf_keras/model_handler.py +14 -14
  147. mlrun/frameworks/tf_keras/model_server.py +6 -6
  148. mlrun/frameworks/xgboost/__init__.py +13 -13
  149. mlrun/frameworks/xgboost/model_handler.py +6 -6
  150. mlrun/k8s_utils.py +14 -16
  151. mlrun/launcher/__init__.py +1 -1
  152. mlrun/launcher/base.py +16 -15
  153. mlrun/launcher/client.py +8 -6
  154. mlrun/launcher/factory.py +1 -1
  155. mlrun/launcher/local.py +17 -11
  156. mlrun/launcher/remote.py +16 -10
  157. mlrun/lists.py +7 -6
  158. mlrun/model.py +238 -73
  159. mlrun/model_monitoring/__init__.py +1 -1
  160. mlrun/model_monitoring/api.py +138 -315
  161. mlrun/model_monitoring/application.py +5 -296
  162. mlrun/model_monitoring/applications/__init__.py +24 -0
  163. mlrun/model_monitoring/applications/_application_steps.py +157 -0
  164. mlrun/model_monitoring/applications/base.py +282 -0
  165. mlrun/model_monitoring/applications/context.py +214 -0
  166. mlrun/model_monitoring/applications/evidently_base.py +211 -0
  167. mlrun/model_monitoring/applications/histogram_data_drift.py +349 -0
  168. mlrun/model_monitoring/applications/results.py +99 -0
  169. mlrun/model_monitoring/controller.py +104 -84
  170. mlrun/model_monitoring/controller_handler.py +13 -5
  171. mlrun/model_monitoring/db/__init__.py +18 -0
  172. mlrun/model_monitoring/{stores → db/stores}/__init__.py +43 -36
  173. mlrun/model_monitoring/db/stores/base/__init__.py +15 -0
  174. mlrun/model_monitoring/{stores/model_endpoint_store.py → db/stores/base/store.py} +64 -40
  175. mlrun/model_monitoring/db/stores/sqldb/__init__.py +13 -0
  176. mlrun/model_monitoring/db/stores/sqldb/models/__init__.py +71 -0
  177. mlrun/model_monitoring/{stores → db/stores/sqldb}/models/base.py +109 -5
  178. mlrun/model_monitoring/db/stores/sqldb/models/mysql.py +88 -0
  179. mlrun/model_monitoring/{stores/models/mysql.py → db/stores/sqldb/models/sqlite.py} +19 -13
  180. mlrun/model_monitoring/db/stores/sqldb/sql_store.py +684 -0
  181. mlrun/model_monitoring/db/stores/v3io_kv/__init__.py +13 -0
  182. mlrun/model_monitoring/{stores/kv_model_endpoint_store.py → db/stores/v3io_kv/kv_store.py} +310 -165
  183. mlrun/model_monitoring/db/tsdb/__init__.py +100 -0
  184. mlrun/model_monitoring/db/tsdb/base.py +329 -0
  185. mlrun/model_monitoring/db/tsdb/helpers.py +30 -0
  186. mlrun/model_monitoring/db/tsdb/tdengine/__init__.py +15 -0
  187. mlrun/model_monitoring/db/tsdb/tdengine/schemas.py +240 -0
  188. mlrun/model_monitoring/db/tsdb/tdengine/stream_graph_steps.py +45 -0
  189. mlrun/model_monitoring/db/tsdb/tdengine/tdengine_connector.py +397 -0
  190. mlrun/model_monitoring/db/tsdb/v3io/__init__.py +15 -0
  191. mlrun/model_monitoring/db/tsdb/v3io/stream_graph_steps.py +117 -0
  192. mlrun/model_monitoring/db/tsdb/v3io/v3io_connector.py +630 -0
  193. mlrun/model_monitoring/evidently_application.py +6 -118
  194. mlrun/model_monitoring/features_drift_table.py +134 -106
  195. mlrun/model_monitoring/helpers.py +127 -28
  196. mlrun/model_monitoring/metrics/__init__.py +13 -0
  197. mlrun/model_monitoring/metrics/histogram_distance.py +127 -0
  198. mlrun/model_monitoring/model_endpoint.py +3 -2
  199. mlrun/model_monitoring/prometheus.py +1 -4
  200. mlrun/model_monitoring/stream_processing.py +62 -231
  201. mlrun/model_monitoring/tracking_policy.py +9 -2
  202. mlrun/model_monitoring/writer.py +152 -124
  203. mlrun/package/__init__.py +6 -6
  204. mlrun/package/context_handler.py +5 -5
  205. mlrun/package/packager.py +7 -7
  206. mlrun/package/packagers/default_packager.py +6 -6
  207. mlrun/package/packagers/numpy_packagers.py +15 -15
  208. mlrun/package/packagers/pandas_packagers.py +5 -5
  209. mlrun/package/packagers/python_standard_library_packagers.py +10 -10
  210. mlrun/package/packagers_manager.py +19 -23
  211. mlrun/package/utils/_formatter.py +6 -6
  212. mlrun/package/utils/_pickler.py +2 -2
  213. mlrun/package/utils/_supported_format.py +4 -4
  214. mlrun/package/utils/log_hint_utils.py +2 -2
  215. mlrun/package/utils/type_hint_utils.py +4 -9
  216. mlrun/platforms/__init__.py +11 -10
  217. mlrun/platforms/iguazio.py +24 -203
  218. mlrun/projects/operations.py +35 -21
  219. mlrun/projects/pipelines.py +68 -99
  220. mlrun/projects/project.py +830 -266
  221. mlrun/render.py +3 -11
  222. mlrun/run.py +162 -166
  223. mlrun/runtimes/__init__.py +62 -7
  224. mlrun/runtimes/base.py +39 -32
  225. mlrun/runtimes/daskjob.py +8 -8
  226. mlrun/runtimes/databricks_job/databricks_cancel_task.py +1 -1
  227. mlrun/runtimes/databricks_job/databricks_runtime.py +7 -7
  228. mlrun/runtimes/databricks_job/databricks_wrapper.py +1 -1
  229. mlrun/runtimes/funcdoc.py +0 -28
  230. mlrun/runtimes/function_reference.py +1 -1
  231. mlrun/runtimes/kubejob.py +28 -122
  232. mlrun/runtimes/local.py +6 -3
  233. mlrun/runtimes/mpijob/__init__.py +0 -20
  234. mlrun/runtimes/mpijob/abstract.py +9 -10
  235. mlrun/runtimes/mpijob/v1.py +1 -1
  236. mlrun/{model_monitoring/stores/models/sqlite.py → runtimes/nuclio/__init__.py} +7 -9
  237. mlrun/runtimes/nuclio/api_gateway.py +709 -0
  238. mlrun/runtimes/nuclio/application/__init__.py +15 -0
  239. mlrun/runtimes/nuclio/application/application.py +523 -0
  240. mlrun/runtimes/nuclio/application/reverse_proxy.go +95 -0
  241. mlrun/runtimes/{function.py → nuclio/function.py} +112 -73
  242. mlrun/runtimes/{nuclio.py → nuclio/nuclio.py} +6 -6
  243. mlrun/runtimes/{serving.py → nuclio/serving.py} +45 -51
  244. mlrun/runtimes/pod.py +286 -88
  245. mlrun/runtimes/remotesparkjob.py +2 -2
  246. mlrun/runtimes/sparkjob/spark3job.py +51 -34
  247. mlrun/runtimes/utils.py +7 -75
  248. mlrun/secrets.py +9 -5
  249. mlrun/serving/remote.py +2 -7
  250. mlrun/serving/routers.py +13 -10
  251. mlrun/serving/server.py +22 -26
  252. mlrun/serving/states.py +99 -25
  253. mlrun/serving/utils.py +3 -3
  254. mlrun/serving/v1_serving.py +6 -7
  255. mlrun/serving/v2_serving.py +59 -20
  256. mlrun/track/tracker.py +2 -1
  257. mlrun/track/tracker_manager.py +3 -3
  258. mlrun/track/trackers/mlflow_tracker.py +1 -2
  259. mlrun/utils/async_http.py +5 -7
  260. mlrun/utils/azure_vault.py +1 -1
  261. mlrun/utils/clones.py +1 -2
  262. mlrun/utils/condition_evaluator.py +3 -3
  263. mlrun/utils/db.py +3 -3
  264. mlrun/utils/helpers.py +183 -197
  265. mlrun/utils/http.py +2 -5
  266. mlrun/utils/logger.py +76 -14
  267. mlrun/utils/notifications/notification/__init__.py +17 -12
  268. mlrun/utils/notifications/notification/base.py +14 -2
  269. mlrun/utils/notifications/notification/console.py +2 -0
  270. mlrun/utils/notifications/notification/git.py +3 -1
  271. mlrun/utils/notifications/notification/ipython.py +3 -1
  272. mlrun/utils/notifications/notification/slack.py +101 -21
  273. mlrun/utils/notifications/notification/webhook.py +11 -1
  274. mlrun/utils/notifications/notification_pusher.py +155 -30
  275. mlrun/utils/retryer.py +208 -0
  276. mlrun/utils/singleton.py +1 -1
  277. mlrun/utils/v3io_clients.py +2 -4
  278. mlrun/utils/version/version.json +2 -2
  279. mlrun/utils/version/version.py +2 -6
  280. {mlrun-1.6.4rc2.dist-info → mlrun-1.7.0rc20.dist-info}/METADATA +31 -19
  281. mlrun-1.7.0rc20.dist-info/RECORD +353 -0
  282. mlrun/kfpops.py +0 -868
  283. mlrun/model_monitoring/batch.py +0 -1095
  284. mlrun/model_monitoring/stores/models/__init__.py +0 -27
  285. mlrun/model_monitoring/stores/sql_model_endpoint_store.py +0 -384
  286. mlrun/platforms/other.py +0 -306
  287. mlrun-1.6.4rc2.dist-info/RECORD +0 -314
  288. {mlrun-1.6.4rc2.dist-info → mlrun-1.7.0rc20.dist-info}/LICENSE +0 -0
  289. {mlrun-1.6.4rc2.dist-info → mlrun-1.7.0rc20.dist-info}/WHEEL +0 -0
  290. {mlrun-1.6.4rc2.dist-info → mlrun-1.7.0rc20.dist-info}/entry_points.txt +0 -0
  291. {mlrun-1.6.4rc2.dist-info → mlrun-1.7.0rc20.dist-info}/top_level.txt +0 -0
@@ -15,10 +15,17 @@
15
15
  import asyncio
16
16
  import datetime
17
17
  import os
18
+ import re
18
19
  import traceback
19
20
  import typing
20
21
  from concurrent.futures import ThreadPoolExecutor
21
22
 
23
+ import kfp
24
+ import mlrun_pipelines.common.ops
25
+ import mlrun_pipelines.models
26
+
27
+ import mlrun.common.constants as mlrun_constants
28
+ import mlrun.common.runtimes.constants
22
29
  import mlrun.common.schemas
23
30
  import mlrun.config
24
31
  import mlrun.db.base
@@ -32,7 +39,7 @@ from mlrun.utils.condition_evaluator import evaluate_condition_in_separate_proce
32
39
  from .notification import NotificationBase, NotificationTypes
33
40
 
34
41
 
35
- class _NotificationPusherBase(object):
42
+ class _NotificationPusherBase:
36
43
  def _push(
37
44
  self, sync_push_callback: typing.Callable, async_push_callback: typing.Callable
38
45
  ):
@@ -95,15 +102,11 @@ class NotificationPusher(_NotificationPusherBase):
95
102
 
96
103
  def __init__(self, runs: typing.Union[mlrun.lists.RunList, list]):
97
104
  self._runs = runs
98
- self._sync_notifications: typing.List[
99
- typing.Tuple[
100
- NotificationBase, mlrun.model.RunObject, mlrun.model.Notification
101
- ]
105
+ self._sync_notifications: list[
106
+ tuple[NotificationBase, mlrun.model.RunObject, mlrun.model.Notification]
102
107
  ] = []
103
- self._async_notifications: typing.List[
104
- typing.Tuple[
105
- NotificationBase, mlrun.model.RunObject, mlrun.model.Notification
106
- ]
108
+ self._async_notifications: list[
109
+ tuple[NotificationBase, mlrun.model.RunObject, mlrun.model.Notification]
107
110
  ] = []
108
111
 
109
112
  for run in self._runs:
@@ -237,25 +240,12 @@ class NotificationPusher(_NotificationPusherBase):
237
240
  resource = "Run"
238
241
  runs = [run.to_dict()]
239
242
 
240
- if "workflow" in run.metadata.labels:
241
- resource = "Workflow"
243
+ if mlrun_constants.MLRunInternalLabels.workflow in run.metadata.labels:
244
+ resource = mlrun_constants.MLRunInternalLabels.workflow
242
245
  custom_message = (
243
246
  f" (workflow: {run.metadata.labels['workflow']}){custom_message}"
244
247
  )
245
- db = mlrun.get_run_db()
246
-
247
- workflow_id = run.status.results.get("workflow_id", None)
248
- if workflow_id:
249
- workflow_runs = db.list_runs(
250
- project=run.metadata.project,
251
- labels=f"workflow={workflow_id}",
252
- )
253
- logger.debug(
254
- "Found workflow runs, extending notification runs",
255
- workflow_id=workflow_id,
256
- workflow_runs_amount=len(workflow_runs),
257
- )
258
- runs.extend(workflow_runs)
248
+ runs.extend(self.get_workflow_steps(run))
259
249
 
260
250
  message = (
261
251
  self.messages.get(run.state(), "").format(resource=resource)
@@ -399,9 +389,140 @@ class NotificationPusher(_NotificationPusherBase):
399
389
  mask_params=False,
400
390
  )
401
391
 
392
+ def get_workflow_steps(self, run: mlrun.model.RunObject) -> list:
393
+ steps = []
394
+ db = mlrun.get_run_db()
395
+
396
+ def _add_run_step(_step: mlrun_pipelines.models.PipelineStep):
397
+ try:
398
+ _run = db.list_runs(
399
+ project=run.metadata.project,
400
+ labels=f"mlrun_constants.MLRunInternalLabels.runner_pod={_step.node_name}",
401
+ )[0]
402
+ except IndexError:
403
+ _run = {
404
+ "metadata": {
405
+ "name": _step.display_name,
406
+ "project": run.metadata.project,
407
+ },
408
+ }
409
+ _run["step_kind"] = _step.step_type
410
+ if _step.skipped:
411
+ _run.setdefault("status", {})["state"] = (
412
+ mlrun.common.runtimes.constants.RunStates.skipped
413
+ )
414
+ steps.append(_run)
415
+
416
+ def _add_deploy_function_step(_step: mlrun_pipelines.models.PipelineStep):
417
+ project, name, hash_key = self._extract_function_uri(
418
+ _step.get_annotation("mlrun/function-uri")
419
+ )
420
+ if name:
421
+ try:
422
+ function = db.get_function(
423
+ project=project, name=name, hash_key=hash_key
424
+ )
425
+ except mlrun.errors.MLRunNotFoundError:
426
+ # If the function is not found (if build failed for example), we will create a dummy
427
+ # function object for the notification to display the function name
428
+ function = {
429
+ "metadata": {
430
+ "name": name,
431
+ "project": project,
432
+ "hash_key": hash_key,
433
+ },
434
+ }
435
+ pod_phase = _step.phase
436
+ if _step.skipped:
437
+ state = mlrun.common.schemas.FunctionState.skipped
438
+ else:
439
+ state = mlrun.common.runtimes.constants.PodPhases.pod_phase_to_run_state(
440
+ pod_phase
441
+ )
442
+ function["status"] = {"state": state}
443
+ if isinstance(function["metadata"].get("updated"), datetime.datetime):
444
+ function["metadata"]["updated"] = function["metadata"][
445
+ "updated"
446
+ ].isoformat()
447
+ function["step_kind"] = _step.step_type
448
+ steps.append(function)
449
+
450
+ step_methods = {
451
+ mlrun_pipelines.common.ops.PipelineRunType.run: _add_run_step,
452
+ mlrun_pipelines.common.ops.PipelineRunType.build: _add_deploy_function_step,
453
+ mlrun_pipelines.common.ops.PipelineRunType.deploy: _add_deploy_function_step,
454
+ }
455
+
456
+ workflow_id = run.status.results.get("workflow_id", None)
457
+ if not workflow_id:
458
+ return steps
459
+
460
+ workflow_manifest = self._get_workflow_manifest(workflow_id)
461
+ if not workflow_manifest:
462
+ return steps
463
+
464
+ try:
465
+ for step in workflow_manifest.get_steps():
466
+ step_method = step_methods.get(step.step_type)
467
+ if step_method:
468
+ step_method(step)
469
+ return steps
470
+ except Exception:
471
+ # If we fail to read the pipeline steps, we will return the list of runs that have the same workflow id
472
+ logger.warning(
473
+ "Failed to extract workflow steps from workflow manifest, "
474
+ "returning all runs with the workflow id label",
475
+ workflow_id=workflow_id,
476
+ traceback=traceback.format_exc(),
477
+ )
478
+ return db.list_runs(
479
+ project=run.metadata.project,
480
+ labels=f"workflow={workflow_id}",
481
+ )
482
+
483
+ @staticmethod
484
+ def _get_workflow_manifest(
485
+ workflow_id: str,
486
+ ) -> typing.Optional[mlrun_pipelines.models.PipelineManifest]:
487
+ kfp_url = mlrun.mlconf.resolve_kfp_url(mlrun.mlconf.namespace)
488
+ if not kfp_url:
489
+ raise mlrun.errors.MLRunNotFoundError(
490
+ "KubeFlow Pipelines is not configured"
491
+ )
492
+
493
+ kfp_client = kfp.Client(host=kfp_url)
494
+
495
+ # arbitrary timeout of 5 seconds, the workflow should be done by now
496
+ kfp_run = kfp_client.wait_for_run_completion(workflow_id, 5)
497
+ if not kfp_run:
498
+ return None
499
+
500
+ kfp_run = mlrun_pipelines.models.PipelineRun(kfp_run)
501
+ return kfp_run.workflow_manifest()
502
+
503
+ def _extract_function_uri(self, function_uri: str) -> tuple[str, str, str]:
504
+ """
505
+ Extract the project, name, and hash key from a function uri.
506
+ Examples:
507
+ - "project/name@hash_key" returns project, name, hash_key
508
+ - "project/name returns" project, name, ""
509
+ """
510
+ project, name, hash_key = None, None, None
511
+ hashed_pattern = r"^(.+)/(.+)@(.+)$"
512
+ pattern = r"^(.+)/(.+)$"
513
+ match = re.match(hashed_pattern, function_uri)
514
+ if match:
515
+ project, name, hash_key = match.groups()
516
+ else:
517
+ match = re.match(pattern, function_uri)
518
+ if match:
519
+ project, name = match.groups()
520
+ hash_key = ""
521
+ return project, name, hash_key
522
+
402
523
 
403
524
  class CustomNotificationPusher(_NotificationPusherBase):
404
- def __init__(self, notification_types: typing.List[str] = None):
525
+ def __init__(self, notification_types: list[str] = None):
405
526
  notifications = {
406
527
  notification_type: NotificationTypes(notification_type).get_notification()()
407
528
  for notification_type in notification_types
@@ -417,6 +538,12 @@ class CustomNotificationPusher(_NotificationPusherBase):
417
538
  if notification.is_async
418
539
  }
419
540
 
541
+ @property
542
+ def notifications(self):
543
+ notifications = self._sync_notifications.copy()
544
+ notifications.update(self._async_notifications)
545
+ return notifications
546
+
420
547
  def push(
421
548
  self,
422
549
  message: str,
@@ -446,7 +573,7 @@ class CustomNotificationPusher(_NotificationPusherBase):
446
573
  def add_notification(
447
574
  self,
448
575
  notification_type: str,
449
- params: typing.Dict[str, str] = None,
576
+ params: dict[str, str] = None,
450
577
  ):
451
578
  if notification_type in self._async_notifications:
452
579
  self._async_notifications[notification_type].load_notification(params)
@@ -471,9 +598,7 @@ class CustomNotificationPusher(_NotificationPusherBase):
471
598
  else:
472
599
  logger.warning(f"No notification of type {notification_type} in project")
473
600
 
474
- def edit_notification(
475
- self, notification_type: str, params: typing.Dict[str, str] = None
476
- ):
601
+ def edit_notification(self, notification_type: str, params: dict[str, str] = None):
477
602
  self.remove_notification(notification_type)
478
603
  self.add_notification(notification_type, params)
479
604
 
mlrun/utils/retryer.py ADDED
@@ -0,0 +1,208 @@
1
+ # Copyright 2023 Iguazio
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ import asyncio
16
+ import time
17
+
18
+ import mlrun.errors
19
+
20
+
21
+ def create_linear_backoff(base=2, coefficient=2, stop_value=120):
22
+ """
23
+ Create a generator of linear backoff. Check out usage example in test_helpers.py
24
+ """
25
+ x = 0
26
+ comparison = min if coefficient >= 0 else max
27
+
28
+ while True:
29
+ next_value = comparison(base + x * coefficient, stop_value)
30
+ yield next_value
31
+ x += 1
32
+
33
+
34
+ def create_step_backoff(steps=None):
35
+ """
36
+ Create a generator of steps backoff.
37
+ Example: steps = [[2, 5], [20, 10], [120, None]] will produce a generator in which the first 5
38
+ values will be 2, the next 10 values will be 20 and the rest will be 120.
39
+ :param steps: a list of lists [step_value, number_of_iteration_in_this_step]
40
+ """
41
+ steps = steps if steps is not None else [[2, 10], [10, 10], [120, None]]
42
+ steps = iter(steps)
43
+
44
+ # Get first step
45
+ step = next(steps)
46
+ while True:
47
+ current_step_value, current_step_remain = step
48
+ if current_step_remain == 0:
49
+ # No more in this step, moving on
50
+ step = next(steps)
51
+ elif current_step_remain is None:
52
+ # We are in the last step, staying here forever
53
+ yield current_step_value
54
+ elif current_step_remain > 0:
55
+ # Still more remains in this step, just reduce the remaining number
56
+ step[1] -= 1
57
+ yield current_step_value
58
+
59
+
60
+ def create_exponential_backoff(base=2, max_value=120, scale_factor=1):
61
+ """
62
+ Create a generator of exponential backoff. Check out usage example in test_helpers.py
63
+ :param base: exponent base
64
+ :param max_value: max limit on the result
65
+ :param scale_factor: factor to be used as linear scaling coefficient
66
+ """
67
+ exponent = 1
68
+ while True:
69
+ # This "complex" implementation (unlike the one in linear backoff) is to avoid exponent growing too fast and
70
+ # risking going behind max_int
71
+ next_value = scale_factor * (base**exponent)
72
+ if next_value < max_value:
73
+ exponent += 1
74
+ yield next_value
75
+ else:
76
+ yield max_value
77
+
78
+
79
+ class Retryer:
80
+ def __init__(self, backoff, timeout, logger, verbose, function, *args, **kwargs):
81
+ """
82
+ Initialize function retryer with given *args and **kwargs.
83
+ Tries to run it until success or timeout reached (timeout is optional)
84
+ :param backoff: can either be a:
85
+ - number (int / float) that will be used as interval.
86
+ - generator of waiting intervals. (support next())
87
+ :param timeout: pass None if timeout is not wanted, number of seconds if it is
88
+ :param logger: a logger so we can log the failures
89
+ :param verbose: whether to log the failure on each retry
90
+ :param _function: function to run
91
+ :param args: functions args
92
+ :param kwargs: functions kwargs
93
+ """
94
+ self.backoff = backoff
95
+ self.timeout = timeout
96
+ self.logger = logger
97
+ self.verbose = verbose
98
+ self.function = function
99
+ self.args = args
100
+ self.kwargs = kwargs
101
+ self.start_time = None
102
+ self.last_exception = None
103
+ self.first_interval = None
104
+
105
+ def run(self):
106
+ self._prepare()
107
+ while not self._timeout_exceeded():
108
+ next_interval = self.first_interval or next(self.backoff)
109
+ result, exc, retry = self._perform_call(next_interval)
110
+ if retry:
111
+ time.sleep(next_interval)
112
+ elif not exc:
113
+ return result
114
+ else:
115
+ break
116
+
117
+ self._raise_last_exception()
118
+
119
+ def _prepare(self):
120
+ self.start_time = time.monotonic()
121
+ self.last_exception = None
122
+
123
+ # Check if backoff is just a simple interval
124
+ if isinstance(self.backoff, int) or isinstance(self.backoff, float):
125
+ self.backoff = create_linear_backoff(base=self.backoff, coefficient=0)
126
+
127
+ self.first_interval = next(self.backoff)
128
+ if self.timeout and self.timeout <= self.first_interval:
129
+ self.logger.warning(
130
+ f"Timeout ({self.timeout}) must be higher than backoff ({self.first_interval})."
131
+ f" Set timeout to be higher than backoff."
132
+ )
133
+
134
+ def _perform_call(self, next_interval):
135
+ try:
136
+ result = self.function(*self.args, **self.kwargs)
137
+ return result, None, False
138
+ except mlrun.errors.MLRunFatalFailureError as exc:
139
+ raise exc.original_exception
140
+ except Exception as exc:
141
+ self.last_exception = exc
142
+ return (
143
+ None,
144
+ self.last_exception,
145
+ self._assert_failure_timeout(next_interval, exc),
146
+ )
147
+
148
+ def _assert_failure_timeout(self, next_interval, exc):
149
+ self.last_exception = exc
150
+
151
+ # If next interval is within allowed time period - wait on interval, abort otherwise
152
+ if not self._timeout_exceeded(next_interval):
153
+ if self.logger is not None and self.verbose:
154
+ self.logger.debug(
155
+ f"Operation not yet successful, Retrying in {next_interval} seconds."
156
+ f" exc: {mlrun.errors.err_to_str(exc)}"
157
+ )
158
+ return True
159
+ else:
160
+ return False
161
+
162
+ def _raise_last_exception(self):
163
+ if self.logger is not None:
164
+ self.logger.warning(
165
+ f"Operation did not complete on time. last exception: {self.last_exception}"
166
+ )
167
+
168
+ raise mlrun.errors.MLRunRetryExhaustedError(
169
+ f"Failed to execute command by the given deadline."
170
+ f" last_exception: {self.last_exception},"
171
+ f" function_name: {self.function.__name__},"
172
+ f" timeout: {self.timeout}"
173
+ ) from self.last_exception
174
+
175
+ def _timeout_exceeded(self, next_interval=None):
176
+ now = time.monotonic()
177
+ if next_interval:
178
+ now = now + next_interval
179
+ return self.timeout is not None and now >= self.start_time + self.timeout
180
+
181
+
182
+ class AsyncRetryer(Retryer):
183
+ async def run(self):
184
+ self._prepare()
185
+ while not self._timeout_exceeded():
186
+ next_interval = self.first_interval or next(self.backoff)
187
+ result, exc, retry = await self._perform_call(next_interval)
188
+ if retry:
189
+ await asyncio.sleep(next_interval)
190
+ elif not exc:
191
+ return result
192
+ else:
193
+ break
194
+
195
+ self._raise_last_exception()
196
+
197
+ async def _perform_call(self, next_interval):
198
+ try:
199
+ result = await self.function(*self.args, **self.kwargs)
200
+ return result, None, False
201
+ except mlrun.errors.MLRunFatalFailureError as exc:
202
+ raise exc.original_exception
203
+ except Exception as exc:
204
+ return (
205
+ None,
206
+ self.last_exception,
207
+ self._assert_failure_timeout(next_interval, exc),
208
+ )
mlrun/utils/singleton.py CHANGED
@@ -20,7 +20,7 @@ class Singleton(type):
20
20
 
21
21
  def __call__(cls, *args, **kwargs):
22
22
  if cls not in cls._instances:
23
- cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
23
+ cls._instances[cls] = super().__call__(*args, **kwargs)
24
24
  return cls._instances[cls]
25
25
 
26
26
 
@@ -11,15 +11,13 @@
11
11
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
- #
15
- from typing import Dict, FrozenSet
16
14
 
17
15
  from v3io.dataplane import Client as V3IOClient
18
16
  from v3io_frames import Client as get_client
19
17
  from v3io_frames.client import ClientBase
20
18
 
21
- _v3io_clients: Dict[FrozenSet, V3IOClient] = {}
22
- _frames_clients: Dict[FrozenSet, ClientBase] = {}
19
+ _v3io_clients: dict[frozenset, V3IOClient] = {}
20
+ _frames_clients: dict[frozenset, ClientBase] = {}
23
21
 
24
22
 
25
23
  def get_frames_client(**kwargs) -> ClientBase:
@@ -1,4 +1,4 @@
1
1
  {
2
- "git_commit": "c86187656ea8299187cdca54869c77d341eb58d4",
3
- "version": "1.6.4-rc2"
2
+ "git_commit": "f869a5513ea7c9f4ccdaddad6589274eec39f0a4",
3
+ "version": "1.7.0-rc20"
4
4
  }
@@ -14,15 +14,11 @@
14
14
  #
15
15
  import json
16
16
  import sys
17
+ from importlib.resources import read_text
17
18
 
18
19
  import mlrun.utils
19
20
  from mlrun.utils.singleton import Singleton
20
21
 
21
- if sys.version_info >= (3, 7):
22
- from importlib.resources import read_text
23
- else:
24
- from importlib_resources import read_text
25
-
26
22
 
27
23
  class _VersionInfo:
28
24
  def __init__(self, major, minor, patch):
@@ -56,5 +52,5 @@ class Version(metaclass=Singleton):
56
52
  return self.python_version
57
53
 
58
54
  @staticmethod
59
- def _resolve_python_version() -> sys.version_info:
55
+ def _resolve_python_version() -> _VersionInfo:
60
56
  return _VersionInfo(*sys.version_info[:3])
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: mlrun
3
- Version: 1.6.4rc2
3
+ Version: 1.7.0rc20
4
4
  Summary: Tracking and config of machine learning runs
5
5
  Home-page: https://github.com/mlrun/mlrun
6
6
  Author: Yaron Haviv
@@ -26,10 +26,9 @@ Requires-Dist: GitPython >=3.1.41,~=3.1
26
26
  Requires-Dist: aiohttp ~=3.9
27
27
  Requires-Dist: aiohttp-retry ~=2.8
28
28
  Requires-Dist: click ~=8.1
29
- Requires-Dist: kfp >=1.8.14,~=1.8
30
29
  Requires-Dist: nest-asyncio ~=1.0
31
30
  Requires-Dist: ipython ~=8.10
32
- Requires-Dist: nuclio-jupyter ~=0.9.15
31
+ Requires-Dist: nuclio-jupyter ~=0.9.17
33
32
  Requires-Dist: numpy <1.27.0,>=1.16.5
34
33
  Requires-Dist: pandas <2.2,>=1.2
35
34
  Requires-Dist: pyarrow <15,>=10.0
@@ -42,16 +41,20 @@ Requires-Dist: mergedeep ~=1.3
42
41
  Requires-Dist: v3io-frames ~=0.10.12
43
42
  Requires-Dist: semver ~=3.0
44
43
  Requires-Dist: dependency-injector ~=4.41
45
- Requires-Dist: fsspec ==2023.9.2
44
+ Requires-Dist: fsspec <2024.4,>=2023.9.2
46
45
  Requires-Dist: v3iofs ~=0.1.17
47
- Requires-Dist: storey ~=1.6.20
46
+ Requires-Dist: storey ~=1.7.17
48
47
  Requires-Dist: inflection ~=0.5.0
49
48
  Requires-Dist: python-dotenv ~=0.17.0
50
49
  Requires-Dist: setuptools ~=69.1
51
50
  Requires-Dist: deprecated ~=1.2
52
51
  Requires-Dist: jinja2 >=3.1.3,~=3.1
53
- Requires-Dist: anyio ~=3.7
54
- Requires-Dist: orjson ~=3.9
52
+ Requires-Dist: orjson <4,>=3.9.15
53
+ Requires-Dist: mlrun-pipelines-kfp-common ~=0.1.0
54
+ Requires-Dist: mlrun-pipelines-kfp-v1-8 ~=0.1.0
55
+ Provides-Extra: alibaba-oss
56
+ Requires-Dist: ossfs ==2023.12.0 ; extra == 'alibaba-oss'
57
+ Requires-Dist: oss2 ==2.18.1 ; extra == 'alibaba-oss'
55
58
  Provides-Extra: all
56
59
  Requires-Dist: adlfs ==2023.9.0 ; extra == 'all'
57
60
  Requires-Dist: aiobotocore <2.8,>=2.5.0 ; extra == 'all'
@@ -64,7 +67,7 @@ Requires-Dist: boto3 <1.29.0,>=1.28.0 ; extra == 'all'
64
67
  Requires-Dist: dask ~=2023.9.0 ; extra == 'all'
65
68
  Requires-Dist: databricks-sdk ~=0.13.0 ; extra == 'all'
66
69
  Requires-Dist: distributed ~=2023.9.0 ; extra == 'all'
67
- Requires-Dist: gcsfs ==2023.9.2 ; extra == 'all'
70
+ Requires-Dist: gcsfs <2024.4,>=2023.9.2 ; extra == 'all'
68
71
  Requires-Dist: google-cloud-bigquery[bqstorage,pandas] ==3.14.1 ; extra == 'all'
69
72
  Requires-Dist: google-cloud-storage ==2.14.0 ; extra == 'all'
70
73
  Requires-Dist: google-cloud ==0.34 ; extra == 'all'
@@ -72,24 +75,26 @@ Requires-Dist: graphviz ~=0.20.0 ; extra == 'all'
72
75
  Requires-Dist: kafka-python ~=2.0 ; extra == 'all'
73
76
  Requires-Dist: mlflow ~=2.8 ; extra == 'all'
74
77
  Requires-Dist: msrest ~=0.6.21 ; extra == 'all'
78
+ Requires-Dist: oss2 ==2.18.1 ; extra == 'all'
79
+ Requires-Dist: ossfs ==2023.12.0 ; extra == 'all'
75
80
  Requires-Dist: plotly <5.12.0,~=5.4 ; extra == 'all'
76
81
  Requires-Dist: pyopenssl >=23 ; extra == 'all'
77
82
  Requires-Dist: redis ~=4.3 ; extra == 'all'
78
- Requires-Dist: s3fs ==2023.9.2 ; extra == 'all'
83
+ Requires-Dist: s3fs <2024.4,>=2023.9.2 ; extra == 'all'
79
84
  Requires-Dist: sqlalchemy ~=1.4 ; extra == 'all'
85
+ Requires-Dist: taos-ws-py ~=0.3.2 ; extra == 'all'
80
86
  Provides-Extra: api
81
87
  Requires-Dist: uvicorn ~=0.27.1 ; extra == 'api'
82
88
  Requires-Dist: dask-kubernetes ~=0.11.0 ; extra == 'api'
83
89
  Requires-Dist: apscheduler <4,>=3.10.3 ; extra == 'api'
84
90
  Requires-Dist: objgraph ~=3.6 ; extra == 'api'
85
- Requires-Dist: igz-mgmt ==0.1.0 ; extra == 'api'
91
+ Requires-Dist: igz-mgmt ~=0.1.3 ; extra == 'api'
86
92
  Requires-Dist: humanfriendly ~=10.0 ; extra == 'api'
87
93
  Requires-Dist: fastapi ~=0.110.0 ; extra == 'api'
88
94
  Requires-Dist: sqlalchemy ~=1.4 ; extra == 'api'
89
95
  Requires-Dist: pymysql ~=1.0 ; extra == 'api'
90
96
  Requires-Dist: alembic ~=1.9 ; extra == 'api'
91
97
  Requires-Dist: timelength ~=1.1 ; extra == 'api'
92
- Requires-Dist: memray ~=1.12 ; extra == 'api'
93
98
  Provides-Extra: azure-blob-storage
94
99
  Requires-Dist: msrest ~=0.6.21 ; extra == 'azure-blob-storage'
95
100
  Requires-Dist: azure-core ~=1.24 ; extra == 'azure-blob-storage'
@@ -112,17 +117,20 @@ Requires-Dist: boto3 <1.29.0,>=1.28.0 ; extra == 'complete'
112
117
  Requires-Dist: dask ~=2023.9.0 ; extra == 'complete'
113
118
  Requires-Dist: databricks-sdk ~=0.13.0 ; extra == 'complete'
114
119
  Requires-Dist: distributed ~=2023.9.0 ; extra == 'complete'
115
- Requires-Dist: gcsfs ==2023.9.2 ; extra == 'complete'
120
+ Requires-Dist: gcsfs <2024.4,>=2023.9.2 ; extra == 'complete'
116
121
  Requires-Dist: google-cloud-bigquery[bqstorage,pandas] ==3.14.1 ; extra == 'complete'
117
122
  Requires-Dist: graphviz ~=0.20.0 ; extra == 'complete'
118
123
  Requires-Dist: kafka-python ~=2.0 ; extra == 'complete'
119
124
  Requires-Dist: mlflow ~=2.8 ; extra == 'complete'
120
125
  Requires-Dist: msrest ~=0.6.21 ; extra == 'complete'
126
+ Requires-Dist: oss2 ==2.18.1 ; extra == 'complete'
127
+ Requires-Dist: ossfs ==2023.12.0 ; extra == 'complete'
121
128
  Requires-Dist: plotly <5.12.0,~=5.4 ; extra == 'complete'
122
129
  Requires-Dist: pyopenssl >=23 ; extra == 'complete'
123
130
  Requires-Dist: redis ~=4.3 ; extra == 'complete'
124
- Requires-Dist: s3fs ==2023.9.2 ; extra == 'complete'
131
+ Requires-Dist: s3fs <2024.4,>=2023.9.2 ; extra == 'complete'
125
132
  Requires-Dist: sqlalchemy ~=1.4 ; extra == 'complete'
133
+ Requires-Dist: taos-ws-py ~=0.3.2 ; extra == 'complete'
126
134
  Provides-Extra: complete-api
127
135
  Requires-Dist: adlfs ==2023.9.0 ; extra == 'complete-api'
128
136
  Requires-Dist: aiobotocore <2.8,>=2.5.0 ; extra == 'complete-api'
@@ -138,22 +146,24 @@ Requires-Dist: dask ~=2023.9.0 ; extra == 'complete-api'
138
146
  Requires-Dist: databricks-sdk ~=0.13.0 ; extra == 'complete-api'
139
147
  Requires-Dist: distributed ~=2023.9.0 ; extra == 'complete-api'
140
148
  Requires-Dist: fastapi ~=0.110.0 ; extra == 'complete-api'
141
- Requires-Dist: gcsfs ==2023.9.2 ; extra == 'complete-api'
149
+ Requires-Dist: gcsfs <2024.4,>=2023.9.2 ; extra == 'complete-api'
142
150
  Requires-Dist: google-cloud-bigquery[bqstorage,pandas] ==3.14.1 ; extra == 'complete-api'
143
151
  Requires-Dist: graphviz ~=0.20.0 ; extra == 'complete-api'
144
152
  Requires-Dist: humanfriendly ~=10.0 ; extra == 'complete-api'
145
- Requires-Dist: igz-mgmt ==0.1.0 ; extra == 'complete-api'
153
+ Requires-Dist: igz-mgmt ~=0.1.3 ; extra == 'complete-api'
146
154
  Requires-Dist: kafka-python ~=2.0 ; extra == 'complete-api'
147
- Requires-Dist: memray ~=1.12 ; extra == 'complete-api'
148
155
  Requires-Dist: mlflow ~=2.8 ; extra == 'complete-api'
149
156
  Requires-Dist: msrest ~=0.6.21 ; extra == 'complete-api'
150
157
  Requires-Dist: objgraph ~=3.6 ; extra == 'complete-api'
158
+ Requires-Dist: oss2 ==2.18.1 ; extra == 'complete-api'
159
+ Requires-Dist: ossfs ==2023.12.0 ; extra == 'complete-api'
151
160
  Requires-Dist: plotly <5.12.0,~=5.4 ; extra == 'complete-api'
152
161
  Requires-Dist: pymysql ~=1.0 ; extra == 'complete-api'
153
162
  Requires-Dist: pyopenssl >=23 ; extra == 'complete-api'
154
163
  Requires-Dist: redis ~=4.3 ; extra == 'complete-api'
155
- Requires-Dist: s3fs ==2023.9.2 ; extra == 'complete-api'
164
+ Requires-Dist: s3fs <2024.4,>=2023.9.2 ; extra == 'complete-api'
156
165
  Requires-Dist: sqlalchemy ~=1.4 ; extra == 'complete-api'
166
+ Requires-Dist: taos-ws-py ~=0.3.2 ; extra == 'complete-api'
157
167
  Requires-Dist: timelength ~=1.1 ; extra == 'complete-api'
158
168
  Requires-Dist: uvicorn ~=0.27.1 ; extra == 'complete-api'
159
169
  Provides-Extra: dask
@@ -168,7 +178,7 @@ Requires-Dist: google-cloud ==0.34 ; extra == 'google-cloud'
168
178
  Provides-Extra: google-cloud-bigquery
169
179
  Requires-Dist: google-cloud-bigquery[bqstorage,pandas] ==3.14.1 ; extra == 'google-cloud-bigquery'
170
180
  Provides-Extra: google-cloud-storage
171
- Requires-Dist: gcsfs ==2023.9.2 ; extra == 'google-cloud-storage'
181
+ Requires-Dist: gcsfs <2024.4,>=2023.9.2 ; extra == 'google-cloud-storage'
172
182
  Provides-Extra: graphviz
173
183
  Requires-Dist: graphviz ~=0.20.0 ; extra == 'graphviz'
174
184
  Provides-Extra: kafka
@@ -183,9 +193,11 @@ Requires-Dist: redis ~=4.3 ; extra == 'redis'
183
193
  Provides-Extra: s3
184
194
  Requires-Dist: boto3 <1.29.0,>=1.28.0 ; extra == 's3'
185
195
  Requires-Dist: aiobotocore <2.8,>=2.5.0 ; extra == 's3'
186
- Requires-Dist: s3fs ==2023.9.2 ; extra == 's3'
196
+ Requires-Dist: s3fs <2024.4,>=2023.9.2 ; extra == 's3'
187
197
  Provides-Extra: sqlalchemy
188
198
  Requires-Dist: sqlalchemy ~=1.4 ; extra == 'sqlalchemy'
199
+ Provides-Extra: tdengine
200
+ Requires-Dist: taos-ws-py ~=0.3.2 ; extra == 'tdengine'
189
201
 
190
202
  <a id="top"></a>
191
203
  [![Build Status](https://github.com/mlrun/mlrun/actions/workflows/build.yaml/badge.svg?branch=development)](https://github.com/mlrun/mlrun/actions/workflows/build.yaml?query=branch%3Adevelopment)