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/__init__.py CHANGED
@@ -12,8 +12,6 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
- # flake8: noqa - this is until we take care of the F401 violations with respect to __all__ & sphinx
16
-
17
15
  __all__ = [
18
16
  "get_version",
19
17
  "set_environment",
@@ -29,9 +27,9 @@ __all__ = [
29
27
  ]
30
28
 
31
29
  from os import environ, path
30
+ from typing import Optional
32
31
 
33
32
  import dotenv
34
- import mlrun_pipelines
35
33
 
36
34
  from .config import config as mlconf
37
35
  from .datastore import DataItem, store_manager
@@ -63,16 +61,16 @@ from .run import (
63
61
  new_function,
64
62
  wait_for_pipeline_completion,
65
63
  )
66
- from .runtimes import new_model_server
64
+ from .runtimes import mounts, new_model_server
67
65
  from .secrets import get_secret_or_env
68
66
  from .utils.version import Version
69
67
 
70
68
  __version__ = Version().get()["version"]
71
69
 
72
- VolumeMount = mlrun_pipelines.common.mounts.VolumeMount
73
- mount_v3io = mlrun_pipelines.mounts.mount_v3io
74
- v3io_cred = mlrun_pipelines.mounts.v3io_cred
75
- auto_mount = mlrun_pipelines.mounts.auto_mount
70
+ VolumeMount = mounts.VolumeMount
71
+ mount_v3io = mounts.mount_v3io
72
+ v3io_cred = mounts.v3io_cred
73
+ auto_mount = mounts.auto_mount
76
74
 
77
75
 
78
76
  def get_version():
@@ -88,12 +86,12 @@ if "IGZ_NAMESPACE_DOMAIN" in environ:
88
86
 
89
87
 
90
88
  def set_environment(
91
- api_path: str = None,
89
+ api_path: Optional[str] = None,
92
90
  artifact_path: str = "",
93
- access_key: str = None,
94
- username: str = None,
95
- env_file: str = None,
96
- mock_functions: str = None,
91
+ access_key: Optional[str] = None,
92
+ username: Optional[str] = None,
93
+ env_file: Optional[str] = None,
94
+ mock_functions: Optional[str] = None,
97
95
  ):
98
96
  """set and test default config for: api path, artifact_path and project
99
97
 
@@ -136,15 +134,16 @@ def set_environment(
136
134
  if not mlconf.dbpath:
137
135
  raise ValueError("DB/API path was not detected, please specify its address")
138
136
 
139
- if mock_functions is not None:
140
- mock_functions = "1" if mock_functions is True else mock_functions
141
- mlconf.force_run_local = mock_functions
142
- mlconf.mock_nuclio_deployment = mock_functions
143
-
144
137
  # check connectivity and load remote defaults
145
138
  get_run_db()
146
139
  if api_path:
147
140
  environ["MLRUN_DBPATH"] = mlconf.dbpath
141
+ mlconf.reload()
142
+
143
+ if mock_functions is not None:
144
+ mock_functions = "1" if mock_functions is True else mock_functions
145
+ mlconf.force_run_local = mock_functions
146
+ mlconf.mock_nuclio_deployment = mock_functions
148
147
 
149
148
  if not mlconf.artifact_path and not artifact_path:
150
149
  raise ValueError(
@@ -159,6 +158,7 @@ def set_environment(
159
158
  "artifact_path must refer to an absolute path" " or a valid url"
160
159
  )
161
160
  mlconf.artifact_path = artifact_path
161
+
162
162
  return mlconf.default_project, mlconf.artifact_path
163
163
 
164
164
 
mlrun/__main__.py CHANGED
@@ -27,13 +27,13 @@ import click
27
27
  import dotenv
28
28
  import pandas as pd
29
29
  import yaml
30
- from mlrun_pipelines.mounts import auto_mount as auto_mount_modifier
31
30
  from tabulate import tabulate
32
31
 
33
32
  import mlrun
34
33
  import mlrun.common.constants as mlrun_constants
35
34
  import mlrun.common.schemas
36
35
  from mlrun.common.helpers import parse_versioned_object_uri
36
+ from mlrun.runtimes.mounts import auto_mount as auto_mount_modifier
37
37
 
38
38
  from .config import config as mlconf
39
39
  from .db import get_run_db
@@ -1248,10 +1248,10 @@ def show_or_set_config(
1248
1248
  }
1249
1249
  for key, value in env_dict.items():
1250
1250
  if value:
1251
- dotenv.set_key(filename, key, value, quote_mode="")
1251
+ dotenv.set_key(filename, key, value, quote_mode="always")
1252
1252
  if env_vars:
1253
1253
  for key, value in list2dict(env_vars).items():
1254
- dotenv.set_key(filename, key, value, quote_mode="")
1254
+ dotenv.set_key(filename, key, value, quote_mode="always")
1255
1255
  if env_file:
1256
1256
  # if its not the default file print the usage details
1257
1257
  print(
mlrun/alerts/alert.py CHANGED
@@ -12,7 +12,7 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
- from typing import Union
15
+ from typing import Optional, Union
16
16
 
17
17
  import mlrun
18
18
  import mlrun.common.schemas.alert as alert_objects
@@ -40,21 +40,21 @@ class AlertConfig(ModelObj):
40
40
 
41
41
  def __init__(
42
42
  self,
43
- project: str = None,
44
- name: str = None,
43
+ project: Optional[str] = None,
44
+ name: Optional[str] = None,
45
45
  template: Union[alert_objects.AlertTemplate, str] = None,
46
- description: str = None,
47
- summary: str = None,
46
+ description: Optional[str] = None,
47
+ summary: Optional[str] = None,
48
48
  severity: alert_objects.AlertSeverity = None,
49
49
  trigger: alert_objects.AlertTrigger = None,
50
50
  criteria: alert_objects.AlertCriteria = None,
51
51
  reset_policy: alert_objects.ResetPolicy = None,
52
- notifications: list[alert_objects.AlertNotification] = None,
52
+ notifications: Optional[list[alert_objects.AlertNotification]] = None,
53
53
  entities: alert_objects.EventEntities = None,
54
- id: int = None,
54
+ id: Optional[int] = None,
55
55
  state: alert_objects.AlertActiveState = None,
56
- created: str = None,
57
- count: int = None,
56
+ created: Optional[str] = None,
57
+ count: Optional[int] = None,
58
58
  ):
59
59
  """Alert config object
60
60
 
@@ -142,7 +142,7 @@ class AlertConfig(ModelObj):
142
142
  raise mlrun.errors.MLRunInvalidArgumentError("Alert name must be provided")
143
143
 
144
144
  def _serialize_field(
145
- self, struct: dict, field_name: str = None, strip: bool = False
145
+ self, struct: dict, field_name: Optional[str] = None, strip: bool = False
146
146
  ):
147
147
  if field_name == "entities":
148
148
  if self.entities:
@@ -179,7 +179,12 @@ class AlertConfig(ModelObj):
179
179
  return None
180
180
  return super()._serialize_field(struct, field_name, strip)
181
181
 
182
- def to_dict(self, fields: list = None, exclude: list = None, strip: bool = False):
182
+ def to_dict(
183
+ self,
184
+ fields: Optional[list] = None,
185
+ exclude: Optional[list] = None,
186
+ strip: bool = False,
187
+ ):
183
188
  if self.entities is None:
184
189
  raise mlrun.errors.MLRunBadRequestError("Alert entity field is missing")
185
190
  if not self.notifications:
@@ -189,7 +194,9 @@ class AlertConfig(ModelObj):
189
194
  return super().to_dict(self._dict_fields)
190
195
 
191
196
  @classmethod
192
- def from_dict(cls, struct=None, fields=None, deprecated_fields: dict = None):
197
+ def from_dict(
198
+ cls, struct=None, fields=None, deprecated_fields: Optional[dict] = None
199
+ ):
193
200
  new_obj = super().from_dict(struct, fields=fields)
194
201
 
195
202
  entity_data = struct.get("entities")
@@ -12,8 +12,6 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
- # flake8: noqa - this is until we take care of the F401 violations with respect to __all__ & sphinx
16
-
17
15
  # Don't remove this, used by sphinx documentation
18
16
  __all__ = ["get_model", "update_model"]
19
17
 
mlrun/artifacts/base.py CHANGED
@@ -62,14 +62,21 @@ class ArtifactMetadata(ModelObj):
62
62
  def base_dict(self):
63
63
  return super().to_dict()
64
64
 
65
- def to_dict(self, fields: list = None, exclude: list = None, strip: bool = False):
65
+ def to_dict(
66
+ self,
67
+ fields: typing.Optional[list] = None,
68
+ exclude: typing.Optional[list] = None,
69
+ strip: bool = False,
70
+ ):
66
71
  """return long dict form of the artifact"""
67
72
  return super().to_dict(
68
73
  self._dict_fields + self._extra_fields, exclude=exclude, strip=strip
69
74
  )
70
75
 
71
76
  @classmethod
72
- def from_dict(cls, struct=None, fields=None, deprecated_fields: dict = None):
77
+ def from_dict(
78
+ cls, struct=None, fields=None, deprecated_fields: typing.Optional[dict] = None
79
+ ):
73
80
  fields = fields or cls._dict_fields + cls._extra_fields
74
81
  return super().from_dict(
75
82
  struct, fields=fields, deprecated_fields=deprecated_fields
@@ -109,7 +116,7 @@ class ArtifactSpec(ModelObj):
109
116
  db_key=None,
110
117
  extra_data=None,
111
118
  body=None,
112
- unpackaging_instructions: dict = None,
119
+ unpackaging_instructions: typing.Optional[dict] = None,
113
120
  ):
114
121
  self.src_path = src_path
115
122
  self.target_path = target_path
@@ -131,14 +138,21 @@ class ArtifactSpec(ModelObj):
131
138
  def base_dict(self):
132
139
  return super().to_dict()
133
140
 
134
- def to_dict(self, fields: list = None, exclude: list = None, strip: bool = False):
141
+ def to_dict(
142
+ self,
143
+ fields: typing.Optional[list] = None,
144
+ exclude: typing.Optional[list] = None,
145
+ strip: bool = False,
146
+ ):
135
147
  """return long dict form of the artifact"""
136
148
  return super().to_dict(
137
149
  self._dict_fields + self._extra_fields, exclude=exclude, strip=strip
138
150
  )
139
151
 
140
152
  @classmethod
141
- def from_dict(cls, struct=None, fields=None, deprecated_fields: dict = None):
153
+ def from_dict(
154
+ cls, struct=None, fields=None, deprecated_fields: typing.Optional[dict] = None
155
+ ):
142
156
  fields = fields or cls._dict_fields + cls._extra_fields
143
157
  return super().from_dict(
144
158
  struct, fields=fields, deprecated_fields=deprecated_fields
@@ -192,7 +206,7 @@ class Artifact(ModelObj):
192
206
  size=None,
193
207
  target_path=None,
194
208
  project=None,
195
- src_path: str = None,
209
+ src_path: typing.Optional[str] = None,
196
210
  # All params up until here are legacy params for compatibility with legacy artifacts.
197
211
  # TODO: remove them in 1.9.0.
198
212
  metadata: ArtifactMetadata = None,
@@ -366,7 +380,7 @@ class Artifact(ModelObj):
366
380
  struct[field] = val.base_dict()
367
381
  return struct
368
382
 
369
- def upload(self, artifact_path: str = None):
383
+ def upload(self, artifact_path: typing.Optional[str] = None):
370
384
  """
371
385
  internal, upload to target store
372
386
  :param artifact_path: required only for when generating target_path from artifact hash
@@ -379,7 +393,9 @@ class Artifact(ModelObj):
379
393
  if src_path and os.path.isfile(src_path):
380
394
  self._upload_file(source_path=src_path, artifact_path=artifact_path)
381
395
 
382
- def _upload_body(self, body, target=None, artifact_path: str = None):
396
+ def _upload_body(
397
+ self, body, target=None, artifact_path: typing.Optional[str] = None
398
+ ):
383
399
  body_hash = None
384
400
  if not target and not self.spec.target_path:
385
401
  if not mlrun.mlconf.artifacts.generate_target_path_from_artifact_hash:
@@ -400,7 +416,10 @@ class Artifact(ModelObj):
400
416
  )
401
417
 
402
418
  def _upload_file(
403
- self, source_path: str, target_path: str = None, artifact_path: str = None
419
+ self,
420
+ source_path: str,
421
+ target_path: typing.Optional[str] = None,
422
+ artifact_path: typing.Optional[str] = None,
404
423
  ):
405
424
  file_hash = None
406
425
  if not target_path and not self.spec.target_path:
@@ -651,7 +670,7 @@ class DirArtifact(Artifact):
651
670
  def is_dir(self):
652
671
  return True
653
672
 
654
- def upload(self, artifact_path: str = None):
673
+ def upload(self, artifact_path: typing.Optional[str] = None):
655
674
  """
656
675
  internal, upload to target store
657
676
  :param artifact_path: required only for when generating target_path from artifact hash
@@ -758,13 +777,17 @@ def upload_extra_data(
758
777
  extra_data: dict,
759
778
  prefix="",
760
779
  update_spec=False,
761
- artifact_path: str = None,
780
+ artifact_path: typing.Optional[str] = None,
762
781
  ):
763
782
  """upload extra data to the artifact store"""
764
783
  if not extra_data:
765
784
  return
766
785
  target_path = artifact.target_path
767
786
  for key, item in extra_data.items():
787
+ if item is ...:
788
+ # Skip future links (packagers feature for linking artifacts before they are logged)
789
+ continue
790
+
768
791
  if isinstance(item, bytes):
769
792
  if target_path:
770
793
  target = os.path.join(target_path, prefix + key)
@@ -149,16 +149,16 @@ class DatasetArtifact(Artifact):
149
149
 
150
150
  def __init__(
151
151
  self,
152
- key: str = None,
152
+ key: Optional[str] = None,
153
153
  df=None,
154
- preview: int = None,
154
+ preview: Optional[int] = None,
155
155
  format: str = "", # TODO: should be changed to 'fmt'.
156
- stats: bool = None,
157
- target_path: str = None,
158
- extra_data: dict = None,
159
- column_metadata: dict = None,
156
+ stats: Optional[bool] = None,
157
+ target_path: Optional[str] = None,
158
+ extra_data: Optional[dict] = None,
159
+ column_metadata: Optional[dict] = None,
160
160
  ignore_preview_limits: bool = False,
161
- label_column: str = None,
161
+ label_column: Optional[str] = None,
162
162
  **kwargs,
163
163
  ):
164
164
  if key or format or target_path:
@@ -207,7 +207,7 @@ class DatasetArtifact(Artifact):
207
207
  def spec(self, spec):
208
208
  self._spec = self._verify_dict(spec, "spec", DatasetArtifactSpec)
209
209
 
210
- def upload(self, artifact_path: str = None):
210
+ def upload(self, artifact_path: Optional[str] = None):
211
211
  """
212
212
  internal, upload to target store
213
213
  :param artifact_path: required only for when generating target_path from artifact hash
@@ -396,13 +396,13 @@ def get_df_stats(df):
396
396
  def update_dataset_meta(
397
397
  artifact,
398
398
  from_df=None,
399
- schema: dict = None,
400
- header: list = None,
401
- preview: list = None,
402
- stats: dict = None,
403
- extra_data: dict = None,
404
- column_metadata: dict = None,
405
- labels: dict = None,
399
+ schema: Optional[dict] = None,
400
+ header: Optional[list] = None,
401
+ preview: Optional[list] = None,
402
+ stats: Optional[dict] = None,
403
+ extra_data: Optional[dict] = None,
404
+ column_metadata: Optional[dict] = None,
405
+ labels: Optional[dict] = None,
406
406
  ignore_preview_limits: bool = False,
407
407
  ):
408
408
  """Update dataset object attributes/metadata
@@ -495,4 +495,4 @@ def upload_dataframe(
495
495
  size = target_class(path=target_path).write_dataframe(df, **kw)
496
496
  return size, None
497
497
 
498
- raise mlrun.errors.MLRunInvalidArgumentError(f"format {format} not implemented yet")
498
+ raise mlrun.errors.MLRunInvalidArgumentError(f"Format {format} not implemented yet")
@@ -124,7 +124,7 @@ class ArtifactManager:
124
124
 
125
125
  self.artifact_db = db
126
126
  self.input_artifacts = {}
127
- self.artifacts = {}
127
+ self.artifact_uris = {}
128
128
 
129
129
  @staticmethod
130
130
  def ensure_artifact_source_file_exists(item, path, body):
@@ -156,14 +156,12 @@ class ArtifactManager:
156
156
 
157
157
  def artifact_list(self, full=False):
158
158
  artifacts = []
159
- for artifact in self.artifacts.values():
160
- if isinstance(artifact, dict):
161
- artifacts.append(artifact)
159
+ for artifacts_uri in self.artifact_uris.values():
160
+ artifact: Artifact = mlrun.datastore.get_store_resource(artifacts_uri)
161
+ if full:
162
+ artifacts.append(artifact.to_dict())
162
163
  else:
163
- if full:
164
- artifacts.append(artifact.to_dict())
165
- else:
166
- artifacts.append(artifact.base_dict())
164
+ artifacts.append(artifact.base_dict())
167
165
  return artifacts
168
166
 
169
167
  def log_artifact(
@@ -246,6 +244,8 @@ class ArtifactManager:
246
244
  # otherwise, we do not want to override it.
247
245
  # this is mainly relevant for imported artifacts that have an explicit db_key value already set
248
246
  db_key = item.db_key or key
247
+ if db_key != key:
248
+ validate_artifact_key_name(db_key, "artifact.db_key")
249
249
  item.db_key = db_key or ""
250
250
  item.viewer = viewer or item.viewer
251
251
  item.tree = producer.tag
@@ -304,7 +304,7 @@ class ArtifactManager:
304
304
  item.target_path = target_path
305
305
 
306
306
  item.before_log()
307
- self.artifacts[key] = item
307
+ self.artifact_uris[key] = item.uri
308
308
 
309
309
  if ((upload is None and item.kind != "dir") or upload) and not item.is_inline():
310
310
  # before uploading the item, we want to ensure that its tags are valid,
@@ -317,12 +317,12 @@ class ArtifactManager:
317
317
  size = str(item.size) or "?"
318
318
  db_str = "Y" if (self.artifact_db and db_key) else "N"
319
319
  logger.debug(
320
- f"log artifact {key} at {item.target_path}, size: {size}, db: {db_str}"
320
+ f"Log artifact {key} at {item.target_path}, size: {size}, db: {db_str}"
321
321
  )
322
322
  return item
323
323
 
324
- def update_artifact(self, producer, item):
325
- self.artifacts[item.key] = item
324
+ def update_artifact(self, producer, item: Artifact):
325
+ self.artifact_uris[item.key] = item.uri
326
326
  self._log_to_db(item.db_key, producer.project, producer.inputs, item)
327
327
 
328
328
  def _log_to_db(self, key, project, sources, item, tag=None):
@@ -387,7 +387,7 @@ class ArtifactManager:
387
387
  deletion_strategy: mlrun.common.schemas.artifact.ArtifactsDeletionStrategies = (
388
388
  mlrun.common.schemas.artifact.ArtifactsDeletionStrategies.metadata_only
389
389
  ),
390
- secrets: dict = None,
390
+ secrets: typing.Optional[dict] = None,
391
391
  ):
392
392
  self.artifact_db.del_artifact(
393
393
  key=item.db_key,
mlrun/artifacts/model.py CHANGED
@@ -303,7 +303,7 @@ class ModelArtifact(Artifact):
303
303
  self.metadata.labels = self.metadata.labels or {}
304
304
  self.metadata.labels["framework"] = self.spec.framework
305
305
 
306
- def upload(self, artifact_path: str = None):
306
+ def upload(self, artifact_path: Optional[str] = None):
307
307
  """
308
308
  internal, upload to target store
309
309
  :param artifact_path: required only for when generating target_path from artifact hash
@@ -324,9 +324,7 @@ class ModelArtifact(Artifact):
324
324
  artifact=self, extra_data=self.spec.extra_data, artifact_path=artifact_path
325
325
  )
326
326
 
327
- # the model spec yaml should not include the tag, as the same model can be used with different tags,
328
- # and the tag is not part of the model spec but the metadata of the model artifact
329
- spec_body = _remove_tag_from_spec_yaml(self)
327
+ spec_body = _sanitize_and_serialize_model_spec_yaml(self)
330
328
  spec_target_path = None
331
329
 
332
330
  if mlrun.mlconf.artifacts.generate_target_path_from_artifact_hash:
@@ -355,7 +353,7 @@ class ModelArtifact(Artifact):
355
353
  def _upload_body_or_file(
356
354
  self,
357
355
  artifact_path: str,
358
- target_model_path: str = None,
356
+ target_model_path: Optional[str] = None,
359
357
  ):
360
358
  body = self.spec.get_body()
361
359
  if body:
@@ -403,12 +401,6 @@ class ModelArtifact(Artifact):
403
401
  return mlrun.get_dataitem(target_model_path).get()
404
402
 
405
403
 
406
- def _get_src_path(model_spec: ModelArtifact, filename):
407
- if model_spec.src_path:
408
- return path.join(model_spec.src_path, filename)
409
- return filename
410
-
411
-
412
404
  def get_model(model_dir, suffix=""):
413
405
  """return model file, model spec object, and list of extra data items
414
406
 
@@ -483,49 +475,20 @@ def get_model(model_dir, suffix=""):
483
475
  return temp_path, model_spec, extra_dataitems
484
476
 
485
477
 
486
- def _load_model_spec(spec_path):
487
- data = mlrun.datastore.store_manager.object(url=spec_path).get()
488
- spec = yaml.load(data, Loader=yaml.FullLoader)
489
- return ModelArtifact.from_dict(spec)
490
-
491
-
492
- def _get_file_path(base_path: str, name: str, isdir=False):
493
- if not is_relative_path(name):
494
- return name
495
- if not isdir:
496
- base_path = path.dirname(base_path)
497
- return path.join(base_path, name).replace("\\", "/")
498
-
499
-
500
- def _get_extra(target, extra_data, is_dir=False):
501
- extra_dataitems = {}
502
- for k, v in extra_data.items():
503
- extra_dataitems[k] = mlrun.datastore.store_manager.object(
504
- url=_get_file_path(target, v, isdir=is_dir), key=k
505
- )
506
- return extra_dataitems
507
-
508
-
509
- def _remove_tag_from_spec_yaml(model_spec):
510
- spec_dict = model_spec.to_dict()
511
- spec_dict["metadata"].pop("tag", None)
512
- return yaml.safe_dump(spec_dict)
513
-
514
-
515
478
  def update_model(
516
479
  model_artifact,
517
- parameters: dict = None,
518
- metrics: dict = None,
519
- extra_data: dict = None,
520
- inputs: list[Feature] = None,
521
- outputs: list[Feature] = None,
522
- feature_vector: str = None,
523
- feature_weights: list = None,
480
+ parameters: Optional[dict] = None,
481
+ metrics: Optional[dict] = None,
482
+ extra_data: Optional[dict] = None,
483
+ inputs: Optional[list[Feature]] = None,
484
+ outputs: Optional[list[Feature]] = None,
485
+ feature_vector: Optional[str] = None,
486
+ feature_weights: Optional[list] = None,
524
487
  key_prefix: str = "",
525
- labels: dict = None,
488
+ labels: Optional[dict] = None,
526
489
  write_spec_copy=True,
527
490
  store_object: bool = True,
528
- ):
491
+ ) -> ModelArtifact:
529
492
  """Update model object attributes
530
493
 
531
494
  this method will edit or add attributes to a model object
@@ -593,10 +556,7 @@ def update_model(
593
556
 
594
557
  if write_spec_copy:
595
558
  spec_path = path.join(model_spec.target_path, model_spec_filename)
596
-
597
- # the model spec yaml should not include the tag, as the same model can be used with different tags,
598
- # and the tag is not part of the model spec but the metadata of the model artifact
599
- model_spec_yaml = _remove_tag_from_spec_yaml(model_spec)
559
+ model_spec_yaml = _sanitize_and_serialize_model_spec_yaml(model_spec)
600
560
  mlrun.datastore.store_manager.object(url=spec_path).put(model_spec_yaml)
601
561
 
602
562
  model_spec.db_key = model_spec.db_key or model_spec.key
@@ -609,3 +569,56 @@ def update_model(
609
569
  project=model_spec.project,
610
570
  )
611
571
  return model_spec
572
+
573
+
574
+ def _get_src_path(model_spec: ModelArtifact, filename: str) -> str:
575
+ return path.join(model_spec.src_path, filename) if model_spec.src_path else filename
576
+
577
+
578
+ def _load_model_spec(spec_path) -> ModelArtifact:
579
+ data = mlrun.datastore.store_manager.object(url=spec_path).get()
580
+ spec = yaml.load(data, Loader=yaml.FullLoader)
581
+ return ModelArtifact.from_dict(spec)
582
+
583
+
584
+ def _get_file_path(base_path: str, name: str, isdir: bool = False) -> str:
585
+ if not is_relative_path(name):
586
+ return name
587
+ if not isdir:
588
+ base_path = path.dirname(base_path)
589
+ return path.join(base_path, name).replace("\\", "/")
590
+
591
+
592
+ def _get_extra(target: str, extra_data: dict, is_dir: bool = False) -> dict:
593
+ extra_dataitems = {}
594
+ for k, v in extra_data.items():
595
+ extra_dataitems[k] = mlrun.datastore.store_manager.object(
596
+ url=_get_file_path(target, v, isdir=is_dir), key=k
597
+ )
598
+ return extra_dataitems
599
+
600
+
601
+ def _sanitize_and_serialize_model_spec_yaml(model: ModelArtifact) -> str:
602
+ model_dict = _sanitize_model_spec(model)
603
+ return _serialize_model_spec_yaml(model_dict)
604
+
605
+
606
+ def _sanitize_model_spec(model: ModelArtifact) -> dict:
607
+ model_dict = model.to_dict()
608
+
609
+ # The model spec yaml should not include the tag, as the same model can be used with different tags,
610
+ # and the tag is not part of the model spec but the metadata of the model artifact
611
+ model_dict["metadata"].pop("tag", None)
612
+
613
+ # Remove future packaging links
614
+ if model_dict["spec"].get("extra_data"):
615
+ model_dict["spec"]["extra_data"] = {
616
+ key: item
617
+ for key, item in model_dict["spec"]["extra_data"].items()
618
+ if item is not ...
619
+ }
620
+ return model_dict
621
+
622
+
623
+ def _serialize_model_spec_yaml(model_dict: dict) -> str:
624
+ return yaml.safe_dump(model_dict)
mlrun/common/constants.py CHANGED
@@ -11,6 +11,7 @@
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
+ import mlrun.common.types
14
15
 
15
16
  IMAGE_NAME_ENRICH_REGISTRY_PREFIX = "." # prefix for image name to enrich with registry
16
17
  MLRUN_SERVING_CONF = "serving-conf"
@@ -86,3 +87,8 @@ class MLRunInternalLabels:
86
87
  for key, value in cls.__dict__.items()
87
88
  if not key.startswith("__") and isinstance(value, str)
88
89
  ]
90
+
91
+
92
+ class DeployStatusTextKind(mlrun.common.types.StrEnum):
93
+ logs = "logs"
94
+ events = "events"
@@ -19,3 +19,4 @@ from .pipeline import PipelineFormat # noqa
19
19
  from .project import ProjectFormat # noqa
20
20
  from .run import RunFormat # noqa
21
21
  from .feature_set import FeatureSetFormat # noqa
22
+ from .model_endpoint import ModelEndpointFormat # noqa
@@ -21,6 +21,7 @@ from .base import ObjectFormat
21
21
 
22
22
 
23
23
  class FeatureSetFormat(ObjectFormat, mlrun.common.types.StrEnum):
24
+ full = "full"
24
25
  minimal = "minimal"
25
26
 
26
27
  @staticmethod
@@ -21,6 +21,7 @@ from .base import ObjectFormat
21
21
 
22
22
 
23
23
  class FunctionFormat(ObjectFormat, mlrun.common.types.StrEnum):
24
+ full = "full"
24
25
  minimal = "minimal"
25
26
 
26
27
  @staticmethod