mlrun 1.7.1rc4__py3-none-any.whl → 1.8.0rc8__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 (257) hide show
  1. mlrun/__init__.py +23 -21
  2. mlrun/__main__.py +3 -3
  3. mlrun/alerts/alert.py +148 -14
  4. mlrun/artifacts/__init__.py +1 -2
  5. mlrun/artifacts/base.py +46 -12
  6. mlrun/artifacts/dataset.py +16 -16
  7. mlrun/artifacts/document.py +334 -0
  8. mlrun/artifacts/manager.py +15 -13
  9. mlrun/artifacts/model.py +66 -53
  10. mlrun/common/constants.py +7 -0
  11. mlrun/common/formatters/__init__.py +1 -0
  12. mlrun/common/formatters/feature_set.py +1 -0
  13. mlrun/common/formatters/function.py +1 -0
  14. mlrun/{model_monitoring/db/stores/base/__init__.py → common/formatters/model_endpoint.py} +16 -1
  15. mlrun/common/formatters/pipeline.py +1 -2
  16. mlrun/common/formatters/project.py +9 -0
  17. mlrun/common/model_monitoring/__init__.py +0 -5
  18. mlrun/common/model_monitoring/helpers.py +1 -29
  19. mlrun/common/runtimes/constants.py +1 -2
  20. mlrun/common/schemas/__init__.py +6 -2
  21. mlrun/common/schemas/alert.py +111 -19
  22. mlrun/common/schemas/api_gateway.py +3 -3
  23. mlrun/common/schemas/artifact.py +11 -7
  24. mlrun/common/schemas/auth.py +6 -4
  25. mlrun/common/schemas/background_task.py +7 -7
  26. mlrun/common/schemas/client_spec.py +2 -3
  27. mlrun/common/schemas/clusterization_spec.py +2 -2
  28. mlrun/common/schemas/common.py +53 -3
  29. mlrun/common/schemas/constants.py +15 -0
  30. mlrun/common/schemas/datastore_profile.py +1 -1
  31. mlrun/common/schemas/feature_store.py +9 -9
  32. mlrun/common/schemas/frontend_spec.py +4 -4
  33. mlrun/common/schemas/function.py +10 -10
  34. mlrun/common/schemas/hub.py +1 -1
  35. mlrun/common/schemas/k8s.py +3 -3
  36. mlrun/common/schemas/memory_reports.py +3 -3
  37. mlrun/common/schemas/model_monitoring/__init__.py +2 -1
  38. mlrun/common/schemas/model_monitoring/constants.py +66 -14
  39. mlrun/common/schemas/model_monitoring/grafana.py +1 -1
  40. mlrun/common/schemas/model_monitoring/model_endpoints.py +91 -147
  41. mlrun/common/schemas/notification.py +24 -3
  42. mlrun/common/schemas/object.py +1 -1
  43. mlrun/common/schemas/pagination.py +4 -4
  44. mlrun/common/schemas/partition.py +137 -0
  45. mlrun/common/schemas/pipeline.py +2 -2
  46. mlrun/common/schemas/project.py +25 -17
  47. mlrun/common/schemas/runs.py +2 -2
  48. mlrun/common/schemas/runtime_resource.py +5 -5
  49. mlrun/common/schemas/schedule.py +1 -1
  50. mlrun/common/schemas/secret.py +1 -1
  51. mlrun/common/schemas/tag.py +3 -3
  52. mlrun/common/schemas/workflow.py +5 -5
  53. mlrun/config.py +67 -10
  54. mlrun/data_types/__init__.py +0 -2
  55. mlrun/data_types/infer.py +3 -1
  56. mlrun/data_types/spark.py +2 -1
  57. mlrun/datastore/__init__.py +0 -2
  58. mlrun/datastore/alibaba_oss.py +4 -1
  59. mlrun/datastore/azure_blob.py +4 -1
  60. mlrun/datastore/base.py +12 -4
  61. mlrun/datastore/datastore.py +9 -3
  62. mlrun/datastore/datastore_profile.py +79 -20
  63. mlrun/datastore/dbfs_store.py +4 -1
  64. mlrun/datastore/filestore.py +4 -1
  65. mlrun/datastore/google_cloud_storage.py +4 -1
  66. mlrun/datastore/hdfs.py +4 -1
  67. mlrun/datastore/inmem.py +4 -1
  68. mlrun/datastore/redis.py +4 -1
  69. mlrun/datastore/s3.py +4 -1
  70. mlrun/datastore/sources.py +52 -51
  71. mlrun/datastore/store_resources.py +0 -2
  72. mlrun/datastore/targets.py +21 -21
  73. mlrun/datastore/utils.py +2 -2
  74. mlrun/datastore/v3io.py +4 -1
  75. mlrun/datastore/vectorstore.py +194 -0
  76. mlrun/datastore/wasbfs/fs.py +13 -12
  77. mlrun/db/base.py +208 -82
  78. mlrun/db/factory.py +0 -3
  79. mlrun/db/httpdb.py +1237 -386
  80. mlrun/db/nopdb.py +201 -74
  81. mlrun/errors.py +2 -2
  82. mlrun/execution.py +136 -50
  83. mlrun/feature_store/__init__.py +0 -2
  84. mlrun/feature_store/api.py +41 -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 +117 -46
  158. mlrun/model_monitoring/__init__.py +4 -4
  159. mlrun/model_monitoring/api.py +61 -59
  160. mlrun/model_monitoring/applications/_application_steps.py +17 -17
  161. mlrun/model_monitoring/applications/base.py +165 -6
  162. mlrun/model_monitoring/applications/context.py +88 -37
  163. mlrun/model_monitoring/applications/evidently_base.py +1 -2
  164. mlrun/model_monitoring/applications/histogram_data_drift.py +43 -21
  165. mlrun/model_monitoring/applications/results.py +55 -3
  166. mlrun/model_monitoring/controller.py +207 -239
  167. mlrun/model_monitoring/db/__init__.py +0 -2
  168. mlrun/model_monitoring/db/_schedules.py +156 -0
  169. mlrun/model_monitoring/db/_stats.py +189 -0
  170. mlrun/model_monitoring/db/tsdb/base.py +78 -25
  171. mlrun/model_monitoring/db/tsdb/tdengine/schemas.py +90 -16
  172. mlrun/model_monitoring/db/tsdb/tdengine/stream_graph_steps.py +33 -0
  173. mlrun/model_monitoring/db/tsdb/tdengine/tdengine_connector.py +279 -59
  174. mlrun/model_monitoring/db/tsdb/v3io/stream_graph_steps.py +1 -0
  175. mlrun/model_monitoring/db/tsdb/v3io/v3io_connector.py +78 -17
  176. mlrun/model_monitoring/helpers.py +152 -49
  177. mlrun/model_monitoring/stream_processing.py +99 -283
  178. mlrun/model_monitoring/tracking_policy.py +10 -3
  179. mlrun/model_monitoring/writer.py +48 -36
  180. mlrun/package/__init__.py +3 -6
  181. mlrun/package/context_handler.py +1 -1
  182. mlrun/package/packager.py +12 -9
  183. mlrun/package/packagers/__init__.py +0 -2
  184. mlrun/package/packagers/default_packager.py +14 -11
  185. mlrun/package/packagers/numpy_packagers.py +16 -7
  186. mlrun/package/packagers/pandas_packagers.py +18 -18
  187. mlrun/package/packagers/python_standard_library_packagers.py +25 -11
  188. mlrun/package/packagers_manager.py +31 -14
  189. mlrun/package/utils/__init__.py +0 -3
  190. mlrun/package/utils/_pickler.py +6 -6
  191. mlrun/platforms/__init__.py +47 -16
  192. mlrun/platforms/iguazio.py +4 -1
  193. mlrun/projects/operations.py +27 -27
  194. mlrun/projects/pipelines.py +75 -38
  195. mlrun/projects/project.py +865 -206
  196. mlrun/run.py +53 -10
  197. mlrun/runtimes/__init__.py +1 -3
  198. mlrun/runtimes/base.py +15 -11
  199. mlrun/runtimes/daskjob.py +9 -9
  200. mlrun/runtimes/generators.py +2 -1
  201. mlrun/runtimes/kubejob.py +4 -5
  202. mlrun/runtimes/mounts.py +572 -0
  203. mlrun/runtimes/mpijob/__init__.py +0 -2
  204. mlrun/runtimes/mpijob/abstract.py +7 -6
  205. mlrun/runtimes/nuclio/api_gateway.py +7 -7
  206. mlrun/runtimes/nuclio/application/application.py +11 -11
  207. mlrun/runtimes/nuclio/function.py +19 -17
  208. mlrun/runtimes/nuclio/serving.py +18 -11
  209. mlrun/runtimes/pod.py +154 -45
  210. mlrun/runtimes/remotesparkjob.py +3 -2
  211. mlrun/runtimes/sparkjob/__init__.py +0 -2
  212. mlrun/runtimes/sparkjob/spark3job.py +21 -11
  213. mlrun/runtimes/utils.py +6 -5
  214. mlrun/serving/merger.py +6 -4
  215. mlrun/serving/remote.py +18 -17
  216. mlrun/serving/routers.py +185 -172
  217. mlrun/serving/server.py +7 -1
  218. mlrun/serving/states.py +97 -78
  219. mlrun/serving/utils.py +13 -2
  220. mlrun/serving/v1_serving.py +3 -2
  221. mlrun/serving/v2_serving.py +74 -65
  222. mlrun/track/__init__.py +1 -1
  223. mlrun/track/tracker.py +2 -2
  224. mlrun/track/trackers/mlflow_tracker.py +6 -5
  225. mlrun/utils/async_http.py +1 -1
  226. mlrun/utils/clones.py +1 -1
  227. mlrun/utils/helpers.py +66 -18
  228. mlrun/utils/logger.py +106 -4
  229. mlrun/utils/notifications/notification/__init__.py +22 -19
  230. mlrun/utils/notifications/notification/base.py +33 -14
  231. mlrun/utils/notifications/notification/console.py +6 -6
  232. mlrun/utils/notifications/notification/git.py +11 -11
  233. mlrun/utils/notifications/notification/ipython.py +10 -9
  234. mlrun/utils/notifications/notification/mail.py +176 -0
  235. mlrun/utils/notifications/notification/slack.py +6 -6
  236. mlrun/utils/notifications/notification/webhook.py +6 -6
  237. mlrun/utils/notifications/notification_pusher.py +86 -44
  238. mlrun/utils/regex.py +3 -1
  239. mlrun/utils/version/version.json +2 -2
  240. {mlrun-1.7.1rc4.dist-info → mlrun-1.8.0rc8.dist-info}/METADATA +191 -186
  241. mlrun-1.8.0rc8.dist-info/RECORD +347 -0
  242. {mlrun-1.7.1rc4.dist-info → mlrun-1.8.0rc8.dist-info}/WHEEL +1 -1
  243. mlrun/model_monitoring/db/stores/__init__.py +0 -136
  244. mlrun/model_monitoring/db/stores/base/store.py +0 -213
  245. mlrun/model_monitoring/db/stores/sqldb/__init__.py +0 -13
  246. mlrun/model_monitoring/db/stores/sqldb/models/__init__.py +0 -71
  247. mlrun/model_monitoring/db/stores/sqldb/models/base.py +0 -190
  248. mlrun/model_monitoring/db/stores/sqldb/models/mysql.py +0 -103
  249. mlrun/model_monitoring/db/stores/sqldb/models/sqlite.py +0 -40
  250. mlrun/model_monitoring/db/stores/sqldb/sql_store.py +0 -659
  251. mlrun/model_monitoring/db/stores/v3io_kv/__init__.py +0 -13
  252. mlrun/model_monitoring/db/stores/v3io_kv/kv_store.py +0 -726
  253. mlrun/model_monitoring/model_endpoint.py +0 -118
  254. mlrun-1.7.1rc4.dist-info/RECORD +0 -351
  255. {mlrun-1.7.1rc4.dist-info → mlrun-1.8.0rc8.dist-info}/LICENSE +0 -0
  256. {mlrun-1.7.1rc4.dist-info → mlrun-1.8.0rc8.dist-info}/entry_points.txt +0 -0
  257. {mlrun-1.7.1rc4.dist-info → mlrun-1.8.0rc8.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
@@ -41,6 +39,7 @@ from .execution import MLClientCtx
41
39
  from .model import RunObject, RunTemplate, new_task
42
40
  from .package import ArtifactType, DefaultPackager, Packager, handler
43
41
  from .projects import (
42
+ MlrunProject,
44
43
  ProjectMetadata,
45
44
  build_function,
46
45
  deploy_function,
@@ -61,18 +60,19 @@ from .run import (
61
60
  get_pipeline,
62
61
  import_function,
63
62
  new_function,
63
+ retry_pipeline,
64
64
  wait_for_pipeline_completion,
65
65
  )
66
- from .runtimes import new_model_server
66
+ from .runtimes import mounts, new_model_server
67
67
  from .secrets import get_secret_or_env
68
68
  from .utils.version import Version
69
69
 
70
70
  __version__ = Version().get()["version"]
71
71
 
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
72
+ VolumeMount = mounts.VolumeMount
73
+ mount_v3io = mounts.mount_v3io
74
+ v3io_cred = mounts.v3io_cred
75
+ auto_mount = mounts.auto_mount
76
76
 
77
77
 
78
78
  def get_version():
@@ -88,12 +88,12 @@ if "IGZ_NAMESPACE_DOMAIN" in environ:
88
88
 
89
89
 
90
90
  def set_environment(
91
- api_path: str = None,
91
+ api_path: Optional[str] = None,
92
92
  artifact_path: str = "",
93
- access_key: str = None,
94
- username: str = None,
95
- env_file: str = None,
96
- mock_functions: str = None,
93
+ access_key: Optional[str] = None,
94
+ username: Optional[str] = None,
95
+ env_file: Optional[str] = None,
96
+ mock_functions: Optional[str] = None,
97
97
  ):
98
98
  """set and test default config for: api path, artifact_path and project
99
99
 
@@ -136,15 +136,16 @@ def set_environment(
136
136
  if not mlconf.dbpath:
137
137
  raise ValueError("DB/API path was not detected, please specify its address")
138
138
 
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
139
  # check connectivity and load remote defaults
145
140
  get_run_db()
146
141
  if api_path:
147
142
  environ["MLRUN_DBPATH"] = mlconf.dbpath
143
+ mlconf.reload()
144
+
145
+ if mock_functions is not None:
146
+ mock_functions = "1" if mock_functions is True else mock_functions
147
+ mlconf.force_run_local = mock_functions
148
+ mlconf.mock_nuclio_deployment = mock_functions
148
149
 
149
150
  if not mlconf.artifact_path and not artifact_path:
150
151
  raise ValueError(
@@ -159,13 +160,14 @@ def set_environment(
159
160
  "artifact_path must refer to an absolute path" " or a valid url"
160
161
  )
161
162
  mlconf.artifact_path = artifact_path
163
+
162
164
  return mlconf.default_project, mlconf.artifact_path
163
165
 
164
166
 
165
- def get_current_project(silent=False):
167
+ def get_current_project(silent: bool = False) -> Optional[MlrunProject]:
166
168
  if not pipeline_context.project and not silent:
167
169
  raise MLRunInvalidArgumentError(
168
- "current project is not initialized, use new, get or load project methods first"
170
+ "No current project is initialized. Use new, get or load project functions first."
169
171
  )
170
172
  return pipeline_context.project
171
173
 
@@ -182,7 +184,7 @@ def get_sample_path(subpath=""):
182
184
  return samples_path
183
185
 
184
186
 
185
- def set_env_from_file(env_file: str, return_dict: bool = False):
187
+ def set_env_from_file(env_file: str, return_dict: bool = False) -> Optional[dict]:
186
188
  """Read and set and/or return environment variables from a file
187
189
  the env file should have lines in the form KEY=VALUE, comment line start with "#"
188
190
 
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
@@ -11,8 +11,8 @@
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 Union
14
+ from datetime import datetime
15
+ from typing import Optional, Union
16
16
 
17
17
  import mlrun
18
18
  import mlrun.common.schemas.alert as alert_objects
@@ -30,6 +30,7 @@ class AlertConfig(ModelObj):
30
30
  "state",
31
31
  "count",
32
32
  "created",
33
+ "updated",
33
34
  ]
34
35
  _fields_to_serialize = ModelObj._fields_to_serialize + [
35
36
  "entities",
@@ -40,21 +41,22 @@ class AlertConfig(ModelObj):
40
41
 
41
42
  def __init__(
42
43
  self,
43
- project: str = None,
44
- name: str = None,
44
+ project: Optional[str] = None,
45
+ name: Optional[str] = None,
45
46
  template: Union[alert_objects.AlertTemplate, str] = None,
46
- description: str = None,
47
- summary: str = None,
47
+ description: Optional[str] = None,
48
+ summary: Optional[str] = None,
48
49
  severity: alert_objects.AlertSeverity = None,
49
50
  trigger: alert_objects.AlertTrigger = None,
50
51
  criteria: alert_objects.AlertCriteria = None,
51
52
  reset_policy: alert_objects.ResetPolicy = None,
52
- notifications: list[alert_objects.AlertNotification] = None,
53
+ notifications: Optional[list[alert_objects.AlertNotification]] = None,
53
54
  entities: alert_objects.EventEntities = None,
54
- id: int = None,
55
+ id: Optional[int] = None,
55
56
  state: alert_objects.AlertActiveState = None,
56
- created: str = None,
57
- count: int = None,
57
+ created: Optional[str] = None,
58
+ count: Optional[int] = None,
59
+ updated: Optional[str] = None,
58
60
  ):
59
61
  """Alert config object
60
62
 
@@ -118,6 +120,7 @@ class AlertConfig(ModelObj):
118
120
  :param state: State of the alert, may be active/inactive (user should not supply it)
119
121
  :param created: When the alert is created (user should not supply it)
120
122
  :param count: Internal counter of the alert (user should not supply it)
123
+ :param updated: The last update time of the alert (user should not supply it)
121
124
  """
122
125
  self.project = project
123
126
  self.name = name
@@ -131,18 +134,45 @@ class AlertConfig(ModelObj):
131
134
  self.entities = entities
132
135
  self.id = id
133
136
  self.state = state
134
- self.created = created
137
+ self._created = created
135
138
  self.count = count
139
+ self._updated = updated
136
140
 
137
141
  if template:
138
142
  self._apply_template(template)
139
143
 
144
+ @property
145
+ def created(self) -> datetime:
146
+ """
147
+ Get the `created` field as a datetime object.
148
+ """
149
+ if isinstance(self._created, str):
150
+ return datetime.fromisoformat(self._created)
151
+ return self._created
152
+
153
+ @created.setter
154
+ def created(self, created):
155
+ self._created = created
156
+
157
+ @property
158
+ def updated(self) -> datetime:
159
+ """
160
+ Get the `updated` field as a datetime object.
161
+ """
162
+ if isinstance(self._updated, str):
163
+ return datetime.fromisoformat(self._updated)
164
+ return self._updated
165
+
166
+ @updated.setter
167
+ def updated(self, updated):
168
+ self._updated = updated
169
+
140
170
  def validate_required_fields(self):
141
171
  if not self.name:
142
172
  raise mlrun.errors.MLRunInvalidArgumentError("Alert name must be provided")
143
173
 
144
174
  def _serialize_field(
145
- self, struct: dict, field_name: str = None, strip: bool = False
175
+ self, struct: dict, field_name: Optional[str] = None, strip: bool = False
146
176
  ):
147
177
  if field_name == "entities":
148
178
  if self.entities:
@@ -179,7 +209,12 @@ class AlertConfig(ModelObj):
179
209
  return None
180
210
  return super()._serialize_field(struct, field_name, strip)
181
211
 
182
- def to_dict(self, fields: list = None, exclude: list = None, strip: bool = False):
212
+ def to_dict(
213
+ self,
214
+ fields: Optional[list] = None,
215
+ exclude: Optional[list] = None,
216
+ strip: bool = False,
217
+ ):
183
218
  if self.entities is None:
184
219
  raise mlrun.errors.MLRunBadRequestError("Alert entity field is missing")
185
220
  if not self.notifications:
@@ -189,7 +224,9 @@ class AlertConfig(ModelObj):
189
224
  return super().to_dict(self._dict_fields)
190
225
 
191
226
  @classmethod
192
- def from_dict(cls, struct=None, fields=None, deprecated_fields: dict = None):
227
+ def from_dict(
228
+ cls, struct=None, fields=None, deprecated_fields: Optional[dict] = None
229
+ ):
193
230
  new_obj = super().from_dict(struct, fields=fields)
194
231
 
195
232
  entity_data = struct.get("entities")
@@ -246,3 +283,100 @@ class AlertConfig(ModelObj):
246
283
  self.criteria = self.criteria or template.criteria
247
284
  self.trigger = self.trigger or template.trigger
248
285
  self.reset_policy = self.reset_policy or template.reset_policy
286
+
287
+ def list_activations(
288
+ self,
289
+ since: Optional[datetime] = None,
290
+ until: Optional[datetime] = None,
291
+ from_last_update: bool = False,
292
+ ) -> list[mlrun.common.schemas.alert.AlertActivation]:
293
+ """
294
+ Retrieve a list of all alert activations.
295
+
296
+ :param since: Filters for alert activations occurring after this timestamp.
297
+ :param until: Filters for alert activations occurring before this timestamp.
298
+ :param from_last_update: If set to True, retrieves alert activations since the alert's last update time.
299
+ if both since and from_last_update=True are provided, from_last_update takes precedence
300
+ and the since value will be overridden by the alert's last update timestamp.
301
+
302
+ :returns: A list of alert activations matching the provided filters.
303
+ """
304
+ db = mlrun.get_run_db()
305
+ if from_last_update and self._updated:
306
+ since = self.updated
307
+
308
+ return db.list_alert_activations(
309
+ project=self.project,
310
+ name=self.name,
311
+ since=since,
312
+ until=until,
313
+ )
314
+
315
+ def paginated_list_activations(
316
+ self,
317
+ *args,
318
+ page: Optional[int] = None,
319
+ page_size: Optional[int] = None,
320
+ page_token: Optional[str] = None,
321
+ from_last_update: bool = False,
322
+ **kwargs,
323
+ ) -> tuple[mlrun.common.schemas.alert.AlertActivation, Optional[str]]:
324
+ """
325
+ List alerts activations with support for pagination and various filtering options.
326
+
327
+ This method retrieves a paginated list of alert activations based on the specified filter parameters.
328
+ Pagination is controlled using the `page`, `page_size`, and `page_token` parameters. The method
329
+ will return a list of alert activations that match the filtering criteria provided.
330
+
331
+ For detailed information about the parameters, refer to the list_activations method:
332
+ See :py:func:`~list_activations` for more details.
333
+
334
+ Examples::
335
+
336
+ # Fetch first page of alert activations with page size of 5
337
+ alert_activations, token = alert_config.paginated_list_activations(page_size=5)
338
+ # Fetch next page using the pagination token from the previous response
339
+ alert_activations, token = alert_config.paginated_list_activations(
340
+ page_token=token
341
+ )
342
+ # Fetch alert activations for a specific page (e.g., page 3)
343
+ alert_activations, token = alert_config.paginated_list_activations(
344
+ page=3, page_size=5
345
+ )
346
+
347
+ # Automatically iterate over all pages without explicitly specifying the page number
348
+ alert_activations = []
349
+ token = None
350
+ while True:
351
+ page_alert_activations, token = alert_config.paginated_list_activations(
352
+ page_token=token, page_size=5
353
+ )
354
+ alert_activations.extend(page_alert_activations)
355
+
356
+ # If token is None and page_alert_activations is empty, we've reached the end (no more activations).
357
+ # If token is None and page_alert_activations is not empty, we've fetched the last page of activations.
358
+ if not token:
359
+ break
360
+ print(f"Total alert activations retrieved: {len(alert_activations)}")
361
+
362
+ :param page: The page number to retrieve. If not provided, the next page will be retrieved.
363
+ :param page_size: The number of items per page to retrieve. Up to `page_size` responses are expected.
364
+ :param page_token: A pagination token used to retrieve the next page of results. Should not be provided
365
+ for the first request.
366
+ :param from_last_update: If set to True, retrieves alert activations since the alert's last update time.
367
+
368
+ :returns: A tuple containing the list of alert activations and an optional `page_token` for pagination.
369
+ """
370
+ if from_last_update and self._updated:
371
+ kwargs["since"] = self.updated
372
+
373
+ db = mlrun.get_run_db()
374
+ return db.paginated_list_alert_activations(
375
+ *args,
376
+ project=self.project,
377
+ name=self.name,
378
+ page=page,
379
+ page_size=page_size,
380
+ page_token=page_token,
381
+ **kwargs,
382
+ )
@@ -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
 
@@ -25,6 +23,7 @@ from .base import (
25
23
  get_artifact_meta,
26
24
  )
27
25
  from .dataset import DatasetArtifact, TableArtifact, update_dataset_meta
26
+ from .document import DocumentArtifact, DocumentLoaderSpec, MLRunLoader
28
27
  from .manager import (
29
28
  ArtifactManager,
30
29
  ArtifactProducer,
mlrun/artifacts/base.py CHANGED
@@ -36,7 +36,16 @@ from ..utils import (
36
36
 
37
37
 
38
38
  class ArtifactMetadata(ModelObj):
39
- _dict_fields = ["key", "project", "iter", "tree", "description", "hash", "tag"]
39
+ _dict_fields = [
40
+ "key",
41
+ "project",
42
+ "iter",
43
+ "tree",
44
+ "description",
45
+ "hash",
46
+ "tag",
47
+ "uid",
48
+ ]
40
49
  _extra_fields = ["updated", "labels"]
41
50
 
42
51
  def __init__(
@@ -48,6 +57,7 @@ class ArtifactMetadata(ModelObj):
48
57
  description=None,
49
58
  hash=None,
50
59
  tag=None,
60
+ uid=None,
51
61
  ):
52
62
  self.key = key
53
63
  self.project = project
@@ -58,18 +68,26 @@ class ArtifactMetadata(ModelObj):
58
68
  self.labels = {}
59
69
  self.updated = None
60
70
  self.tag = tag # temp store of the tag
71
+ self.uid = uid
61
72
 
62
73
  def base_dict(self):
63
74
  return super().to_dict()
64
75
 
65
- def to_dict(self, fields: list = None, exclude: list = None, strip: bool = False):
76
+ def to_dict(
77
+ self,
78
+ fields: typing.Optional[list] = None,
79
+ exclude: typing.Optional[list] = None,
80
+ strip: bool = False,
81
+ ):
66
82
  """return long dict form of the artifact"""
67
83
  return super().to_dict(
68
84
  self._dict_fields + self._extra_fields, exclude=exclude, strip=strip
69
85
  )
70
86
 
71
87
  @classmethod
72
- def from_dict(cls, struct=None, fields=None, deprecated_fields: dict = None):
88
+ def from_dict(
89
+ cls, struct=None, fields=None, deprecated_fields: typing.Optional[dict] = None
90
+ ):
73
91
  fields = fields or cls._dict_fields + cls._extra_fields
74
92
  return super().from_dict(
75
93
  struct, fields=fields, deprecated_fields=deprecated_fields
@@ -109,7 +127,7 @@ class ArtifactSpec(ModelObj):
109
127
  db_key=None,
110
128
  extra_data=None,
111
129
  body=None,
112
- unpackaging_instructions: dict = None,
130
+ unpackaging_instructions: typing.Optional[dict] = None,
113
131
  ):
114
132
  self.src_path = src_path
115
133
  self.target_path = target_path
@@ -131,14 +149,21 @@ class ArtifactSpec(ModelObj):
131
149
  def base_dict(self):
132
150
  return super().to_dict()
133
151
 
134
- def to_dict(self, fields: list = None, exclude: list = None, strip: bool = False):
152
+ def to_dict(
153
+ self,
154
+ fields: typing.Optional[list] = None,
155
+ exclude: typing.Optional[list] = None,
156
+ strip: bool = False,
157
+ ):
135
158
  """return long dict form of the artifact"""
136
159
  return super().to_dict(
137
160
  self._dict_fields + self._extra_fields, exclude=exclude, strip=strip
138
161
  )
139
162
 
140
163
  @classmethod
141
- def from_dict(cls, struct=None, fields=None, deprecated_fields: dict = None):
164
+ def from_dict(
165
+ cls, struct=None, fields=None, deprecated_fields: typing.Optional[dict] = None
166
+ ):
142
167
  fields = fields or cls._dict_fields + cls._extra_fields
143
168
  return super().from_dict(
144
169
  struct, fields=fields, deprecated_fields=deprecated_fields
@@ -192,7 +217,7 @@ class Artifact(ModelObj):
192
217
  size=None,
193
218
  target_path=None,
194
219
  project=None,
195
- src_path: str = None,
220
+ src_path: typing.Optional[str] = None,
196
221
  # All params up until here are legacy params for compatibility with legacy artifacts.
197
222
  # TODO: remove them in 1.9.0.
198
223
  metadata: ArtifactMetadata = None,
@@ -366,7 +391,7 @@ class Artifact(ModelObj):
366
391
  struct[field] = val.base_dict()
367
392
  return struct
368
393
 
369
- def upload(self, artifact_path: str = None):
394
+ def upload(self, artifact_path: typing.Optional[str] = None):
370
395
  """
371
396
  internal, upload to target store
372
397
  :param artifact_path: required only for when generating target_path from artifact hash
@@ -379,7 +404,9 @@ class Artifact(ModelObj):
379
404
  if src_path and os.path.isfile(src_path):
380
405
  self._upload_file(source_path=src_path, artifact_path=artifact_path)
381
406
 
382
- def _upload_body(self, body, target=None, artifact_path: str = None):
407
+ def _upload_body(
408
+ self, body, target=None, artifact_path: typing.Optional[str] = None
409
+ ):
383
410
  body_hash = None
384
411
  if not target and not self.spec.target_path:
385
412
  if not mlrun.mlconf.artifacts.generate_target_path_from_artifact_hash:
@@ -400,7 +427,10 @@ class Artifact(ModelObj):
400
427
  )
401
428
 
402
429
  def _upload_file(
403
- self, source_path: str, target_path: str = None, artifact_path: str = None
430
+ self,
431
+ source_path: str,
432
+ target_path: typing.Optional[str] = None,
433
+ artifact_path: typing.Optional[str] = None,
404
434
  ):
405
435
  file_hash = None
406
436
  if not target_path and not self.spec.target_path:
@@ -651,7 +681,7 @@ class DirArtifact(Artifact):
651
681
  def is_dir(self):
652
682
  return True
653
683
 
654
- def upload(self, artifact_path: str = None):
684
+ def upload(self, artifact_path: typing.Optional[str] = None):
655
685
  """
656
686
  internal, upload to target store
657
687
  :param artifact_path: required only for when generating target_path from artifact hash
@@ -758,13 +788,17 @@ def upload_extra_data(
758
788
  extra_data: dict,
759
789
  prefix="",
760
790
  update_spec=False,
761
- artifact_path: str = None,
791
+ artifact_path: typing.Optional[str] = None,
762
792
  ):
763
793
  """upload extra data to the artifact store"""
764
794
  if not extra_data:
765
795
  return
766
796
  target_path = artifact.target_path
767
797
  for key, item in extra_data.items():
798
+ if item is ...:
799
+ # Skip future links (packagers feature for linking artifacts before they are logged)
800
+ continue
801
+
768
802
  if isinstance(item, bytes):
769
803
  if target_path:
770
804
  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")