mlrun 1.7.2rc3__py3-none-any.whl → 1.8.0rc1__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 (222) hide show
  1. mlrun/__init__.py +14 -12
  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/model_monitoring/__init__.py +0 -3
  16. mlrun/common/model_monitoring/helpers.py +1 -1
  17. mlrun/common/runtimes/constants.py +1 -2
  18. mlrun/common/schemas/__init__.py +4 -2
  19. mlrun/common/schemas/artifact.py +0 -6
  20. mlrun/common/schemas/common.py +50 -0
  21. mlrun/common/schemas/model_monitoring/__init__.py +8 -1
  22. mlrun/common/schemas/model_monitoring/constants.py +62 -12
  23. mlrun/common/schemas/model_monitoring/model_endpoint_v2.py +149 -0
  24. mlrun/common/schemas/model_monitoring/model_endpoints.py +21 -5
  25. mlrun/common/schemas/partition.py +122 -0
  26. mlrun/config.py +43 -15
  27. mlrun/data_types/__init__.py +0 -2
  28. mlrun/data_types/data_types.py +0 -1
  29. mlrun/data_types/infer.py +3 -1
  30. mlrun/data_types/spark.py +4 -4
  31. mlrun/data_types/to_pandas.py +2 -11
  32. mlrun/datastore/__init__.py +0 -2
  33. mlrun/datastore/alibaba_oss.py +4 -1
  34. mlrun/datastore/azure_blob.py +4 -1
  35. mlrun/datastore/base.py +12 -4
  36. mlrun/datastore/datastore.py +9 -3
  37. mlrun/datastore/datastore_profile.py +1 -1
  38. mlrun/datastore/dbfs_store.py +4 -1
  39. mlrun/datastore/filestore.py +4 -1
  40. mlrun/datastore/google_cloud_storage.py +4 -1
  41. mlrun/datastore/hdfs.py +4 -1
  42. mlrun/datastore/inmem.py +4 -1
  43. mlrun/datastore/redis.py +4 -1
  44. mlrun/datastore/s3.py +4 -1
  45. mlrun/datastore/sources.py +51 -49
  46. mlrun/datastore/store_resources.py +0 -2
  47. mlrun/datastore/targets.py +22 -23
  48. mlrun/datastore/utils.py +2 -2
  49. mlrun/datastore/v3io.py +4 -1
  50. mlrun/datastore/wasbfs/fs.py +13 -12
  51. mlrun/db/base.py +126 -62
  52. mlrun/db/factory.py +3 -0
  53. mlrun/db/httpdb.py +767 -231
  54. mlrun/db/nopdb.py +126 -57
  55. mlrun/errors.py +2 -2
  56. mlrun/execution.py +55 -29
  57. mlrun/feature_store/__init__.py +0 -2
  58. mlrun/feature_store/api.py +40 -40
  59. mlrun/feature_store/common.py +9 -9
  60. mlrun/feature_store/feature_set.py +20 -18
  61. mlrun/feature_store/feature_vector.py +27 -24
  62. mlrun/feature_store/retrieval/base.py +14 -9
  63. mlrun/feature_store/retrieval/job.py +2 -1
  64. mlrun/feature_store/steps.py +2 -2
  65. mlrun/features.py +30 -13
  66. mlrun/frameworks/__init__.py +1 -2
  67. mlrun/frameworks/_common/__init__.py +1 -2
  68. mlrun/frameworks/_common/artifacts_library.py +2 -2
  69. mlrun/frameworks/_common/mlrun_interface.py +10 -6
  70. mlrun/frameworks/_common/model_handler.py +29 -27
  71. mlrun/frameworks/_common/producer.py +3 -1
  72. mlrun/frameworks/_dl_common/__init__.py +1 -2
  73. mlrun/frameworks/_dl_common/loggers/__init__.py +1 -2
  74. mlrun/frameworks/_dl_common/loggers/mlrun_logger.py +4 -4
  75. mlrun/frameworks/_dl_common/loggers/tensorboard_logger.py +3 -3
  76. mlrun/frameworks/_ml_common/__init__.py +1 -2
  77. mlrun/frameworks/_ml_common/loggers/__init__.py +1 -2
  78. mlrun/frameworks/_ml_common/model_handler.py +21 -21
  79. mlrun/frameworks/_ml_common/plans/__init__.py +1 -2
  80. mlrun/frameworks/_ml_common/plans/confusion_matrix_plan.py +3 -1
  81. mlrun/frameworks/_ml_common/plans/dataset_plan.py +3 -3
  82. mlrun/frameworks/_ml_common/plans/roc_curve_plan.py +4 -4
  83. mlrun/frameworks/auto_mlrun/__init__.py +1 -2
  84. mlrun/frameworks/auto_mlrun/auto_mlrun.py +22 -15
  85. mlrun/frameworks/huggingface/__init__.py +1 -2
  86. mlrun/frameworks/huggingface/model_server.py +9 -9
  87. mlrun/frameworks/lgbm/__init__.py +47 -44
  88. mlrun/frameworks/lgbm/callbacks/__init__.py +1 -2
  89. mlrun/frameworks/lgbm/callbacks/logging_callback.py +4 -2
  90. mlrun/frameworks/lgbm/callbacks/mlrun_logging_callback.py +4 -2
  91. mlrun/frameworks/lgbm/mlrun_interfaces/__init__.py +1 -2
  92. mlrun/frameworks/lgbm/mlrun_interfaces/mlrun_interface.py +5 -5
  93. mlrun/frameworks/lgbm/model_handler.py +15 -11
  94. mlrun/frameworks/lgbm/model_server.py +11 -7
  95. mlrun/frameworks/lgbm/utils.py +2 -2
  96. mlrun/frameworks/onnx/__init__.py +1 -2
  97. mlrun/frameworks/onnx/dataset.py +3 -3
  98. mlrun/frameworks/onnx/mlrun_interface.py +2 -2
  99. mlrun/frameworks/onnx/model_handler.py +7 -5
  100. mlrun/frameworks/onnx/model_server.py +8 -6
  101. mlrun/frameworks/parallel_coordinates.py +11 -11
  102. mlrun/frameworks/pytorch/__init__.py +22 -23
  103. mlrun/frameworks/pytorch/callbacks/__init__.py +1 -2
  104. mlrun/frameworks/pytorch/callbacks/callback.py +2 -1
  105. mlrun/frameworks/pytorch/callbacks/logging_callback.py +15 -8
  106. mlrun/frameworks/pytorch/callbacks/mlrun_logging_callback.py +19 -12
  107. mlrun/frameworks/pytorch/callbacks/tensorboard_logging_callback.py +22 -15
  108. mlrun/frameworks/pytorch/callbacks_handler.py +36 -30
  109. mlrun/frameworks/pytorch/mlrun_interface.py +17 -17
  110. mlrun/frameworks/pytorch/model_handler.py +21 -17
  111. mlrun/frameworks/pytorch/model_server.py +13 -9
  112. mlrun/frameworks/sklearn/__init__.py +19 -18
  113. mlrun/frameworks/sklearn/estimator.py +2 -2
  114. mlrun/frameworks/sklearn/metric.py +3 -3
  115. mlrun/frameworks/sklearn/metrics_library.py +8 -6
  116. mlrun/frameworks/sklearn/mlrun_interface.py +3 -2
  117. mlrun/frameworks/sklearn/model_handler.py +4 -3
  118. mlrun/frameworks/tf_keras/__init__.py +11 -12
  119. mlrun/frameworks/tf_keras/callbacks/__init__.py +1 -2
  120. mlrun/frameworks/tf_keras/callbacks/logging_callback.py +17 -14
  121. mlrun/frameworks/tf_keras/callbacks/mlrun_logging_callback.py +15 -12
  122. mlrun/frameworks/tf_keras/callbacks/tensorboard_logging_callback.py +21 -18
  123. mlrun/frameworks/tf_keras/model_handler.py +17 -13
  124. mlrun/frameworks/tf_keras/model_server.py +12 -8
  125. mlrun/frameworks/xgboost/__init__.py +19 -18
  126. mlrun/frameworks/xgboost/model_handler.py +13 -9
  127. mlrun/launcher/base.py +3 -4
  128. mlrun/launcher/local.py +1 -1
  129. mlrun/launcher/remote.py +1 -1
  130. mlrun/lists.py +4 -3
  131. mlrun/model.py +108 -44
  132. mlrun/model_monitoring/__init__.py +1 -2
  133. mlrun/model_monitoring/api.py +6 -6
  134. mlrun/model_monitoring/applications/_application_steps.py +13 -15
  135. mlrun/model_monitoring/applications/histogram_data_drift.py +41 -15
  136. mlrun/model_monitoring/applications/results.py +55 -3
  137. mlrun/model_monitoring/controller.py +185 -223
  138. mlrun/model_monitoring/db/_schedules.py +156 -0
  139. mlrun/model_monitoring/db/_stats.py +189 -0
  140. mlrun/model_monitoring/db/stores/__init__.py +1 -1
  141. mlrun/model_monitoring/db/stores/base/store.py +6 -65
  142. mlrun/model_monitoring/db/stores/sqldb/models/__init__.py +0 -25
  143. mlrun/model_monitoring/db/stores/sqldb/models/base.py +0 -97
  144. mlrun/model_monitoring/db/stores/sqldb/models/mysql.py +2 -58
  145. mlrun/model_monitoring/db/stores/sqldb/models/sqlite.py +0 -15
  146. mlrun/model_monitoring/db/stores/sqldb/sql_store.py +6 -257
  147. mlrun/model_monitoring/db/stores/v3io_kv/kv_store.py +9 -271
  148. mlrun/model_monitoring/db/tsdb/base.py +74 -22
  149. mlrun/model_monitoring/db/tsdb/tdengine/schemas.py +66 -35
  150. mlrun/model_monitoring/db/tsdb/tdengine/stream_graph_steps.py +33 -0
  151. mlrun/model_monitoring/db/tsdb/tdengine/tdengine_connector.py +284 -51
  152. mlrun/model_monitoring/db/tsdb/v3io/stream_graph_steps.py +1 -0
  153. mlrun/model_monitoring/db/tsdb/v3io/v3io_connector.py +35 -17
  154. mlrun/model_monitoring/helpers.py +97 -1
  155. mlrun/model_monitoring/model_endpoint.py +4 -2
  156. mlrun/model_monitoring/stream_processing.py +2 -2
  157. mlrun/model_monitoring/tracking_policy.py +10 -3
  158. mlrun/model_monitoring/writer.py +47 -26
  159. mlrun/package/__init__.py +3 -6
  160. mlrun/package/context_handler.py +1 -1
  161. mlrun/package/packager.py +12 -9
  162. mlrun/package/packagers/__init__.py +0 -2
  163. mlrun/package/packagers/default_packager.py +14 -11
  164. mlrun/package/packagers/numpy_packagers.py +16 -7
  165. mlrun/package/packagers/pandas_packagers.py +18 -18
  166. mlrun/package/packagers/python_standard_library_packagers.py +25 -11
  167. mlrun/package/packagers_manager.py +31 -14
  168. mlrun/package/utils/__init__.py +0 -3
  169. mlrun/package/utils/_pickler.py +6 -6
  170. mlrun/platforms/__init__.py +3 -3
  171. mlrun/platforms/iguazio.py +4 -1
  172. mlrun/projects/__init__.py +1 -6
  173. mlrun/projects/operations.py +27 -27
  174. mlrun/projects/pipelines.py +85 -215
  175. mlrun/projects/project.py +444 -158
  176. mlrun/run.py +9 -9
  177. mlrun/runtimes/__init__.py +1 -3
  178. mlrun/runtimes/base.py +13 -10
  179. mlrun/runtimes/daskjob.py +9 -9
  180. mlrun/runtimes/generators.py +2 -1
  181. mlrun/runtimes/kubejob.py +4 -5
  182. mlrun/runtimes/mpijob/__init__.py +0 -2
  183. mlrun/runtimes/mpijob/abstract.py +7 -6
  184. mlrun/runtimes/nuclio/api_gateway.py +7 -7
  185. mlrun/runtimes/nuclio/application/application.py +11 -11
  186. mlrun/runtimes/nuclio/function.py +14 -13
  187. mlrun/runtimes/nuclio/serving.py +9 -9
  188. mlrun/runtimes/pod.py +74 -29
  189. mlrun/runtimes/remotesparkjob.py +3 -2
  190. mlrun/runtimes/sparkjob/__init__.py +0 -2
  191. mlrun/runtimes/sparkjob/spark3job.py +21 -11
  192. mlrun/runtimes/utils.py +6 -5
  193. mlrun/serving/merger.py +6 -4
  194. mlrun/serving/remote.py +18 -17
  195. mlrun/serving/routers.py +27 -27
  196. mlrun/serving/server.py +1 -1
  197. mlrun/serving/states.py +76 -71
  198. mlrun/serving/utils.py +13 -2
  199. mlrun/serving/v1_serving.py +3 -2
  200. mlrun/serving/v2_serving.py +4 -4
  201. mlrun/track/__init__.py +1 -1
  202. mlrun/track/tracker.py +2 -2
  203. mlrun/track/trackers/mlflow_tracker.py +6 -5
  204. mlrun/utils/async_http.py +1 -1
  205. mlrun/utils/helpers.py +72 -28
  206. mlrun/utils/logger.py +104 -2
  207. mlrun/utils/notifications/notification/base.py +23 -4
  208. mlrun/utils/notifications/notification/console.py +1 -1
  209. mlrun/utils/notifications/notification/git.py +6 -6
  210. mlrun/utils/notifications/notification/ipython.py +5 -4
  211. mlrun/utils/notifications/notification/slack.py +1 -1
  212. mlrun/utils/notifications/notification/webhook.py +13 -17
  213. mlrun/utils/notifications/notification_pusher.py +23 -19
  214. mlrun/utils/regex.py +1 -1
  215. mlrun/utils/version/version.json +2 -2
  216. {mlrun-1.7.2rc3.dist-info → mlrun-1.8.0rc1.dist-info}/METADATA +186 -186
  217. mlrun-1.8.0rc1.dist-info/RECORD +356 -0
  218. {mlrun-1.7.2rc3.dist-info → mlrun-1.8.0rc1.dist-info}/WHEEL +1 -1
  219. mlrun-1.7.2rc3.dist-info/RECORD +0 -351
  220. {mlrun-1.7.2rc3.dist-info → mlrun-1.8.0rc1.dist-info}/LICENSE +0 -0
  221. {mlrun-1.7.2rc3.dist-info → mlrun-1.8.0rc1.dist-info}/entry_points.txt +0 -0
  222. {mlrun-1.7.2rc3.dist-info → mlrun-1.8.0rc1.dist-info}/top_level.txt +0 -0
mlrun/serving/states.py CHANGED
@@ -25,7 +25,7 @@ import pathlib
25
25
  import traceback
26
26
  from copy import copy, deepcopy
27
27
  from inspect import getfullargspec, signature
28
- from typing import Any, Union
28
+ from typing import Any, Optional, Union
29
29
 
30
30
  import storey.utils
31
31
 
@@ -104,7 +104,12 @@ class BaseStep(ModelObj):
104
104
  default_shape = "ellipse"
105
105
  _dict_fields = ["kind", "comment", "after", "on_error"]
106
106
 
107
- def __init__(self, name: str = None, after: list = None, shape: str = None):
107
+ def __init__(
108
+ self,
109
+ name: Optional[str] = None,
110
+ after: Optional[list] = None,
111
+ shape: Optional[str] = None,
112
+ ):
108
113
  self.name = name
109
114
  self._parent = None
110
115
  self.comment = None
@@ -154,14 +159,14 @@ class BaseStep(ModelObj):
154
159
 
155
160
  def error_handler(
156
161
  self,
157
- name: str = None,
162
+ name: Optional[str] = None,
158
163
  class_name=None,
159
164
  handler=None,
160
165
  before=None,
161
166
  function=None,
162
- full_event: bool = None,
163
- input_path: str = None,
164
- result_path: str = None,
167
+ full_event: Optional[bool] = None,
168
+ input_path: Optional[str] = None,
169
+ result_path: Optional[str] = None,
165
170
  **class_args,
166
171
  ):
167
172
  """set error handler on a step or the entire graph (to be executed on failure/raise)
@@ -297,13 +302,13 @@ class BaseStep(ModelObj):
297
302
  def to(
298
303
  self,
299
304
  class_name: Union[str, StepToDict] = None,
300
- name: str = None,
301
- handler: str = None,
302
- graph_shape: str = None,
303
- function: str = None,
304
- full_event: bool = None,
305
- input_path: str = None,
306
- result_path: str = None,
305
+ name: Optional[str] = None,
306
+ handler: Optional[str] = None,
307
+ graph_shape: Optional[str] = None,
308
+ function: Optional[str] = None,
309
+ full_event: Optional[bool] = None,
310
+ input_path: Optional[str] = None,
311
+ result_path: Optional[str] = None,
307
312
  **class_args,
308
313
  ):
309
314
  """add a step right after this step and return the new step
@@ -404,16 +409,16 @@ class TaskStep(BaseStep):
404
409
 
405
410
  def __init__(
406
411
  self,
407
- class_name: Union[str, type] = None,
408
- class_args: dict = None,
409
- handler: str = None,
410
- name: str = None,
411
- after: list = None,
412
- full_event: bool = None,
413
- function: str = None,
414
- responder: bool = None,
415
- input_path: str = None,
416
- result_path: str = None,
412
+ class_name: Optional[Union[str, type]] = None,
413
+ class_args: Optional[dict] = None,
414
+ handler: Optional[str] = None,
415
+ name: Optional[str] = None,
416
+ after: Optional[list] = None,
417
+ full_event: Optional[bool] = None,
418
+ function: Optional[str] = None,
419
+ responder: Optional[bool] = None,
420
+ input_path: Optional[str] = None,
421
+ result_path: Optional[str] = None,
417
422
  ):
418
423
  super().__init__(name, after)
419
424
  self.class_name = class_name
@@ -607,16 +612,16 @@ class MonitoringApplicationStep(TaskStep):
607
612
 
608
613
  def __init__(
609
614
  self,
610
- class_name: Union[str, type] = None,
611
- class_args: dict = None,
612
- handler: str = None,
613
- name: str = None,
614
- after: list = None,
615
- full_event: bool = None,
616
- function: str = None,
617
- responder: bool = None,
618
- input_path: str = None,
619
- result_path: str = None,
615
+ class_name: Optional[Union[str, type]] = None,
616
+ class_args: Optional[dict] = None,
617
+ handler: Optional[str] = None,
618
+ name: Optional[str] = None,
619
+ after: Optional[list] = None,
620
+ full_event: Optional[bool] = None,
621
+ function: Optional[str] = None,
622
+ responder: Optional[bool] = None,
623
+ input_path: Optional[str] = None,
624
+ result_path: Optional[str] = None,
620
625
  ):
621
626
  super().__init__(
622
627
  class_name=class_name,
@@ -641,16 +646,16 @@ class ErrorStep(TaskStep):
641
646
 
642
647
  def __init__(
643
648
  self,
644
- class_name: Union[str, type] = None,
645
- class_args: dict = None,
646
- handler: str = None,
647
- name: str = None,
648
- after: list = None,
649
- full_event: bool = None,
650
- function: str = None,
651
- responder: bool = None,
652
- input_path: str = None,
653
- result_path: str = None,
649
+ class_name: Optional[Union[str, type]] = None,
650
+ class_args: Optional[dict] = None,
651
+ handler: Optional[str] = None,
652
+ name: Optional[str] = None,
653
+ after: Optional[list] = None,
654
+ full_event: Optional[bool] = None,
655
+ function: Optional[str] = None,
656
+ responder: Optional[bool] = None,
657
+ input_path: Optional[str] = None,
658
+ result_path: Optional[str] = None,
654
659
  ):
655
660
  super().__init__(
656
661
  class_name=class_name,
@@ -678,14 +683,14 @@ class RouterStep(TaskStep):
678
683
 
679
684
  def __init__(
680
685
  self,
681
- class_name: Union[str, type] = None,
682
- class_args: dict = None,
683
- handler: str = None,
684
- routes: list = None,
685
- name: str = None,
686
- function: str = None,
687
- input_path: str = None,
688
- result_path: str = None,
686
+ class_name: Optional[Union[str, type]] = None,
687
+ class_args: Optional[dict] = None,
688
+ handler: Optional[str] = None,
689
+ routes: Optional[list] = None,
690
+ name: Optional[str] = None,
691
+ function: Optional[str] = None,
692
+ input_path: Optional[str] = None,
693
+ result_path: Optional[str] = None,
689
694
  ):
690
695
  super().__init__(
691
696
  class_name,
@@ -813,12 +818,12 @@ class QueueStep(BaseStep):
813
818
 
814
819
  def __init__(
815
820
  self,
816
- name: str = None,
817
- path: str = None,
818
- after: list = None,
819
- shards: int = None,
820
- retention_in_hours: int = None,
821
- trigger_args: dict = None,
821
+ name: Optional[str] = None,
822
+ path: Optional[str] = None,
823
+ after: Optional[list] = None,
824
+ shards: Optional[int] = None,
825
+ retention_in_hours: Optional[int] = None,
826
+ trigger_args: Optional[dict] = None,
822
827
  **options,
823
828
  ):
824
829
  super().__init__(name, after)
@@ -850,13 +855,13 @@ class QueueStep(BaseStep):
850
855
  def to(
851
856
  self,
852
857
  class_name: Union[str, StepToDict] = None,
853
- name: str = None,
854
- handler: str = None,
855
- graph_shape: str = None,
856
- function: str = None,
857
- full_event: bool = None,
858
- input_path: str = None,
859
- result_path: str = None,
858
+ name: Optional[str] = None,
859
+ handler: Optional[str] = None,
860
+ graph_shape: Optional[str] = None,
861
+ function: Optional[str] = None,
862
+ full_event: Optional[bool] = None,
863
+ input_path: Optional[str] = None,
864
+ result_path: Optional[str] = None,
860
865
  **class_args,
861
866
  ):
862
867
  if not function:
@@ -905,7 +910,7 @@ class FlowStep(BaseStep):
905
910
  self,
906
911
  name=None,
907
912
  steps=None,
908
- after: list = None,
913
+ after: Optional[list] = None,
909
914
  engine=None,
910
915
  final_step=None,
911
916
  ):
@@ -948,9 +953,9 @@ class FlowStep(BaseStep):
948
953
  before=None,
949
954
  graph_shape=None,
950
955
  function=None,
951
- full_event: bool = None,
952
- input_path: str = None,
953
- result_path: str = None,
956
+ full_event: Optional[bool] = None,
957
+ input_path: Optional[str] = None,
958
+ result_path: Optional[str] = None,
954
959
  **class_args,
955
960
  ):
956
961
  """add task, queue or router step/class to the flow
@@ -1037,7 +1042,7 @@ class FlowStep(BaseStep):
1037
1042
  self._last_added = step
1038
1043
  return step
1039
1044
 
1040
- def clear_children(self, steps: list = None):
1045
+ def clear_children(self, steps: Optional[list] = None):
1041
1046
  """remove some or all of the states, empty/None for all"""
1042
1047
  if not steps:
1043
1048
  steps = self._steps.keys()
@@ -1554,8 +1559,8 @@ def params_to_step(
1554
1559
  graph_shape=None,
1555
1560
  function=None,
1556
1561
  full_event=None,
1557
- input_path: str = None,
1558
- result_path: str = None,
1562
+ input_path: Optional[str] = None,
1563
+ result_path: Optional[str] = None,
1559
1564
  class_args=None,
1560
1565
  ):
1561
1566
  """return step object from provided params or classes/objects"""
mlrun/serving/utils.py CHANGED
@@ -13,6 +13,7 @@
13
13
  # limitations under the License.
14
14
  #
15
15
  import inspect
16
+ from typing import Optional
16
17
 
17
18
  from mlrun.utils import get_in, update_in
18
19
 
@@ -55,7 +56,12 @@ class StepToDict:
55
56
  "kwargs",
56
57
  ]
57
58
 
58
- def to_dict(self, fields: list = None, exclude: list = None, strip: bool = False):
59
+ def to_dict(
60
+ self,
61
+ fields: Optional[list] = None,
62
+ exclude: Optional[list] = None,
63
+ strip: bool = False,
64
+ ):
59
65
  """convert the step object to a python dictionary"""
60
66
  fields = fields or getattr(self, "_dict_fields", None)
61
67
  if not fields:
@@ -105,5 +111,10 @@ class MonitoringApplicationToDict(StepToDict):
105
111
  class RouterToDict(StepToDict):
106
112
  _STEP_KIND = "router"
107
113
 
108
- def to_dict(self, fields: list = None, exclude: list = None, strip: bool = False):
114
+ def to_dict(
115
+ self,
116
+ fields: Optional[list] = None,
117
+ exclude: Optional[list] = None,
118
+ strip: bool = False,
119
+ ):
109
120
  return super().to_dict(exclude=["routes"], strip=strip)
@@ -18,6 +18,7 @@ import socket
18
18
  from copy import deepcopy
19
19
  from datetime import datetime
20
20
  from io import BytesIO
21
+ from typing import Optional
21
22
  from urllib.request import urlopen
22
23
 
23
24
  import nuclio
@@ -33,7 +34,7 @@ serving_handler = "handler"
33
34
  def new_v1_model_server(
34
35
  name,
35
36
  model_class: str,
36
- models: dict = None,
37
+ models: Optional[dict] = None,
37
38
  filename="",
38
39
  protocol="",
39
40
  image="",
@@ -68,7 +69,7 @@ def new_v1_model_server(
68
69
 
69
70
 
70
71
  class MLModelServer:
71
- def __init__(self, name: str, model_dir: str = None, model=None):
72
+ def __init__(self, name: str, model_dir: Optional[str] = None, model=None):
72
73
  self.name = name
73
74
  self.ready = False
74
75
  self.model_dir = model_dir
@@ -33,12 +33,12 @@ class V2ModelServer(StepToDict):
33
33
  def __init__(
34
34
  self,
35
35
  context=None,
36
- name: str = None,
37
- model_path: str = None,
36
+ name: Optional[str] = None,
37
+ model_path: Optional[str] = None,
38
38
  model=None,
39
39
  protocol=None,
40
- input_path: str = None,
41
- result_path: str = None,
40
+ input_path: Optional[str] = None,
41
+ result_path: Optional[str] = None,
42
42
  shard_by_endpoint: Optional[bool] = None,
43
43
  **kwargs,
44
44
  ):
mlrun/track/__init__.py CHANGED
@@ -11,6 +11,6 @@
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
- # flake8: noqa - this is until we take care of the F401 violations with respect to __all__ & sphinx
14
+
15
15
  from mlrun.track.tracker import Tracker
16
16
  from mlrun.track.tracker_manager import TrackerManager
mlrun/track/tracker.py CHANGED
@@ -13,7 +13,7 @@
13
13
  # limitations under the License.
14
14
 
15
15
  from abc import ABC, abstractmethod
16
- from typing import Any, Union
16
+ from typing import Any, Optional, Union
17
17
 
18
18
  from mlrun.artifacts import Artifact, ModelArtifact
19
19
  from mlrun.execution import MLClientCtx
@@ -63,7 +63,7 @@ class Tracker(ABC):
63
63
  project: MlrunProject,
64
64
  reference_id: Any,
65
65
  function_name: str,
66
- handler: str = None,
66
+ handler: Optional[str] = None,
67
67
  **kwargs,
68
68
  ) -> RunObject:
69
69
  """
@@ -15,6 +15,7 @@ import os
15
15
  import pathlib
16
16
  import tempfile
17
17
  import zipfile
18
+ from typing import Optional
18
19
 
19
20
  import mlflow
20
21
  import mlflow.entities
@@ -190,7 +191,7 @@ class MLFlowTracker(Tracker):
190
191
  project: MlrunProject,
191
192
  reference_id: str,
192
193
  function_name: str,
193
- handler: str = None,
194
+ handler: Optional[str] = None,
194
195
  **kwargs,
195
196
  ) -> RunObject:
196
197
  """
@@ -251,9 +252,9 @@ class MLFlowTracker(Tracker):
251
252
  self,
252
253
  project: MlrunProject,
253
254
  reference_id: str,
254
- key: str = None,
255
- metrics: dict = None,
256
- extra_data: dict = None,
255
+ key: Optional[str] = None,
256
+ metrics: Optional[dict] = None,
257
+ extra_data: Optional[dict] = None,
257
258
  ) -> ModelArtifact:
258
259
  """
259
260
  Import a model from MLFlow to MLRun.
@@ -290,7 +291,7 @@ class MLFlowTracker(Tracker):
290
291
  return model
291
292
 
292
293
  def import_artifact(
293
- self, project: MlrunProject, reference_id: str, key: str = None
294
+ self, project: MlrunProject, reference_id: str, key: Optional[str] = None
294
295
  ) -> Artifact:
295
296
  """
296
297
  Import an artifact from MLFlow to MLRun.
mlrun/utils/async_http.py CHANGED
@@ -42,7 +42,7 @@ class AsyncClientWithRetry(RetryClient):
42
42
  retry_on_exception: bool = True,
43
43
  raise_for_status: bool = True,
44
44
  blacklisted_methods: typing.Optional[list[str]] = None,
45
- logger: logging.Logger = None,
45
+ logger: Optional[logging.Logger] = None,
46
46
  *args,
47
47
  **kwargs,
48
48
  ):
mlrun/utils/helpers.py CHANGED
@@ -40,7 +40,6 @@ import pandas
40
40
  import semver
41
41
  import yaml
42
42
  from dateutil import parser
43
- from mlrun_pipelines.models import PipelineRun
44
43
  from pandas import Timedelta, Timestamp
45
44
  from yaml.representer import RepresenterError
46
45
 
@@ -52,6 +51,7 @@ import mlrun.utils.regex
52
51
  import mlrun.utils.version.version
53
52
  from mlrun.common.constants import MYSQL_MEDIUMBLOB_SIZE_BYTES
54
53
  from mlrun.config import config
54
+ from mlrun_pipelines.models import PipelineRun
55
55
 
56
56
  from .logger import create_logger
57
57
  from .retryer import ( # noqa: F401
@@ -167,6 +167,7 @@ class RunKeys:
167
167
  inputs = "inputs"
168
168
  returns = "returns"
169
169
  artifacts = "artifacts"
170
+ artifact_uris = "artifact_uris"
170
171
  outputs = "outputs"
171
172
  data_stores = "data_stores"
172
173
  secrets = "secret_sources"
@@ -220,7 +221,7 @@ def verify_field_regex(
220
221
 
221
222
 
222
223
  def validate_builder_source(
223
- source: str, pull_at_runtime: bool = False, workdir: str = None
224
+ source: str, pull_at_runtime: bool = False, workdir: Optional[str] = None
224
225
  ):
225
226
  if pull_at_runtime or not source:
226
227
  return
@@ -268,12 +269,14 @@ def validate_tag_name(
268
269
  def validate_artifact_key_name(
269
270
  artifact_key: str, field_name: str, raise_on_failure: bool = True
270
271
  ) -> bool:
272
+ field_type = "key" if field_name == "artifact.key" else "db_key"
271
273
  return mlrun.utils.helpers.verify_field_regex(
272
274
  field_name,
273
275
  artifact_key,
274
276
  mlrun.utils.regex.artifact_key,
275
277
  raise_on_failure=raise_on_failure,
276
- log_message="Slashes are not permitted in the artifact key (both \\ and /)",
278
+ log_message=f"Artifact {field_type} must start and end with an alphanumeric character, and may only contain "
279
+ "letters, numbers, hyphens, underscores, and dots.",
277
280
  )
278
281
 
279
282
 
@@ -354,8 +357,8 @@ def verify_field_list_of_type(
354
357
  def verify_dict_items_type(
355
358
  name: str,
356
359
  dictionary: dict,
357
- expected_keys_types: list = None,
358
- expected_values_types: list = None,
360
+ expected_keys_types: Optional[list] = None,
361
+ expected_values_types: Optional[list] = None,
359
362
  ):
360
363
  if dictionary:
361
364
  if not isinstance(dictionary, dict):
@@ -372,7 +375,7 @@ def verify_dict_items_type(
372
375
  ) from exc
373
376
 
374
377
 
375
- def verify_list_items_type(list_, expected_types: list = None):
378
+ def verify_list_items_type(list_, expected_types: Optional[list] = None):
376
379
  if list_ and expected_types:
377
380
  list_items_types = set(map(type, list_))
378
381
  expected_types = set(expected_types)
@@ -396,6 +399,10 @@ def now_date(tz: timezone = timezone.utc) -> datetime:
396
399
  return datetime.now(tz=tz)
397
400
 
398
401
 
402
+ def datetime_min(tz: timezone = timezone.utc) -> datetime:
403
+ return datetime(1970, 1, 1, tzinfo=tz)
404
+
405
+
399
406
  datetime_now = now_date
400
407
 
401
408
 
@@ -816,7 +823,9 @@ def _convert_python_package_version_to_image_tag(version: typing.Optional[str]):
816
823
 
817
824
 
818
825
  def enrich_image_url(
819
- image_url: str, client_version: str = None, client_python_version: str = None
826
+ image_url: str,
827
+ client_version: Optional[str] = None,
828
+ client_python_version: Optional[str] = None,
820
829
  ) -> str:
821
830
  client_version = _convert_python_package_version_to_image_tag(client_version)
822
831
  server_version = _convert_python_package_version_to_image_tag(
@@ -856,7 +865,7 @@ def enrich_image_url(
856
865
 
857
866
 
858
867
  def resolve_image_tag_suffix(
859
- mlrun_version: str = None, python_version: str = None
868
+ mlrun_version: Optional[str] = None, python_version: Optional[str] = None
860
869
  ) -> str:
861
870
  """
862
871
  resolves what suffix should be appended to the image tag
@@ -947,6 +956,36 @@ def fill_function_hash(function_dict, tag=""):
947
956
  return fill_object_hash(function_dict, "hash", tag)
948
957
 
949
958
 
959
+ def fill_model_endpoint_hash(
960
+ model_endpoint: mlrun.common.schemas.ModelEndpointV2,
961
+ created_time: typing.Union[str, datetime],
962
+ ) -> str:
963
+ """
964
+ Fill the model endpoint uid field in the model endpoint object and returns it.
965
+ The uid is generated by hashing the following model endpoint fields:
966
+ - name
967
+ - model_tag
968
+ - function_name
969
+ - project
970
+ - created_time
971
+ """
972
+
973
+ name = model_endpoint.metadata.name
974
+ model_tag = model_endpoint.spec.model_tag
975
+ function_name = model_endpoint.spec.function_name
976
+ project = model_endpoint.metadata.project
977
+ created_time = (
978
+ created_time
979
+ if isinstance(created_time, str)
980
+ else created_time.isoformat(sep=" ", timespec="microseconds")
981
+ )
982
+
983
+ unique_string = f"{name}_{model_tag}_{function_name}_{project}_{created_time}"
984
+ uid = hashlib.sha1(unique_string.encode("utf-8")).hexdigest()
985
+ model_endpoint.metadata.uid = uid
986
+ return uid
987
+
988
+
950
989
  def retry_until_successful(
951
990
  backoff: int, timeout: int, logger, verbose: bool, _function, *args, **kwargs
952
991
  ):
@@ -1175,7 +1214,7 @@ def get_function(function, namespaces, reload_modules: bool = False):
1175
1214
  def get_handler_extended(
1176
1215
  handler_path: str,
1177
1216
  context=None,
1178
- class_args: dict = None,
1217
+ class_args: Optional[dict] = None,
1179
1218
  namespaces=None,
1180
1219
  reload_modules: bool = False,
1181
1220
  ):
@@ -1226,24 +1265,14 @@ def datetime_to_iso(time_obj: Optional[datetime]) -> Optional[str]:
1226
1265
  return time_obj.isoformat()
1227
1266
 
1228
1267
 
1229
- def enrich_datetime_with_tz_info(timestamp_string) -> Optional[datetime]:
1268
+ def enrich_datetime_with_tz_info(timestamp_string):
1230
1269
  if not timestamp_string:
1231
1270
  return timestamp_string
1232
1271
 
1233
1272
  if timestamp_string and not mlrun.utils.helpers.has_timezone(timestamp_string):
1234
1273
  timestamp_string += datetime.now(timezone.utc).astimezone().strftime("%z")
1235
1274
 
1236
- for _format in [
1237
- # e.g: 2021-08-25 12:00:00.000Z
1238
- "%Y-%m-%d %H:%M:%S.%f%z",
1239
- # e.g: 2024-11-11 07:44:56+0000
1240
- "%Y-%m-%d %H:%M:%S%z",
1241
- ]:
1242
- try:
1243
- return datetime.strptime(timestamp_string, _format)
1244
- except ValueError as exc:
1245
- last_exc = exc
1246
- raise last_exc
1275
+ return datetime.strptime(timestamp_string, "%Y-%m-%d %H:%M:%S.%f%z")
1247
1276
 
1248
1277
 
1249
1278
  def has_timezone(timestamp):
@@ -1694,17 +1723,22 @@ def merge_dicts_with_precedence(*dicts: dict) -> dict:
1694
1723
 
1695
1724
 
1696
1725
  def validate_component_version_compatibility(
1697
- component_name: typing.Literal["iguazio", "nuclio"], *min_versions: str
1726
+ component_name: typing.Literal["iguazio", "nuclio", "mlrun-client"],
1727
+ *min_versions: str,
1728
+ mlrun_client_version: Optional[str] = None,
1698
1729
  ):
1699
1730
  """
1700
1731
  :param component_name: Name of the component to validate compatibility for.
1701
1732
  :param min_versions: Valid minimum version(s) required, assuming no 2 versions has equal major and minor.
1733
+ :param mlrun_client_version: Client version to validate when component_name is "mlrun-client".
1702
1734
  """
1703
1735
  parsed_min_versions = [
1704
1736
  semver.VersionInfo.parse(min_version) for min_version in min_versions
1705
1737
  ]
1706
1738
  parsed_current_version = None
1707
1739
  component_current_version = None
1740
+ # For mlrun client we don't assume compatability if we fail to parse the client version
1741
+ assume_compatible = component_name not in ["mlrun-client"]
1708
1742
  try:
1709
1743
  if component_name == "iguazio":
1710
1744
  component_current_version = mlrun.mlconf.igz_version
@@ -1721,18 +1755,29 @@ def validate_component_version_compatibility(
1721
1755
  parsed_current_version = semver.VersionInfo.parse(
1722
1756
  mlrun.mlconf.nuclio_version
1723
1757
  )
1758
+ if component_name == "mlrun-client":
1759
+ # dev version, assume compatible
1760
+ if mlrun_client_version and (
1761
+ mlrun_client_version.startswith("0.0.0+")
1762
+ or "unstable" in mlrun_client_version
1763
+ ):
1764
+ return True
1765
+
1766
+ component_current_version = mlrun_client_version
1767
+ parsed_current_version = semver.Version.parse(mlrun_client_version)
1724
1768
  if not parsed_current_version:
1725
- return True
1769
+ return assume_compatible
1726
1770
  except ValueError:
1727
1771
  # only log when version is set but invalid
1728
1772
  if component_current_version:
1729
1773
  logger.warning(
1730
- "Unable to parse current version, assuming compatibility",
1774
+ "Unable to parse current version",
1731
1775
  component_name=component_name,
1732
1776
  current_version=component_current_version,
1733
1777
  min_versions=min_versions,
1778
+ assume_compatible=assume_compatible,
1734
1779
  )
1735
- return True
1780
+ return assume_compatible
1736
1781
 
1737
1782
  # Feature might have been back-ported e.g. nuclio node selection is supported from
1738
1783
  # 1.5.20 and 1.6.10 but not in 1.6.9 - therefore we reverse sort to validate against 1.6.x 1st and
@@ -1797,9 +1842,8 @@ def _reload(module, max_recursion_depth):
1797
1842
  def run_with_retry(
1798
1843
  retry_count: int,
1799
1844
  func: typing.Callable,
1800
- retry_on_exceptions: typing.Union[
1801
- type[Exception],
1802
- tuple[type[Exception]],
1845
+ retry_on_exceptions: Optional[
1846
+ typing.Union[type[Exception], tuple[type[Exception]]]
1803
1847
  ] = None,
1804
1848
  *args,
1805
1849
  **kwargs,