mlrun 1.7.0rc14__py3-none-any.whl → 1.7.0rc22__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 (160) hide show
  1. mlrun/__init__.py +10 -1
  2. mlrun/__main__.py +23 -111
  3. mlrun/alerts/__init__.py +15 -0
  4. mlrun/alerts/alert.py +169 -0
  5. mlrun/api/schemas/__init__.py +4 -3
  6. mlrun/artifacts/__init__.py +8 -3
  7. mlrun/artifacts/base.py +36 -253
  8. mlrun/artifacts/dataset.py +9 -190
  9. mlrun/artifacts/manager.py +46 -42
  10. mlrun/artifacts/model.py +9 -141
  11. mlrun/artifacts/plots.py +14 -375
  12. mlrun/common/constants.py +65 -3
  13. mlrun/common/formatters/__init__.py +19 -0
  14. mlrun/{runtimes/mpijob/v1alpha1.py → common/formatters/artifact.py} +6 -14
  15. mlrun/common/formatters/base.py +113 -0
  16. mlrun/common/formatters/function.py +46 -0
  17. mlrun/common/formatters/pipeline.py +53 -0
  18. mlrun/common/formatters/project.py +51 -0
  19. mlrun/{runtimes → common/runtimes}/constants.py +32 -4
  20. mlrun/common/schemas/__init__.py +10 -5
  21. mlrun/common/schemas/alert.py +92 -11
  22. mlrun/common/schemas/api_gateway.py +56 -0
  23. mlrun/common/schemas/artifact.py +15 -5
  24. mlrun/common/schemas/auth.py +2 -0
  25. mlrun/common/schemas/client_spec.py +1 -0
  26. mlrun/common/schemas/frontend_spec.py +1 -0
  27. mlrun/common/schemas/function.py +4 -0
  28. mlrun/common/schemas/model_monitoring/__init__.py +15 -3
  29. mlrun/common/schemas/model_monitoring/constants.py +58 -7
  30. mlrun/common/schemas/model_monitoring/grafana.py +9 -5
  31. mlrun/common/schemas/model_monitoring/model_endpoints.py +86 -2
  32. mlrun/common/schemas/pipeline.py +0 -9
  33. mlrun/common/schemas/project.py +5 -11
  34. mlrun/common/types.py +1 -0
  35. mlrun/config.py +30 -9
  36. mlrun/data_types/to_pandas.py +9 -9
  37. mlrun/datastore/base.py +41 -9
  38. mlrun/datastore/datastore.py +6 -2
  39. mlrun/datastore/datastore_profile.py +56 -4
  40. mlrun/datastore/inmem.py +2 -2
  41. mlrun/datastore/redis.py +2 -2
  42. mlrun/datastore/s3.py +5 -0
  43. mlrun/datastore/sources.py +147 -7
  44. mlrun/datastore/store_resources.py +7 -7
  45. mlrun/datastore/targets.py +110 -42
  46. mlrun/datastore/utils.py +42 -0
  47. mlrun/db/base.py +54 -10
  48. mlrun/db/httpdb.py +282 -79
  49. mlrun/db/nopdb.py +52 -10
  50. mlrun/errors.py +11 -0
  51. mlrun/execution.py +26 -9
  52. mlrun/feature_store/__init__.py +0 -2
  53. mlrun/feature_store/api.py +12 -47
  54. mlrun/feature_store/feature_set.py +9 -0
  55. mlrun/feature_store/feature_vector.py +8 -0
  56. mlrun/feature_store/ingestion.py +7 -6
  57. mlrun/feature_store/retrieval/base.py +9 -4
  58. mlrun/feature_store/retrieval/conversion.py +9 -9
  59. mlrun/feature_store/retrieval/dask_merger.py +2 -0
  60. mlrun/feature_store/retrieval/job.py +9 -3
  61. mlrun/feature_store/retrieval/local_merger.py +2 -0
  62. mlrun/feature_store/retrieval/spark_merger.py +16 -0
  63. mlrun/frameworks/__init__.py +6 -0
  64. mlrun/frameworks/_dl_common/loggers/tensorboard_logger.py +7 -12
  65. mlrun/frameworks/parallel_coordinates.py +2 -1
  66. mlrun/frameworks/tf_keras/__init__.py +4 -1
  67. mlrun/k8s_utils.py +10 -11
  68. mlrun/launcher/base.py +4 -3
  69. mlrun/launcher/client.py +5 -3
  70. mlrun/launcher/local.py +12 -2
  71. mlrun/launcher/remote.py +9 -2
  72. mlrun/lists.py +6 -2
  73. mlrun/model.py +47 -21
  74. mlrun/model_monitoring/__init__.py +1 -1
  75. mlrun/model_monitoring/api.py +42 -18
  76. mlrun/model_monitoring/application.py +5 -305
  77. mlrun/model_monitoring/applications/__init__.py +11 -0
  78. mlrun/model_monitoring/applications/_application_steps.py +157 -0
  79. mlrun/model_monitoring/applications/base.py +280 -0
  80. mlrun/model_monitoring/applications/context.py +214 -0
  81. mlrun/model_monitoring/applications/evidently_base.py +211 -0
  82. mlrun/model_monitoring/applications/histogram_data_drift.py +132 -91
  83. mlrun/model_monitoring/applications/results.py +99 -0
  84. mlrun/model_monitoring/controller.py +3 -1
  85. mlrun/model_monitoring/db/__init__.py +2 -0
  86. mlrun/model_monitoring/db/stores/__init__.py +0 -2
  87. mlrun/model_monitoring/db/stores/base/store.py +22 -37
  88. mlrun/model_monitoring/db/stores/sqldb/models/__init__.py +43 -21
  89. mlrun/model_monitoring/db/stores/sqldb/models/base.py +39 -8
  90. mlrun/model_monitoring/db/stores/sqldb/models/mysql.py +27 -7
  91. mlrun/model_monitoring/db/stores/sqldb/models/sqlite.py +5 -0
  92. mlrun/model_monitoring/db/stores/sqldb/sql_store.py +246 -224
  93. mlrun/model_monitoring/db/stores/v3io_kv/kv_store.py +232 -216
  94. mlrun/model_monitoring/db/tsdb/__init__.py +100 -0
  95. mlrun/model_monitoring/db/tsdb/base.py +316 -0
  96. mlrun/model_monitoring/db/tsdb/helpers.py +30 -0
  97. mlrun/model_monitoring/db/tsdb/tdengine/__init__.py +15 -0
  98. mlrun/model_monitoring/db/tsdb/tdengine/schemas.py +240 -0
  99. mlrun/model_monitoring/db/tsdb/tdengine/stream_graph_steps.py +45 -0
  100. mlrun/model_monitoring/db/tsdb/tdengine/tdengine_connector.py +401 -0
  101. mlrun/model_monitoring/db/tsdb/v3io/__init__.py +15 -0
  102. mlrun/model_monitoring/db/tsdb/v3io/stream_graph_steps.py +117 -0
  103. mlrun/model_monitoring/db/tsdb/v3io/v3io_connector.py +658 -0
  104. mlrun/model_monitoring/evidently_application.py +6 -118
  105. mlrun/model_monitoring/helpers.py +63 -1
  106. mlrun/model_monitoring/model_endpoint.py +3 -2
  107. mlrun/model_monitoring/stream_processing.py +57 -216
  108. mlrun/model_monitoring/writer.py +134 -124
  109. mlrun/package/__init__.py +13 -1
  110. mlrun/package/packagers/__init__.py +6 -1
  111. mlrun/package/utils/_formatter.py +2 -2
  112. mlrun/platforms/__init__.py +10 -9
  113. mlrun/platforms/iguazio.py +21 -202
  114. mlrun/projects/operations.py +24 -12
  115. mlrun/projects/pipelines.py +79 -102
  116. mlrun/projects/project.py +271 -103
  117. mlrun/render.py +15 -14
  118. mlrun/run.py +16 -46
  119. mlrun/runtimes/__init__.py +6 -3
  120. mlrun/runtimes/base.py +14 -7
  121. mlrun/runtimes/daskjob.py +1 -0
  122. mlrun/runtimes/databricks_job/databricks_runtime.py +1 -0
  123. mlrun/runtimes/databricks_job/databricks_wrapper.py +1 -1
  124. mlrun/runtimes/funcdoc.py +0 -28
  125. mlrun/runtimes/kubejob.py +2 -1
  126. mlrun/runtimes/local.py +12 -3
  127. mlrun/runtimes/mpijob/__init__.py +0 -20
  128. mlrun/runtimes/mpijob/v1.py +1 -1
  129. mlrun/runtimes/nuclio/api_gateway.py +194 -84
  130. mlrun/runtimes/nuclio/application/application.py +170 -8
  131. mlrun/runtimes/nuclio/function.py +39 -49
  132. mlrun/runtimes/pod.py +16 -36
  133. mlrun/runtimes/remotesparkjob.py +9 -3
  134. mlrun/runtimes/sparkjob/spark3job.py +1 -1
  135. mlrun/runtimes/utils.py +6 -45
  136. mlrun/serving/__init__.py +8 -1
  137. mlrun/serving/server.py +2 -1
  138. mlrun/serving/states.py +51 -8
  139. mlrun/serving/utils.py +19 -11
  140. mlrun/serving/v2_serving.py +5 -1
  141. mlrun/track/tracker.py +2 -1
  142. mlrun/utils/async_http.py +25 -5
  143. mlrun/utils/helpers.py +157 -83
  144. mlrun/utils/logger.py +39 -7
  145. mlrun/utils/notifications/notification/__init__.py +14 -9
  146. mlrun/utils/notifications/notification/base.py +1 -1
  147. mlrun/utils/notifications/notification/slack.py +34 -7
  148. mlrun/utils/notifications/notification/webhook.py +1 -1
  149. mlrun/utils/notifications/notification_pusher.py +147 -16
  150. mlrun/utils/regex.py +9 -0
  151. mlrun/utils/v3io_clients.py +0 -1
  152. mlrun/utils/version/version.json +2 -2
  153. {mlrun-1.7.0rc14.dist-info → mlrun-1.7.0rc22.dist-info}/METADATA +14 -6
  154. {mlrun-1.7.0rc14.dist-info → mlrun-1.7.0rc22.dist-info}/RECORD +158 -138
  155. mlrun/kfpops.py +0 -865
  156. mlrun/platforms/other.py +0 -305
  157. {mlrun-1.7.0rc14.dist-info → mlrun-1.7.0rc22.dist-info}/LICENSE +0 -0
  158. {mlrun-1.7.0rc14.dist-info → mlrun-1.7.0rc22.dist-info}/WHEEL +0 -0
  159. {mlrun-1.7.0rc14.dist-info → mlrun-1.7.0rc22.dist-info}/entry_points.txt +0 -0
  160. {mlrun-1.7.0rc14.dist-info → mlrun-1.7.0rc22.dist-info}/top_level.txt +0 -0
mlrun/artifacts/plots.py CHANGED
@@ -13,14 +13,12 @@
13
13
  # limitations under the License.
14
14
  import base64
15
15
  import typing
16
+ import warnings
16
17
  from io import BytesIO
17
18
 
18
- from deprecated import deprecated
19
-
20
19
  import mlrun
21
20
 
22
- from ..utils import dict_to_json
23
- from .base import Artifact, LegacyArtifact
21
+ from .base import Artifact
24
22
 
25
23
  if typing.TYPE_CHECKING:
26
24
  from plotly.graph_objs import Figure
@@ -37,6 +35,12 @@ class PlotArtifact(Artifact):
37
35
  def __init__(
38
36
  self, key=None, body=None, is_inline=False, target_path=None, title=None
39
37
  ):
38
+ if key or body or is_inline or target_path:
39
+ warnings.warn(
40
+ "Artifact constructor parameters are deprecated and will be removed in 1.9.0. "
41
+ "Use the metadata and spec parameters instead.",
42
+ DeprecationWarning,
43
+ )
40
44
  super().__init__(key, body, format="html", target_path=target_path)
41
45
  self.metadata.description = title
42
46
 
@@ -70,138 +74,6 @@ class PlotArtifact(Artifact):
70
74
  )
71
75
 
72
76
 
73
- # TODO: remove in 1.7.0
74
- @deprecated(
75
- version="1.5.0",
76
- reason="'ChartArtifact' will be removed in 1.7.0, use 'Artifact' instead",
77
- category=FutureWarning,
78
- )
79
- class ChartArtifact(Artifact):
80
- kind = "chart"
81
-
82
- _TEMPLATE = """
83
- <html>
84
- <head>
85
- <script
86
- type="text/javascript"
87
- src="https://www.gstatic.com/charts/loader.js"></script>
88
- <script type="text/javascript">
89
- google.charts.load('current', {'packages':['corechart']});
90
- google.charts.setOnLoadCallback(drawChart);
91
- function drawChart() {
92
- var data = google.visualization.arrayToDataTable($data$);
93
- var options = $opts$;
94
- var chart = new google.visualization.$chart$(
95
- document.getElementById('chart_div'));
96
- chart.draw(data, options);
97
- }
98
- </script>
99
- </head>
100
- <body>
101
- <div id="chart_div" style="width: 100%; height: 500px;"></div>
102
- </body>
103
- </html>
104
- """
105
-
106
- def __init__(
107
- self,
108
- key=None,
109
- data=None,
110
- header=None,
111
- options=None,
112
- title=None,
113
- chart=None,
114
- target_path=None,
115
- ):
116
- data = [] if data is None else data
117
- options = {} if options is None else options
118
- super().__init__(key, target_path=target_path)
119
- self.viewer = "chart"
120
- self.header = header or []
121
- self.title = title
122
- self.rows = []
123
- if data:
124
- if header:
125
- self.rows = data
126
- else:
127
- self.header = data[0]
128
- self.rows = data[1:]
129
- self.options = options
130
- self.chart = chart or "LineChart"
131
- self.format = "html"
132
-
133
- def add_row(self, row):
134
- self.rows += [row]
135
-
136
- def get_body(self):
137
- if not self.options.get("title"):
138
- self.options["title"] = self.title or self.key
139
- data = [self.header] + self.rows
140
- return (
141
- self._TEMPLATE.replace("$data$", dict_to_json(data))
142
- .replace("$opts$", dict_to_json(self.options))
143
- .replace("$chart$", self.chart)
144
- )
145
-
146
-
147
- # TODO: remove in 1.7.0
148
- @deprecated(
149
- version="1.5.0",
150
- reason="'BokehArtifact' will be removed in 1.7.0, use 'Artifact' instead",
151
- category=FutureWarning,
152
- )
153
- class BokehArtifact(Artifact):
154
- """
155
- Bokeh artifact is an artifact for saving Bokeh generated figures. They will be stored in a html format.
156
- """
157
-
158
- kind = "bokeh"
159
-
160
- def __init__(
161
- self,
162
- figure=None,
163
- key: str = None,
164
- target_path: str = None,
165
- ):
166
- """
167
- Initialize a Bokeh artifact with the given figure.
168
-
169
- :param figure: Bokeh figure ('bokeh.plotting.Figure' object) to save as an artifact.
170
- :param key: Key for the artifact to be stored in the database.
171
- :param target_path: Path to save the artifact.
172
- """
173
- # Validate input:
174
- try:
175
- from bokeh.plotting import Figure
176
- except (ModuleNotFoundError, ImportError) as Error:
177
- raise Error(
178
- "Using 'BokehArtifact' requires bokeh package. Use pip install mlrun[bokeh] to install it."
179
- )
180
- if figure is not None and not isinstance(figure, Figure):
181
- raise ValueError(
182
- "BokehArtifact requires the figure parameter to be a "
183
- f"'bokeh.plotting.Figure' but received '{type(figure)}'"
184
- )
185
-
186
- # Call the artifact initializer:
187
- super().__init__(key=key, target_path=target_path, viewer="bokeh")
188
-
189
- # Continue initializing the bokeh artifact:
190
- self._figure = figure
191
- self.spec.format = "html"
192
-
193
- def get_body(self):
194
- """
195
- Get the artifact's body - the bokeh figure's html code.
196
-
197
- :return: The figure's html code.
198
- """
199
- from bokeh.embed import file_html
200
- from bokeh.resources import CDN
201
-
202
- return file_html(self._figure, CDN, self.metadata.key)
203
-
204
-
205
77
  class PlotlyArtifact(Artifact):
206
78
  """
207
79
  Plotly artifact is an artifact for saving Plotly generated figures. They will be stored in a html format.
@@ -222,6 +94,12 @@ class PlotlyArtifact(Artifact):
222
94
  :param key: Key for the artifact to be stored in the database.
223
95
  :param target_path: Path to save the artifact.
224
96
  """
97
+ if key or target_path:
98
+ warnings.warn(
99
+ "Artifact constructor parameters are deprecated and will be removed in 1.9.0. "
100
+ "Use the metadata and spec parameters instead.",
101
+ DeprecationWarning,
102
+ )
225
103
  # Validate the plotly package:
226
104
  try:
227
105
  from plotly.graph_objs import Figure
@@ -258,242 +136,3 @@ class PlotlyArtifact(Artifact):
258
136
  :return: The figure's html code.
259
137
  """
260
138
  return self._figure.to_html()
261
-
262
-
263
- # TODO: remove in 1.7.0
264
- @deprecated(
265
- version="1.3.0",
266
- reason="'LegacyPlotArtifact' will be removed in 1.7.0, use 'PlotArtifact' instead",
267
- category=FutureWarning,
268
- )
269
- class LegacyPlotArtifact(LegacyArtifact):
270
- _TEMPLATE = """
271
- <h3 style="text-align:center">{}</h3>
272
- <img title="{}" src="data:image/png;base64,{}">
273
- """
274
- kind = "plot"
275
-
276
- def __init__(
277
- self, key=None, body=None, is_inline=False, target_path=None, title=None
278
- ):
279
- super().__init__(key, body, format="html", target_path=target_path)
280
- self.description = title
281
-
282
- def before_log(self):
283
- self.viewer = "chart"
284
- import matplotlib
285
-
286
- if not self._body or not isinstance(
287
- self._body, (bytes, matplotlib.figure.Figure)
288
- ):
289
- raise ValueError(
290
- "matplotlib fig or png bytes must be provided as artifact body"
291
- )
292
-
293
- def get_body(self):
294
- """Convert Matplotlib figure 'fig' into a <img> tag for HTML use
295
- using base64 encoding."""
296
- if isinstance(self._body, bytes):
297
- data = self._body
298
- else:
299
- from matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvas
300
-
301
- canvas = FigureCanvas(self._body)
302
- png_output = BytesIO()
303
- canvas.print_png(png_output)
304
- data = png_output.getvalue()
305
-
306
- data_uri = base64.b64encode(data).decode("utf-8")
307
- return self._TEMPLATE.format(self.description or self.key, self.key, data_uri)
308
-
309
-
310
- # TODO: remove in 1.7.0
311
- @deprecated(
312
- version="1.3.0",
313
- reason="'LegacyChartArtifact' will be removed in 1.7.0, use 'ChartArtifact' instead",
314
- category=FutureWarning,
315
- )
316
- class LegacyChartArtifact(LegacyArtifact):
317
- _TEMPLATE = """
318
- <html>
319
- <head>
320
- <script
321
- type="text/javascript"
322
- src="https://www.gstatic.com/charts/loader.js"></script>
323
- <script type="text/javascript">
324
- google.charts.load('current', {'packages':['corechart']});
325
- google.charts.setOnLoadCallback(drawChart);
326
- function drawChart() {
327
- var data = google.visualization.arrayToDataTable($data$);
328
- var options = $opts$;
329
- var chart = new google.visualization.$chart$(
330
- document.getElementById('chart_div'));
331
- chart.draw(data, options);
332
- }
333
- </script>
334
- </head>
335
- <body>
336
- <div id="chart_div" style="width: 100%; height: 500px;"></div>
337
- </body>
338
- </html>
339
- """
340
-
341
- kind = "chart"
342
-
343
- def __init__(
344
- self,
345
- key=None,
346
- data=None,
347
- header=None,
348
- options=None,
349
- title=None,
350
- chart=None,
351
- target_path=None,
352
- ):
353
- data = [] if data is None else data
354
- options = {} if options is None else options
355
- super().__init__(key, target_path=target_path)
356
- self.viewer = "chart"
357
- self.header = header or []
358
- self.title = title
359
- self.rows = []
360
- if data:
361
- if header:
362
- self.rows = data
363
- else:
364
- self.header = data[0]
365
- self.rows = data[1:]
366
- self.options = options
367
- self.chart = chart or "LineChart"
368
- self.format = "html"
369
-
370
- def add_row(self, row):
371
- self.rows += [row]
372
-
373
- def get_body(self):
374
- if not self.options.get("title"):
375
- self.options["title"] = self.title or self.key
376
- data = [self.header] + self.rows
377
- return (
378
- self._TEMPLATE.replace("$data$", dict_to_json(data))
379
- .replace("$opts$", dict_to_json(self.options))
380
- .replace("$chart$", self.chart)
381
- )
382
-
383
-
384
- # TODO: remove in 1.7.0
385
- @deprecated(
386
- version="1.3.0",
387
- reason="'LegacyBokehArtifact' will be removed in 1.7.0, use 'BokehArtifact' instead",
388
- category=FutureWarning,
389
- )
390
- class LegacyBokehArtifact(LegacyArtifact):
391
- """
392
- Bokeh artifact is an artifact for saving Bokeh generated figures. They will be stored in a html format.
393
- """
394
-
395
- kind = "bokeh"
396
-
397
- def __init__(
398
- self,
399
- figure=None,
400
- key: str = None,
401
- target_path: str = None,
402
- ):
403
- """
404
- Initialize a Bokeh artifact with the given figure.
405
- :param figure: Bokeh figure ('bokeh.plotting.Figure' object) to save as an artifact.
406
- :param key: Key for the artifact to be stored in the database.
407
- :param target_path: Path to save the artifact.
408
- """
409
- # Validate input:
410
- try:
411
- from bokeh.plotting import Figure
412
- except (ModuleNotFoundError, ImportError) as Error:
413
- raise Error(
414
- "Using 'BokehArtifact' requires bokeh package. Use pip install mlrun[bokeh] to install it."
415
- )
416
- if figure is not None and not isinstance(figure, Figure):
417
- raise ValueError(
418
- "BokehArtifact requires the figure parameter to be a "
419
- f"'bokeh.plotting.Figure' but received '{type(figure)}'"
420
- )
421
-
422
- # Call the artifact initializer:
423
- super().__init__(key=key, target_path=target_path, viewer="bokeh")
424
-
425
- # Continue initializing the bokeh artifact:
426
- self._figure = figure
427
- self.format = "html"
428
-
429
- def get_body(self):
430
- """
431
- Get the artifact's body - the bokeh figure's html code.
432
- :return: The figure's html code.
433
- """
434
- from bokeh.embed import file_html
435
- from bokeh.resources import CDN
436
-
437
- return file_html(self._figure, CDN, self.key)
438
-
439
-
440
- # TODO: remove in 1.7.0
441
- @deprecated(
442
- version="1.3.0",
443
- reason="'LegacyPlotlyArtifact' will be removed in 1.7.0, use 'PlotlyArtifact' instead",
444
- category=FutureWarning,
445
- )
446
- class LegacyPlotlyArtifact(LegacyArtifact):
447
- """
448
- Plotly artifact is an artifact for saving Plotly generated figures. They will be stored in a html format.
449
- """
450
-
451
- kind = "plotly"
452
-
453
- def __init__(
454
- self,
455
- figure=None,
456
- key: str = None,
457
- target_path: str = None,
458
- ):
459
- """
460
- Initialize a Plotly artifact with the given figure.
461
- :param figure: Plotly figure ('plotly.graph_objs.Figure' object) to save as an artifact.
462
- :param key: Key for the artifact to be stored in the database.
463
- :param target_path: Path to save the artifact.
464
- """
465
- # Validate the plotly package:
466
- try:
467
- from plotly.graph_objs import Figure
468
- except ModuleNotFoundError:
469
- raise mlrun.errors.MLRunMissingDependencyError(
470
- "Using `PlotlyArtifact` requires plotly package. Use `pip install mlrun[plotly]` to install it."
471
- )
472
- except ImportError:
473
- import plotly
474
-
475
- raise mlrun.errors.MLRunMissingDependencyError(
476
- f"Using `PlotlyArtifact` requires plotly version >= 5.4.0 but found version {plotly.__version__}. "
477
- f"Use `pip install -U mlrun[plotly]` to install it."
478
- )
479
-
480
- # Call the artifact initializer:
481
- super().__init__(key=key, target_path=target_path, viewer="plotly")
482
-
483
- # Validate input:
484
- if figure is not None and not isinstance(figure, Figure):
485
- raise mlrun.errors.MLRunInvalidArgumentError(
486
- f"PlotlyArtifact requires the figure parameter to be a "
487
- f"`plotly.graph_objs.Figure` but received '{type(figure)}'"
488
- )
489
-
490
- # Continue initializing the plotly artifact:
491
- self._figure = figure
492
- self.format = "html"
493
-
494
- def get_body(self):
495
- """
496
- Get the artifact's body - the Plotly figure's html code.
497
- :return: The figure's html code.
498
- """
499
- return self._figure.to_html()
mlrun/common/constants.py CHANGED
@@ -12,12 +12,74 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
  #
15
+
15
16
  IMAGE_NAME_ENRICH_REGISTRY_PREFIX = "." # prefix for image name to enrich with registry
16
- MLRUN_CREATED_LABEL = "mlrun-created"
17
- MLRUN_MODEL_CONF = "model-conf"
18
- MLRUN_SERVING_SPEC_MOUNT_PATH = f"/tmp/mlrun/{MLRUN_MODEL_CONF}"
17
+ MLRUN_SERVING_CONF = "serving-conf"
18
+ MLRUN_SERVING_SPEC_MOUNT_PATH = f"/tmp/mlrun/{MLRUN_SERVING_CONF}"
19
19
  MLRUN_SERVING_SPEC_FILENAME = "serving_spec.json"
20
20
  MLRUN_SERVING_SPEC_PATH = (
21
21
  f"{MLRUN_SERVING_SPEC_MOUNT_PATH}/{MLRUN_SERVING_SPEC_FILENAME}"
22
22
  )
23
+ MLRUN_FUNCTIONS_ANNOTATION = "mlrun/mlrun-functions"
23
24
  MYSQL_MEDIUMBLOB_SIZE_BYTES = 16 * 1024 * 1024
25
+ MLRUN_LABEL_PREFIX = "mlrun/"
26
+ DASK_LABEL_PREFIX = "dask.org/"
27
+ NUCLIO_LABEL_PREFIX = "nuclio.io/"
28
+
29
+
30
+ class MLRunInternalLabels:
31
+ ### dask
32
+ dask_cluster_name = f"{DASK_LABEL_PREFIX}cluster-name"
33
+ dask_component = f"{DASK_LABEL_PREFIX}component"
34
+
35
+ ### spark
36
+ spark_role = "spark-role"
37
+
38
+ ### mpi
39
+ mpi_job_name = "mpi-job-name"
40
+ mpi_job_role = "mpi-job-role"
41
+ mpi_role_type = "mpi_role_type"
42
+
43
+ ### nuclio
44
+ nuclio_project_name = f"{NUCLIO_LABEL_PREFIX}project-name"
45
+ nuclio_function_name = f"{NUCLIO_LABEL_PREFIX}function-name"
46
+ nuclio_class = f"{NUCLIO_LABEL_PREFIX}class"
47
+
48
+ ### mlrun
49
+ mlrun_auth_key = "mlrun-auth-key"
50
+ mlrun_class = f"{MLRUN_LABEL_PREFIX}class"
51
+ client_python_version = f"{MLRUN_LABEL_PREFIX}client_python_version"
52
+ client_version = f"{MLRUN_LABEL_PREFIX}client_version"
53
+ function = f"{MLRUN_LABEL_PREFIX}function"
54
+ job = f"{MLRUN_LABEL_PREFIX}job"
55
+ name = f"{MLRUN_LABEL_PREFIX}name"
56
+ mlrun_owner = f"{MLRUN_LABEL_PREFIX}owner"
57
+ owner_domain = f"{MLRUN_LABEL_PREFIX}owner_domain"
58
+ project = f"{MLRUN_LABEL_PREFIX}project"
59
+ runner_pod = f"{MLRUN_LABEL_PREFIX}runner-pod"
60
+ schedule_name = f"{MLRUN_LABEL_PREFIX}schedule-name"
61
+ scrape_metrics = f"{MLRUN_LABEL_PREFIX}scrape-metrics"
62
+ tag = f"{MLRUN_LABEL_PREFIX}tag"
63
+ uid = f"{MLRUN_LABEL_PREFIX}uid"
64
+ username = f"{MLRUN_LABEL_PREFIX}username"
65
+ username_domain = f"{MLRUN_LABEL_PREFIX}username_domain"
66
+ task_name = f"{MLRUN_LABEL_PREFIX}task-name"
67
+ host = "host"
68
+ job_type = "job-type"
69
+ kind = "kind"
70
+ component = "component"
71
+ resource_name = "resource_name"
72
+ created = "mlrun-created"
73
+
74
+ owner = "owner"
75
+ v3io_user = "v3io_user"
76
+ workflow = "workflow"
77
+ feature_vector = "feature-vector"
78
+
79
+ @classmethod
80
+ def all(cls):
81
+ return [
82
+ value
83
+ for key, value in cls.__dict__.items()
84
+ if not key.startswith("__") and isinstance(value, str)
85
+ ]
@@ -0,0 +1,19 @@
1
+ # Copyright 2024 Iguazio
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ #
15
+
16
+ from .artifact import ArtifactFormat # noqa
17
+ from .function import FunctionFormat # noqa
18
+ from .pipeline import PipelineFormat # noqa
19
+ from .project import ProjectFormat # noqa
@@ -1,4 +1,4 @@
1
- # Copyright 2023 Iguazio
1
+ # Copyright 2024 Iguazio
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -11,19 +11,11 @@
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
- from deprecated import deprecated
14
+ #
15
15
 
16
- from mlrun.runtimes.constants import MPIJobCRDVersions
17
- from mlrun.runtimes.mpijob.abstract import AbstractMPIJobRuntime
16
+ import mlrun.common.types
18
17
 
19
18
 
20
- # TODO: Remove in 1.7.0
21
- @deprecated(
22
- version="1.5.0",
23
- reason="v1alpha1 mpi will be removed in 1.7.0, use v1 instead",
24
- category=FutureWarning,
25
- )
26
- class MpiRuntimeV1Alpha1(AbstractMPIJobRuntime):
27
- crd_group = "kubeflow.org"
28
- crd_version = MPIJobCRDVersions.v1alpha1
29
- crd_plural = "mpijobs"
19
+ # TODO: add a format that returns a minimal response with ObjectFormat
20
+ class ArtifactFormat(mlrun.common.types.StrEnum):
21
+ full = "full"
@@ -0,0 +1,113 @@
1
+ # Copyright 2024 Iguazio
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ #
15
+
16
+ import typing
17
+
18
+ import mlrun.errors
19
+
20
+
21
+ class ObjectFormat:
22
+ """
23
+ MLRun object formatter. Any class that inherits from this class should implement the `format_method` method
24
+ to specify the formatting method for each format.
25
+ A `filter_obj_method` utility method is provided to filter the object based on a list of keys.
26
+ """
27
+
28
+ full = "full"
29
+
30
+ @staticmethod
31
+ def format_method(_format: str) -> typing.Optional[typing.Callable]:
32
+ """
33
+ Get the formatting method for the provided format.
34
+ A `None` value signifies a pass-through formatting method (no formatting).
35
+ :param _format: The format as a string representation.
36
+ :return: The formatting method.
37
+ """
38
+ return {
39
+ ObjectFormat.full: None,
40
+ }[_format]
41
+
42
+ @classmethod
43
+ def format_obj(
44
+ cls,
45
+ obj: typing.Any,
46
+ _format: str,
47
+ exclude_formats: typing.Optional[list[str]] = None,
48
+ ) -> typing.Any:
49
+ """
50
+ Format the provided object based on the provided format.
51
+ :param obj: The object to format.
52
+ :param _format: The format as a string representation.
53
+ :param exclude_formats: A list of formats to exclude from the formatting process. If the provided format is in
54
+ this list, an invalid format exception will be raised.
55
+ """
56
+ exclude_formats = exclude_formats or []
57
+ _format = _format or cls.full
58
+ invalid_format_exc = mlrun.errors.MLRunBadRequestError(
59
+ f"Provided format is not supported. format={_format}"
60
+ )
61
+
62
+ if _format in exclude_formats:
63
+ raise invalid_format_exc
64
+
65
+ try:
66
+ format_method = cls.format_method(_format)
67
+ except KeyError:
68
+ raise invalid_format_exc
69
+
70
+ if not format_method:
71
+ return obj
72
+
73
+ return format_method(obj)
74
+
75
+ @staticmethod
76
+ def filter_obj_method(_filter: list[str]) -> typing.Callable:
77
+ """
78
+ Returns a method that filters the object based on the provided list of keys.
79
+ The keys should be in a dot-separated format, denoting the path within the dictionary to the desired key.
80
+ The object maintains its structure, with the filtered keys and their values, while all other keys are removed.
81
+ :param _filter: The list of keys to filter by.
82
+ Example:
83
+ [
84
+ "kind",
85
+ "metadata.name",
86
+ "spec.something.else",
87
+ ]
88
+
89
+ :return: The filtering method.
90
+ """
91
+
92
+ def _filter_method(obj: dict) -> dict:
93
+ formatted_obj = {}
94
+ for key in _filter:
95
+ key_list = key.split(".")
96
+ obj_recursive_iterator = obj
97
+ formatted_obj_recursive_iterator = formatted_obj
98
+ for idx, key in enumerate(key_list):
99
+ if key not in obj_recursive_iterator:
100
+ break
101
+ value = (
102
+ {} if idx < len(key_list) - 1 else obj_recursive_iterator[key]
103
+ )
104
+ formatted_obj_recursive_iterator.setdefault(key, value)
105
+
106
+ obj_recursive_iterator = obj_recursive_iterator[key]
107
+ formatted_obj_recursive_iterator = formatted_obj_recursive_iterator[
108
+ key
109
+ ]
110
+
111
+ return formatted_obj
112
+
113
+ return _filter_method