mlrun 1.10.0rc27__py3-none-any.whl → 1.10.0rc29__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.

mlrun/__init__.py CHANGED
@@ -37,6 +37,7 @@ from .datastore import DataItem, ModelProvider, store_manager
37
37
  from .db import get_run_db
38
38
  from .errors import MLRunInvalidArgumentError, MLRunNotFoundError
39
39
  from .execution import MLClientCtx
40
+ from .hub import get_hub_module, import_module
40
41
  from .model import RunObject, RunTemplate, new_task
41
42
  from .package import ArtifactType, DefaultPackager, Packager, handler
42
43
  from .projects import (
@@ -134,3 +134,8 @@ class HubCatalog(BaseModel):
134
134
  kind: ObjectKind = Field(ObjectKind.hub_catalog, const=True)
135
135
  channel: str
136
136
  catalog: list[HubItem]
137
+
138
+
139
+ class HubModuleType(mlrun.common.types.StrEnum):
140
+ generic = "generic"
141
+ monitoring_app = "monitoring-app"
mlrun/config.py CHANGED
@@ -255,7 +255,8 @@ default_config = {
255
255
  },
256
256
  "runtimes": {
257
257
  "dask": "600",
258
- "dask_cluster_start": "300",
258
+ # cluster start might take some time in case k8s needs to spin up new nodes
259
+ "dask_cluster_start": "600",
259
260
  },
260
261
  "push_notifications": "60",
261
262
  },
@@ -1,4 +1,4 @@
1
- # Copyright 2023 Iguazio
1
+ # Copyright 2025 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.
@@ -12,6 +12,7 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
+ import contextlib
15
16
  import time
16
17
  from pathlib import Path
17
18
  from typing import Optional
@@ -30,6 +31,40 @@ from .base import DataStore, FileStats, make_datastore_schema_sanitizer
30
31
 
31
32
 
32
33
  class AzureBlobStore(DataStore):
34
+ """
35
+ Azure Blob Storage datastore implementation.
36
+
37
+ Supports multiple URL schemas: az://, wasbs://, wasb://
38
+
39
+ Supported Connection String Formats:
40
+ ====================================
41
+
42
+ 1. Account Key (Standard):
43
+ "DefaultEndpointsProtocol=https;AccountName=<account>;AccountKey=<key>;EndpointSuffix=core.windows.net"
44
+
45
+ 2. SAS Token:
46
+ "BlobEndpoint=https://<account>.blob.core.windows.net/;SharedAccessSignature=<sas_token>"
47
+
48
+ 3. Minimal BlobEndpoint:
49
+ "BlobEndpoint=https://<account>.blob.core.windows.net/;AccountName=<account>;AccountKey=<key>"
50
+
51
+ 4. Custom Domain:
52
+ "BlobEndpoint=https://<account>.mydomain.com/;AccountName=<account>;AccountKey=<key>"
53
+
54
+ 5. China/Government Cloud:
55
+ "DefaultEndpointsProtocol=https;AccountName=<account>;AccountKey=<key>;EndpointSuffix=core.chinacloudapi.cn"
56
+
57
+ 6. Full Service Endpoints with SAS:
58
+ "BlobEndpoint=https://<account>.blob.core.windows.net/;QueueEndpoint=...;SharedAccessSignature=<sas>"
59
+
60
+ Authentication Methods:
61
+ ======================
62
+ - Account Key (connection_string or storage_options)
63
+ - SAS Token (connection_string or storage_options)
64
+ - OAuth/Azure AD (storage_options: client_id, client_secret, tenant_id)
65
+
66
+ """
67
+
33
68
  using_bucket = True
34
69
  max_concurrency = 100
35
70
  max_blocksize = 1024 * 1024 * 4
@@ -40,6 +75,12 @@ class AzureBlobStore(DataStore):
40
75
  def __init__(
41
76
  self, parent, schema, name, endpoint="", secrets: Optional[dict] = None
42
77
  ):
78
+ # Extract container from WASBS endpoint before calling super()
79
+ self._container_from_endpoint = None
80
+ if schema in ["wasbs", "wasb"] and endpoint and "@" in endpoint:
81
+ # Handle container@host format
82
+ self._container_from_endpoint, endpoint = endpoint.split("@", 1)
83
+
43
84
  super().__init__(parent, name, schema, endpoint, secrets=secrets)
44
85
  self._service_client = None
45
86
  self._storage_options = None
@@ -67,6 +108,34 @@ class AzureBlobStore(DataStore):
67
108
  or self._get_secret_or_env("AZURE_STORAGE_SAS_TOKEN"),
68
109
  credential=self._get_secret_or_env("credential"),
69
110
  )
111
+ # Use container extracted from WASBS endpoint during initialization
112
+ if self._container_from_endpoint:
113
+ res["container"] = self._container_from_endpoint
114
+
115
+ # For az:// URLs, endpoint contains the container name
116
+ if not res.get("container") and self.kind in ["az"]:
117
+ if container := getattr(self, "endpoint", None):
118
+ res["container"] = container
119
+
120
+ # Last resort: For wasbs:// without container, check if connection string has BlobEndpoint with container
121
+ if not res.get("container") and self.kind in ["wasbs", "wasb"]:
122
+ connection_string = res.get("connection_string")
123
+ if connection_string and "BlobEndpoint=" in connection_string:
124
+ # Try to extract container from BlobEndpoint URL
125
+ for part in connection_string.split(";"):
126
+ if part.startswith("BlobEndpoint="):
127
+ blob_endpoint = part.split("=", 1)[1]
128
+ # Parse URL to get path component
129
+ from urllib.parse import urlparse
130
+
131
+ parsed = urlparse(blob_endpoint)
132
+ if parsed.path and parsed.path.strip("/"):
133
+ # Extract first path segment as container
134
+ path_parts = parsed.path.strip("/").split("/")
135
+ if path_parts[0]:
136
+ res["container"] = path_parts[0]
137
+ break
138
+
70
139
  self._storage_options = self._sanitize_options(res)
71
140
  return self._storage_options
72
141
 
@@ -243,10 +312,12 @@ class AzureBlobStore(DataStore):
243
312
 
244
313
  for key in ["account_name", "account_key", "sas_token"]:
245
314
  if parsed_value := parsed_credential.get(key):
246
- if key in st and st[key] != parsed_value:
315
+ # Only check for conflicts if storage options has a non-empty value for this key
316
+ existing_value = st.get(key)
317
+ if existing_value and existing_value != parsed_value:
247
318
  if key == "account_name":
248
319
  raise mlrun.errors.MLRunInvalidArgumentError(
249
- f"Storage option for '{key}' is '{st[key]}', "
320
+ f"Storage option for '{key}' is '{existing_value}', "
250
321
  f"which does not match corresponding connection string '{parsed_value}'"
251
322
  )
252
323
  else:
@@ -262,7 +333,8 @@ class AzureBlobStore(DataStore):
262
333
  primary_url = primary_url[len("http://") :]
263
334
  if primary_url.startswith("https://"):
264
335
  primary_url = primary_url[len("https://") :]
265
- host = primary_url
336
+ # Remove any path components from the host
337
+ host = primary_url.split("/")[0]
266
338
  elif account_name:
267
339
  host = f"{account_name}.{service}.core.windows.net"
268
340
  else:
@@ -278,7 +350,10 @@ class AzureBlobStore(DataStore):
278
350
  # --- WASB + SAS (container-scoped key; no provider classes needed) ---
279
351
  if "sas_token" in st and st["sas_token"]:
280
352
  sas = st["sas_token"].lstrip("?")
281
- if container := getattr(self, "endpoint", None) or st.get("container"):
353
+
354
+ container = st.get("container")
355
+
356
+ if container:
282
357
  # fs.azure.sas.<container>.<account>.blob.core.windows.net = <sas>
283
358
  res[f"spark.hadoop.fs.azure.sas.{container}.{host}"] = sas
284
359
 
@@ -295,11 +370,12 @@ class AzureBlobStore(DataStore):
295
370
  st = self.storage_options
296
371
  service = "blob"
297
372
 
298
- container = getattr(self, "endpoint", None) or st.get("container")
373
+ container = st.get("container")
374
+
299
375
  if not container:
300
376
  raise mlrun.errors.MLRunInvalidArgumentError(
301
- "Container is required to build the WASB URL "
302
- "(self.endpoint or storage_options['container'])."
377
+ "Container name is required to build the WASB URL. "
378
+ "Set storage_options['container'] or use datastore profile with container specified."
303
379
  )
304
380
 
305
381
  # Prefer host from connection string; else synthesize from account_name
@@ -308,18 +384,23 @@ class AzureBlobStore(DataStore):
308
384
  connection_string = st.get("connection_string")
309
385
 
310
386
  if connection_string:
311
- primary_url, _, _ = parse_connection_str(
312
- connection_string, credential=None, service=service
313
- )
314
- if primary_url.startswith("http://"):
315
- primary_url = primary_url[len("http://") :]
316
- if primary_url.startswith("https://"):
317
- primary_url = primary_url[len("https://") :]
318
- host = primary_url.rstrip("/")
319
-
387
+ with contextlib.suppress(Exception):
388
+ primary_url, _, _ = parse_connection_str(
389
+ connection_string, credential=None, service=service
390
+ )
391
+ if primary_url.startswith("http://"):
392
+ primary_url = primary_url[len("http://") :]
393
+ if primary_url.startswith("https://"):
394
+ primary_url = primary_url[len("https://") :]
395
+ # Remove any path components from the host
396
+ host = primary_url.split("/")[0].rstrip("/")
320
397
  if not host and account_name:
321
398
  host = f"{account_name}.{service}.core.windows.net"
322
399
 
400
+ # For wasbs:// URLs where endpoint is already the host
401
+ if not host and self.kind in ["wasbs", "wasb"] and hasattr(self, "endpoint"):
402
+ host = getattr(self, "endpoint", None)
403
+
323
404
  if not host:
324
405
  raise mlrun.errors.MLRunInvalidArgumentError(
325
406
  "account_name is required (or provide a connection_string) to build the WASB URL."
mlrun/datastore/utils.py CHANGED
@@ -320,7 +320,13 @@ def parse_url(url):
320
320
  parsed_url = urlparse(url)
321
321
  schema = parsed_url.scheme.lower()
322
322
  endpoint = parsed_url.hostname
323
- if endpoint:
323
+
324
+ # Special handling for WASBS URLs to preserve container information
325
+ if schema in ["wasbs", "wasb"] and parsed_url.netloc and "@" in parsed_url.netloc:
326
+ # For wasbs://container@host format, preserve the full netloc as endpoint
327
+ # This allows the datastore to extract container later
328
+ endpoint = parsed_url.netloc
329
+ elif endpoint:
324
330
  # HACK - urlparse returns the hostname after in lower case - we want the original case:
325
331
  # the hostname is a substring of the netloc, in which it's the original case, so we find the indexes of the
326
332
  # hostname in the netloc and take it from there
@@ -331,8 +337,8 @@ def parse_url(url):
331
337
  endpoint = netloc[
332
338
  hostname_index_in_netloc : hostname_index_in_netloc + len(lower_hostname)
333
339
  ]
334
- if parsed_url.port:
335
- endpoint += f":{parsed_url.port}"
340
+ if parsed_url.port:
341
+ endpoint += f":{parsed_url.port}"
336
342
  return schema, endpoint, parsed_url
337
343
 
338
344
 
mlrun/db/base.py CHANGED
@@ -774,6 +774,7 @@ class RunDBInterface(ABC):
774
774
  item_name: Optional[str] = None,
775
775
  tag: Optional[str] = None,
776
776
  version: Optional[str] = None,
777
+ item_type: mlrun.common.schemas.hub.HubSourceType = mlrun.common.schemas.hub.HubSourceType.functions,
777
778
  ):
778
779
  pass
779
780
 
mlrun/db/httpdb.py CHANGED
@@ -4310,6 +4310,7 @@ class HTTPRunDB(RunDBInterface):
4310
4310
  item_name: Optional[str] = None,
4311
4311
  tag: Optional[str] = None,
4312
4312
  version: Optional[str] = None,
4313
+ item_type: HubSourceType = HubSourceType.functions,
4313
4314
  ) -> list[mlrun.common.schemas.hub.IndexedHubSource]:
4314
4315
  """
4315
4316
  List hub sources in the MLRun DB.
@@ -4317,6 +4318,7 @@ class HTTPRunDB(RunDBInterface):
4317
4318
  :param item_name: Sources contain this item will be returned, If not provided all sources will be returned.
4318
4319
  :param tag: Item tag to filter by, supported only if item name is provided.
4319
4320
  :param version: Item version to filter by, supported only if item name is provided and tag is not.
4321
+ :param item_type: Item type to filter by, supported only if item name is provided.
4320
4322
 
4321
4323
  :returns: List of indexed hub sources.
4322
4324
  """
@@ -4324,6 +4326,7 @@ class HTTPRunDB(RunDBInterface):
4324
4326
  params = {}
4325
4327
  if item_name:
4326
4328
  params["item-name"] = normalize_name(item_name)
4329
+ params["item-type"] = item_type
4327
4330
  if tag:
4328
4331
  params["tag"] = tag
4329
4332
  if version:
@@ -5200,7 +5203,7 @@ class HTTPRunDB(RunDBInterface):
5200
5203
 
5201
5204
  :return: A ModelEndpointDriftValues object containing the drift counts over time.
5202
5205
  """
5203
- endpoint_path = f"projects/{project}/model-endpoints/drift-over-time"
5206
+ endpoint_path = f"projects/{project}/model-monitoring/drift-over-time"
5204
5207
  error_message = f"Failed retrieving drift data for {project}"
5205
5208
  response = self.api_call(
5206
5209
  method="GET",
mlrun/db/nopdb.py CHANGED
@@ -673,6 +673,7 @@ class NopDB(RunDBInterface):
673
673
  item_name: Optional[str] = None,
674
674
  tag: Optional[str] = None,
675
675
  version: Optional[str] = None,
676
+ item_type: mlrun.common.schemas.hub.HubSourceType = mlrun.common.schemas.hub.HubSourceType.functions,
676
677
  ):
677
678
  pass
678
679
 
mlrun/hub/__init__.py ADDED
@@ -0,0 +1,15 @@
1
+ # Copyright 2025 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
+ from .module import get_hub_module, import_module
mlrun/hub/module.py ADDED
@@ -0,0 +1,166 @@
1
+ # Copyright 2025 Iguazio
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ import os
16
+ import subprocess
17
+ import sys
18
+ from pathlib import Path
19
+ from typing import Optional, Union
20
+
21
+ import yaml
22
+
23
+ import mlrun.common.types
24
+ import mlrun.utils
25
+ from mlrun.common.schemas.hub import HubModuleType, HubSourceType
26
+ from mlrun.run import function_to_module, get_object
27
+ from mlrun.utils import logger
28
+
29
+ from ..model import ModelObj
30
+ from ..utils import extend_hub_uri_if_needed
31
+
32
+
33
+ class HubModule(ModelObj):
34
+ def __init__(
35
+ self,
36
+ name: str,
37
+ kind: Union[HubModuleType, str],
38
+ version: Optional[str] = None,
39
+ description: Optional[str] = None,
40
+ categories: Optional[list] = None,
41
+ requirements: Optional[list] = None,
42
+ local_path: Optional[str] = None,
43
+ filename: Optional[str] = None,
44
+ example: Optional[str] = None,
45
+ url: Optional[str] = None,
46
+ **kwargs, # catch all for unused args
47
+ ):
48
+ self.name: str = name
49
+ self.version: str = version
50
+ self.kind: HubModuleType = kind
51
+ self.description: str = description or ""
52
+ self.categories: list = categories or []
53
+ self.requirements: list = requirements or []
54
+ self.local_path: str = local_path or ""
55
+ self.filename: str = filename or name + ".py"
56
+ self.example: str = example or ""
57
+ self.url: str = url or ""
58
+
59
+ def module(self):
60
+ """Import the module after downloading its fils to local_path"""
61
+ try:
62
+ return function_to_module(code=self.filename, workdir=self.local_path)
63
+ except FileNotFoundError:
64
+ searched_path = self.local_path or "./"
65
+ raise FileNotFoundError(
66
+ f"Module file {self.filename} not found in {searched_path}, try calling download_module_files() first"
67
+ )
68
+
69
+ def install_requirements(self) -> None:
70
+ """
71
+ Install pip-style requirements (e.g., ["pandas>=2.0.0", "requests==2.31.0"]).
72
+ """
73
+ for req in self.requirements:
74
+ logger.info(f"Installing {req} ...")
75
+ try:
76
+ subprocess.run(
77
+ [sys.executable, "-m", "pip", "install", req], check=True, text=True
78
+ )
79
+ logger.info(f"Installed {req}")
80
+ except subprocess.CalledProcessError as e:
81
+ logger.error(f"Failed to install {req} (exit code {e.returncode})")
82
+
83
+ def download_module_files(self, local_path=None, secrets=None):
84
+ """
85
+ Download this hub module’s files (code file and, if available, an example notebook) to the target directory
86
+ specified by `local_path` (defaults to the current working directory).
87
+ This path will be used later to locate the code file when importing the module.
88
+ """
89
+ self.local_path = self.verify_directory(path=local_path)
90
+ source_url, _ = extend_hub_uri_if_needed(
91
+ uri=self.url, asset_type=HubSourceType.modules, file=self.filename
92
+ )
93
+ self._download_object(
94
+ obj_url=source_url, target_name=self.filename, secrets=secrets
95
+ )
96
+ if self.example:
97
+ example_url, _ = extend_hub_uri_if_needed(
98
+ uri=self.url, asset_type=HubSourceType.modules, file=self.example
99
+ )
100
+ self._download_object(
101
+ obj_url=example_url, target_name=self.example, secrets=secrets
102
+ )
103
+
104
+ def _download_object(self, obj_url, target_name, secrets=None):
105
+ data = get_object(url=obj_url, secrets=secrets)
106
+ target_dir = self.local_path if self.local_path is not None else os.getcwd()
107
+ target_filepath = os.path.join(target_dir, target_name)
108
+ with open(target_filepath, "wb") as f:
109
+ f.write(data)
110
+
111
+ @staticmethod
112
+ def verify_directory(path: str) -> Path:
113
+ """Validate that the given path is an existing directory."""
114
+ if path:
115
+ path = Path(path)
116
+ if not path.exists():
117
+ raise ValueError(f"Path does not exist: {path}")
118
+ if not path.is_dir():
119
+ raise ValueError(f"Path is not a directory: {path}")
120
+ return path
121
+
122
+
123
+ def get_hub_module(
124
+ url="", download_files=True, secrets=None, local_path=None
125
+ ) -> HubModule:
126
+ """
127
+ Get a hub-module object containing metadata of the requested module.
128
+ :param url: Hub module url in the format "hub://[<source>/]<item-name>[:<tag>]"
129
+ :param download_files: When set to True, the module files (code file and example notebook) are downloaded
130
+ :param secrets: Optional, credentials dict for DB or URL (s3, v3io, ...)
131
+ :param local_path: Path to target directory for the module files. Ignored when download_files is set to False.
132
+ Defaults to the current working directory.
133
+
134
+ :return: HubModule object
135
+ """
136
+ item_yaml_url, is_hub_uri = extend_hub_uri_if_needed(
137
+ uri=url, asset_type=HubSourceType.modules, file="item.yaml"
138
+ )
139
+ if not is_hub_uri:
140
+ raise mlrun.errors.MLRunInvalidArgumentError("Not a valid hub URL")
141
+ yaml_obj = get_object(url=item_yaml_url, secrets=secrets)
142
+ item_yaml = yaml.safe_load(yaml_obj)
143
+ spec = item_yaml.pop("spec", {})
144
+ hub_module = HubModule(**item_yaml, **spec, url=url)
145
+ if download_files:
146
+ hub_module.download_module_files(local_path=local_path, secrets=secrets)
147
+ return hub_module
148
+
149
+
150
+ def import_module(url="", install_requirements=False, secrets=None, local_path=None):
151
+ """
152
+ Import a module from the hub to use directly.
153
+ :param url: hub module url in the format "hub://[<source>/]<item-name>[:<tag>]"
154
+ :param install_requirements: when set to True, the module's requirements are installed.
155
+ :param secrets: optional, credentials dict for DB or URL (s3, v3io, ...)
156
+ :param local_path: Path to target directory for the module files (code and example notebook).
157
+ Defaults to the current working directory.
158
+
159
+ :return: the module
160
+ """
161
+ hub_module: HubModule = get_hub_module(
162
+ url=url, download_files=True, secrets=secrets, local_path=local_path
163
+ )
164
+ if install_requirements:
165
+ hub_module.install_requirements()
166
+ return hub_module.module()
@@ -1499,20 +1499,51 @@ class V3IOTSDBConnector(TSDBConnector):
1499
1499
  ) -> mm_schemas.ModelEndpointDriftValues:
1500
1500
  table = mm_schemas.V3IOTSDBTables.APP_RESULTS
1501
1501
  start, end, interval = self._prepare_aligned_start_end(start, end)
1502
-
1503
- # get per time-interval x endpoint_id combination the max result status
1504
1502
  df = self._get_records(
1505
1503
  table=table,
1506
1504
  start=start,
1507
1505
  end=end,
1508
- interval=interval,
1509
- sliding_window_step=interval,
1510
1506
  columns=[mm_schemas.ResultData.RESULT_STATUS],
1511
- agg_funcs=["max"],
1512
- group_by=mm_schemas.WriterEvent.ENDPOINT_ID,
1513
1507
  )
1508
+ df = self._aggregate_raw_drift_data(df, start, end, interval)
1514
1509
  if df.empty:
1515
1510
  return mm_schemas.ModelEndpointDriftValues(values=[])
1516
1511
  df = df[df[f"max({mm_schemas.ResultData.RESULT_STATUS})"] >= 1]
1517
- df = df.reset_index(names="_wstart")
1518
1512
  return self._df_to_drift_data(df)
1513
+
1514
+ @staticmethod
1515
+ def _aggregate_raw_drift_data(
1516
+ df: pd.DataFrame, start: datetime, end: datetime, interval: str
1517
+ ) -> pd.DataFrame:
1518
+ if df.empty:
1519
+ return df
1520
+ if not isinstance(df.index, pd.DatetimeIndex):
1521
+ raise TypeError("Expected a DatetimeIndex on the DataFrame (time index).")
1522
+ df[EventFieldType.ENDPOINT_ID] = (
1523
+ df[EventFieldType.ENDPOINT_ID].astype("string").str.strip()
1524
+ ) # remove extra data carried by the category dtype
1525
+ window = df.loc[
1526
+ (df.index >= start) & (df.index < end),
1527
+ [mm_schemas.ResultData.RESULT_STATUS, EventFieldType.ENDPOINT_ID],
1528
+ ]
1529
+ out = (
1530
+ window.groupby(
1531
+ [
1532
+ EventFieldType.ENDPOINT_ID,
1533
+ pd.Grouper(
1534
+ freq=interval, origin=start, label="left", closed="left"
1535
+ ),
1536
+ ]
1537
+ # align to start, [start, end) intervals
1538
+ )[mm_schemas.ResultData.RESULT_STATUS]
1539
+ .max()
1540
+ .reset_index()
1541
+ .rename(
1542
+ columns={
1543
+ mm_schemas.ResultData.RESULT_STATUS: f"max({mm_schemas.ResultData.RESULT_STATUS})"
1544
+ }
1545
+ )
1546
+ )
1547
+ return out.rename(
1548
+ columns={"time": "_wstart"}
1549
+ ) # rename datetime column to _wstart to align with the tdengine result
@@ -659,3 +659,26 @@ def get_start_end(
659
659
  )
660
660
 
661
661
  return start, end
662
+
663
+
664
+ def validate_time_range(
665
+ start: Optional[datetime.datetime] = None, end: Optional[datetime.datetime] = None
666
+ ) -> tuple[datetime.datetime, datetime.datetime]:
667
+ """
668
+ validate start and end parameters and set default values if needed.
669
+ :param start: Either None or datetime, None is handled as datetime.now(tz=timezone.utc) - timedelta(days=1)
670
+ :param end: Either None or datetime, None is handled as datetime.now(tz=timezone.utc)
671
+ :return: start datetime, end datetime
672
+ """
673
+ end = end or mlrun.utils.helpers.datetime_now()
674
+ start = start or (end - datetime.timedelta(days=1))
675
+ if start.tzinfo is None or end.tzinfo is None:
676
+ raise mlrun.errors.MLRunInvalidArgumentTypeError(
677
+ "Custom start and end times must contain the timezone."
678
+ )
679
+ if start > end:
680
+ raise mlrun.errors.MLRunInvalidArgumentError(
681
+ "The start time must be before the end time. Note that if end time is not provided, "
682
+ "the current time is used by default."
683
+ )
684
+ return start, end
@@ -177,7 +177,12 @@ def run_function(
177
177
  This ensures latest code changes are executed. This argument must be used in
178
178
  conjunction with the local=True argument.
179
179
  :param output_path: path to store artifacts, when running in a workflow this will be set automatically
180
- :param retry: Retry configuration for the run, can be a dict or an instance of mlrun.model.Retry.
180
+ :param retry: Retry configuration for the run, can be a dict or an instance of
181
+ :py:class:`~mlrun.model.Retry`.
182
+ The `count` field in the `Retry` object specifies the number of retry attempts.
183
+ If `count=0`, the run will not be retried.
184
+ The `backoff` field specifies the retry backoff strategy between retry attempts.
185
+ If not provided, no backoff is applied.
181
186
  :return: MLRun RunObject or PipelineNodeWrapper
182
187
  """
183
188
  if artifact_path:
mlrun/projects/project.py CHANGED
@@ -4104,7 +4104,12 @@ class MlrunProject(ModelObj):
4104
4104
  This ensures latest code changes are executed. This argument must be used in
4105
4105
  conjunction with the local=True argument.
4106
4106
  :param output_path: path to store artifacts, when running in a workflow this will be set automatically
4107
- :param retry: Retry configuration for the run, can be a dict or an instance of mlrun.model.Retry.
4107
+ :param retry: Retry configuration for the run, can be a dict or an instance of
4108
+ :py:class:`~mlrun.model.Retry`.
4109
+ The `count` field in the `Retry` object specifies the number of retry attempts.
4110
+ If `count=0`, the run will not be retried.
4111
+ The `backoff` field specifies the retry backoff strategy between retry attempts.
4112
+ If not provided, no backoff is applied.
4108
4113
  :return: MLRun RunObject or PipelineNodeWrapper
4109
4114
  """
4110
4115
  if artifact_path:
mlrun/runtimes/base.py CHANGED
@@ -376,7 +376,12 @@ class BaseRuntime(ModelObj):
376
376
  This ensures latest code changes are executed. This argument must be used in
377
377
  conjunction with the local=True argument.
378
378
  :param output_path: Default artifact output path.
379
- :param retry: Retry configuration for the run, can be a dict or an instance of mlrun.model.Retry.
379
+ :param retry: Retry configuration for the run, can be a dict or an instance of
380
+ :py:class:`~mlrun.model.Retry`.
381
+ The `count` field in the `Retry` object specifies the number of retry attempts.
382
+ If `count=0`, the run will not be retried.
383
+ The `backoff` field specifies the retry backoff strategy between retry attempts.
384
+ If not provided, no backoff is applied.
380
385
  :return: Run context object (RunObject) with run metadata, results and status
381
386
  """
382
387
  if artifact_path or out_path:
@@ -443,9 +448,11 @@ class BaseRuntime(ModelObj):
443
448
  :param runobj: Run context object (RunObject) with run metadata and status
444
449
  :return: Dictionary with all the variables that could be parsed
445
450
  """
451
+ active_project = self.metadata.project or config.active_project
446
452
  runtime_env = {
447
- mlrun_constants.MLRUN_ACTIVE_PROJECT: self.metadata.project
448
- or config.active_project
453
+ mlrun_constants.MLRUN_ACTIVE_PROJECT: active_project,
454
+ # TODO: Remove this in 1.12.0 as MLRUN_DEFAULT_PROJECT is deprecated and should not be injected anymore
455
+ "MLRUN_DEFAULT_PROJECT": active_project,
449
456
  }
450
457
  if runobj:
451
458
  runtime_env["MLRUN_EXEC_CONFIG"] = runobj.to_json(
@@ -698,6 +698,12 @@ class ApplicationRuntime(RemoteRuntime):
698
698
  """
699
699
  # create a function that includes only the reverse proxy, without the application
700
700
 
701
+ if not mlrun.get_current_project(silent=True):
702
+ raise mlrun.errors.MLRunMissingProjectError(
703
+ "An active project is required to run deploy_reverse_proxy_image(). "
704
+ "Use `mlrun.get_or_create_project()` or set an active project first."
705
+ )
706
+
701
707
  reverse_proxy_func = mlrun.run.new_function(
702
708
  name="reverse-proxy-temp", kind="remote"
703
709
  )
@@ -14,6 +14,7 @@
14
14
  import json
15
15
  import os
16
16
  import warnings
17
+ from base64 import b64decode
17
18
  from copy import deepcopy
18
19
  from typing import Optional, Union
19
20
 
@@ -678,6 +679,17 @@ class ServingRuntime(RemoteRuntime):
678
679
  f"function {function} is used in steps and is not defined, "
679
680
  "use the .add_child_function() to specify child function attributes"
680
681
  )
682
+ if isinstance(self.spec.graph, RootFlowStep) and any(
683
+ isinstance(step_type, mlrun.serving.states.ModelRunnerStep)
684
+ for step_type in self.spec.graph.steps.values()
685
+ ):
686
+ # Add import for LLModel
687
+ decoded_code = b64decode(self.spec.build.functionSourceCode).decode("utf-8")
688
+ import_llmodel_code = "\nfrom mlrun.serving.states import LLModel\n"
689
+ if import_llmodel_code not in decoded_code:
690
+ decoded_code += import_llmodel_code
691
+ encoded_code = mlrun.utils.helpers.encode_user_code(decoded_code)
692
+ self.spec.build.functionSourceCode = encoded_code
681
693
 
682
694
  # Handle secret processing before handling child functions, since secrets are transferred to them
683
695
  if self.spec.secret_sources:
mlrun/runtimes/pod.py CHANGED
@@ -109,6 +109,7 @@ class KubeResourceSpec(FunctionSpec):
109
109
  "track_models",
110
110
  "parameters",
111
111
  "graph",
112
+ "filename",
112
113
  ]
113
114
  _default_fields_to_strip = FunctionSpec._default_fields_to_strip + [
114
115
  "volumes",
mlrun/serving/states.py CHANGED
@@ -1641,6 +1641,9 @@ class ModelRunnerStep(MonitoredStep):
1641
1641
  model_runner_step.add_model(..., model_class=MyModel(name="my_model"))
1642
1642
  graph.to(model_runner_step)
1643
1643
 
1644
+ Note when ModelRunnerStep is used in a graph, MLRun automatically imports
1645
+ the default language model class (LLModel) during function deployment.
1646
+
1644
1647
  :param model_selector: ModelSelector instance whose select() method will be used to select models to run on each
1645
1648
  event. Optional. If not passed, all models will be run.
1646
1649
  :param raise_exception: If True, an error will be raised when model selection fails or if one of the models raised
@@ -1829,7 +1832,9 @@ class ModelRunnerStep(MonitoredStep):
1829
1832
  Add a Model to this ModelRunner.
1830
1833
 
1831
1834
  :param endpoint_name: str, will identify the model in the ModelRunnerStep, and assign model endpoint name
1832
- :param model_class: Model class name
1835
+ :param model_class: Model class name. If LLModel is chosen
1836
+ (either by name `LLModel` or by its full path, e.g. mlrun.serving.states.LLModel),
1837
+ outputs will be overridden with UsageResponseKeys fields.
1833
1838
  :param execution_mechanism: Parallel execution mechanism to be used to execute this model. Must be one of:
1834
1839
  * "process_pool" – To run in a separate process from a process pool. This is appropriate for CPU or GPU
1835
1840
  intensive tasks as they would otherwise block the main process by holding Python's Global Interpreter
@@ -1902,7 +1907,8 @@ class ModelRunnerStep(MonitoredStep):
1902
1907
  "Cannot provide a model object as argument to `model_class` and also provide `model_parameters`."
1903
1908
  )
1904
1909
  if type(model_class) is LLModel or (
1905
- isinstance(model_class, str) and model_class == LLModel.__name__
1910
+ isinstance(model_class, str)
1911
+ and model_class.split(".")[-1] == LLModel.__name__
1906
1912
  ):
1907
1913
  if outputs:
1908
1914
  warnings.warn(
@@ -2848,7 +2854,9 @@ class RootFlowStep(FlowStep):
2848
2854
  """
2849
2855
  Add a shared model to the graph, this model will be available to all the ModelRunners in the graph
2850
2856
  :param name: Name of the shared model (should be unique in the graph)
2851
- :param model_class: Model class name
2857
+ :param model_class: Model class name. If LLModel is chosen
2858
+ (either by name `LLModel` or by its full path, e.g. mlrun.serving.states.LLModel),
2859
+ outputs will be overridden with UsageResponseKeys fields.
2852
2860
  :param execution_mechanism: Parallel execution mechanism to be used to execute this model. Must be one of:
2853
2861
  * "process_pool" – To run in a separate process from a process pool. This is appropriate for CPU or GPU
2854
2862
  intensive tasks as they would otherwise block the main process by holding Python's Global Interpreter
@@ -2892,7 +2900,8 @@ class RootFlowStep(FlowStep):
2892
2900
  "Cannot provide a model object as argument to `model_class` and also provide `model_parameters`."
2893
2901
  )
2894
2902
  if type(model_class) is LLModel or (
2895
- isinstance(model_class, str) and model_class == LLModel.__name__
2903
+ isinstance(model_class, str)
2904
+ and model_class.split(".")[-1] == LLModel.__name__
2896
2905
  ):
2897
2906
  if outputs:
2898
2907
  warnings.warn(
mlrun/utils/helpers.py CHANGED
@@ -45,6 +45,7 @@ import pytz
45
45
  import semver
46
46
  import yaml
47
47
  from dateutil import parser
48
+ from orjson import orjson
48
49
  from pandas import Timedelta, Timestamp
49
50
  from yaml.representer import RepresenterError
50
51
 
@@ -61,6 +62,7 @@ import mlrun_pipelines.models
61
62
  import mlrun_pipelines.utils
62
63
  from mlrun.common.constants import MYSQL_MEDIUMBLOB_SIZE_BYTES
63
64
  from mlrun.common.schemas import ArtifactCategories
65
+ from mlrun.common.schemas.hub import HubSourceType
64
66
  from mlrun.config import config
65
67
  from mlrun_pipelines.models import PipelineRun
66
68
 
@@ -801,11 +803,17 @@ def remove_tag_from_artifact_uri(uri: str) -> Optional[str]:
801
803
  return uri if not add_store else DB_SCHEMA + "://" + uri
802
804
 
803
805
 
804
- def extend_hub_uri_if_needed(uri) -> tuple[str, bool]:
806
+ def extend_hub_uri_if_needed(
807
+ uri: str,
808
+ asset_type: HubSourceType = HubSourceType.functions,
809
+ file: str = "function.yaml",
810
+ ) -> tuple[str, bool]:
805
811
  """
806
- Retrieve the full uri of the function's yaml in the hub.
812
+ Retrieve the full uri of an object in the hub.
807
813
 
808
814
  :param uri: structure: "hub://[<source>/]<item-name>[:<tag>]"
815
+ :param asset_type: The type of the hub item (functions, modules, etc.)
816
+ :param file: The file name inside the hub item directory (default: function.yaml)
809
817
 
810
818
  :return: A tuple of:
811
819
  [0] = Extended URI of item
@@ -831,7 +839,7 @@ def extend_hub_uri_if_needed(uri) -> tuple[str, bool]:
831
839
  name = normalize_name(name=name)
832
840
  if not source_name:
833
841
  # Searching item in all sources
834
- sources = db.list_hub_sources(item_name=name, tag=tag)
842
+ sources = db.list_hub_sources(item_name=name, tag=tag, item_type=asset_type)
835
843
  if not sources:
836
844
  raise mlrun.errors.MLRunNotFoundError(
837
845
  f"Item={name}, tag={tag} not found in any hub source"
@@ -841,13 +849,10 @@ def extend_hub_uri_if_needed(uri) -> tuple[str, bool]:
841
849
  else:
842
850
  # Specific source is given
843
851
  indexed_source = db.get_hub_source(source_name)
844
- # hub function directory name are with underscores instead of hyphens
852
+ # hub directories name are with underscores instead of hyphens
845
853
  name = name.replace("-", "_")
846
- function_suffix = f"{name}/{tag}/src/function.yaml"
847
- function_type = mlrun.common.schemas.hub.HubSourceType.functions
848
- return indexed_source.source.get_full_uri(
849
- function_suffix, function_type
850
- ), is_hub_uri
854
+ suffix = f"{name}/{tag}/src/{file}"
855
+ return indexed_source.source.get_full_uri(suffix, asset_type), is_hub_uri
851
856
 
852
857
 
853
858
  def gen_md_table(header, rows=None):
@@ -1214,52 +1219,58 @@ def get_workflow_url(
1214
1219
 
1215
1220
 
1216
1221
  def get_kfp_list_runs_filter(
1217
- project_name: Optional[str] = None,
1218
- end_date: Optional[str] = None,
1219
1222
  start_date: Optional[str] = None,
1223
+ end_date: Optional[str] = None,
1224
+ filter_: Optional[str] = None,
1225
+ experiment_ids: Optional[list[str]] = None,
1220
1226
  ) -> str:
1221
1227
  """
1222
- Generates a filter for listing Kubeflow Pipelines (KFP) runs.
1223
-
1224
- :param project_name: The name of the project. If "*", it won't filter by project.
1225
- :param end_date: The latest creation date for filtering runs (ISO 8601 format).
1226
- :param start_date: The earliest creation date for filtering runs (ISO 8601 format).
1227
- :return: A JSON-formatted filter string for KFP.
1228
+ Generate a filter for KFP runs based on start and end dates, and experiment IDs.
1228
1229
  """
1230
+ existing_filter_object = json.loads(filter_) if filter_ else {"predicates": []}
1231
+ preserved_predicates = [
1232
+ predicate
1233
+ for predicate in existing_filter_object.get("predicates", [])
1234
+ if predicate.get("key") != "name"
1235
+ ]
1229
1236
 
1230
- # KFP filter operation codes
1231
- kfp_less_than_or_equal_op = 7 # '<='
1232
- kfp_greater_than_or_equal_op = 5 # '>='
1233
- kfp_substring_op = 9 # Substring match
1234
-
1235
- filters = {"predicates": []}
1236
-
1237
+ new_predicates = []
1237
1238
  if end_date:
1238
- filters["predicates"].append(
1239
+ new_predicates.append(
1239
1240
  {
1240
- "key": "created_at",
1241
- "op": kfp_less_than_or_equal_op,
1241
+ "key": mlrun_pipelines.models.FilterFields.CREATED_AT,
1242
+ "op": mlrun_pipelines.models.FilterOperations.LESS_THAN_EQUALS.value,
1242
1243
  "timestamp_value": end_date,
1243
1244
  }
1244
1245
  )
1245
1246
 
1246
- if project_name and project_name != "*":
1247
- filters["predicates"].append(
1247
+ if start_date:
1248
+ new_predicates.append(
1248
1249
  {
1249
- "key": "name",
1250
- "op": kfp_substring_op,
1251
- "string_value": project_name,
1250
+ "key": mlrun_pipelines.models.FilterFields.CREATED_AT,
1251
+ "op": mlrun_pipelines.models.FilterOperations.GREATER_THAN_EQUALS.value,
1252
+ "timestamp_value": start_date,
1252
1253
  }
1253
1254
  )
1254
- if start_date:
1255
- filters["predicates"].append(
1255
+
1256
+ if experiment_ids and all(experiment_ids):
1257
+ new_predicates.append(
1256
1258
  {
1257
- "key": "created_at",
1258
- "op": kfp_greater_than_or_equal_op,
1259
- "timestamp_value": start_date,
1259
+ "key": mlrun_pipelines.models.FilterFields.EXPERIMENT_ID,
1260
+ "op": mlrun_pipelines.models.FilterOperations.IN.value,
1261
+ "string_values": {"values": experiment_ids},
1260
1262
  }
1261
1263
  )
1262
- return json.dumps(filters)
1264
+
1265
+ final_filter_object = {"predicates": preserved_predicates + new_predicates}
1266
+ if not final_filter_object["predicates"]:
1267
+ return ""
1268
+
1269
+ logger.debug(
1270
+ "Generated KFP runs filter",
1271
+ filter_object_with_predicates=final_filter_object,
1272
+ )
1273
+ return orjson.dumps(final_filter_object).decode()
1263
1274
 
1264
1275
 
1265
1276
  def validate_and_convert_date(date_input: str) -> str:
@@ -1,4 +1,4 @@
1
1
  {
2
- "git_commit": "8b5d7492c858f675bcf8fce28d536c9af13a8d86",
3
- "version": "1.10.0-rc27"
2
+ "git_commit": "c36122fc31d3870a252575a3019e26ae8128b24a",
3
+ "version": "1.10.0-rc29"
4
4
  }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mlrun
3
- Version: 1.10.0rc27
3
+ Version: 1.10.0rc29
4
4
  Summary: Tracking and config of machine learning runs
5
5
  Home-page: https://github.com/mlrun/mlrun
6
6
  Author: Yaron Haviv
@@ -22,7 +22,7 @@ Requires-Python: >=3.9, <3.12
22
22
  Description-Content-Type: text/markdown
23
23
  License-File: LICENSE
24
24
  Requires-Dist: urllib3>=1.26.20
25
- Requires-Dist: v3io-frames>=0.10.15
25
+ Requires-Dist: v3io-frames>=0.10.16
26
26
  Requires-Dist: GitPython>=3.1.41,~=3.1
27
27
  Requires-Dist: aiohttp~=3.11
28
28
  Requires-Dist: aiohttp-retry~=2.9
@@ -1,6 +1,6 @@
1
- mlrun/__init__.py,sha256=JYy9uteFFNPbPoC0geDEPhaLrfiqTijxUhLZSToAky4,8029
1
+ mlrun/__init__.py,sha256=acM2jRv7RCvBROwucuC01Rf_HdvV3xUPtJlQtX_01MY,8076
2
2
  mlrun/__main__.py,sha256=wQNaxW7QsqFBtWffnPkw-497fnpsrQzUnscBQQAP_UM,48364
3
- mlrun/config.py,sha256=3FWf5jbJDJrwfipSXoiNWOQ5A2Vy4FcZl7Ai8Pv4yIg,73057
3
+ mlrun/config.py,sha256=F1PDI88t2cFujGnDr4YslEBzG6SckBKjUSdkxFX3zUE,73149
4
4
  mlrun/errors.py,sha256=bAk0t_qmCxQSPNK0TugOAfA5R6f0G6OYvEvXUWSJ_5U,9062
5
5
  mlrun/execution.py,sha256=wkmT1k0QROgGJFMBIsYUsJaqEF2bkqaYVzp_ZQb527Q,58814
6
6
  mlrun/features.py,sha256=jMEXo6NB36A6iaxNEJWzdtYwUmglYD90OIKTIEeWhE8,15841
@@ -56,7 +56,7 @@ mlrun/common/schemas/feature_store.py,sha256=Kz7AWQ1RCPA8sTL9cGRZnfUBhWf4MX_5yyY
56
56
  mlrun/common/schemas/frontend_spec.py,sha256=tR8k78cppYK-X8kCWe0mz1gk8yqpsn2IxM3QmBdTJs8,2622
57
57
  mlrun/common/schemas/function.py,sha256=BUHenAK6r_mWtDrBWE42xPJU8zh8ng5Usj7GmB_SAcU,5108
58
58
  mlrun/common/schemas/http.py,sha256=KozLgGV1vpNXQ8Qptr_Zm6BEbc2VcU42hSphe_ffe_A,704
59
- mlrun/common/schemas/hub.py,sha256=k6WycRuUZ343ISDniMSDO_Nr8BlAQL5MTKYIvAUfHf0,4154
59
+ mlrun/common/schemas/hub.py,sha256=K_9AyyYF-qnwjvkGWYFEke-jG58pS3Klv1IKAkdWOxA,4267
60
60
  mlrun/common/schemas/k8s.py,sha256=YgyDK7KNt29GHCOxd1vw-jnl_757cIPLzViCTNT1Zcc,1403
61
61
  mlrun/common/schemas/memory_reports.py,sha256=Q6w7xofQlMD-iqjE8uK9yU5ijLPkht_EsXJCMad_TQo,899
62
62
  mlrun/common/schemas/notification.py,sha256=Q-tBaU_V7YZiuj3ankuACf3_-hb874_osxq0eaW90Ww,5549
@@ -85,7 +85,7 @@ mlrun/data_types/spark.py,sha256=I5JC887dT9RGs5Tqz5zaRxlCMyhMeFmwuNbExQoyW0E,962
85
85
  mlrun/data_types/to_pandas.py,sha256=KOy0FLXPJirsgH6szcC5BI6t70yVDCjuo6LmuYHNTuI,11429
86
86
  mlrun/datastore/__init__.py,sha256=LAAqChT1ydUpQ9f8PpAMXb20xjpr1kMMx74ZvtyiTp4,6097
87
87
  mlrun/datastore/alibaba_oss.py,sha256=E0t0-e9Me2t2Mux2LWdC9riOG921TgNjhoy897JJX7o,4932
88
- mlrun/datastore/azure_blob.py,sha256=g_ZM4LtccFsDqV2hG_6kfxHB-aGuAdmXEasR_SODWro,13546
88
+ mlrun/datastore/azure_blob.py,sha256=G1NNAyJMPWB_ziHASrcxIx72ueCTK6E7qsq1Vig5xEM,17328
89
89
  mlrun/datastore/base.py,sha256=yLdnFCL2k_rcasdbxXjnQr7Lwm-A79LnW9AITtn9-p4,25450
90
90
  mlrun/datastore/datastore.py,sha256=F9NdQFwyAHgjKFSQ1mcLZBuxNqXXesNMjtIVj03L5Gk,13422
91
91
  mlrun/datastore/datastore_profile.py,sha256=K2MrA0KjznkoWci5ua6L_k1rjMGBfCsQFAql-Iwok0M,24680
@@ -104,7 +104,7 @@ mlrun/datastore/spark_utils.py,sha256=dn0RWpYzee-M8UZw-NVuHAdqlNAZ7VO-fNtI8ZiDky
104
104
  mlrun/datastore/store_resources.py,sha256=s2794zqkzy_mjRMvRedDNs_tycTLoF8wxTqsWRQphCE,6839
105
105
  mlrun/datastore/storeytargets.py,sha256=c1NRT_dfwlwjY8O8KnD_8PKaRRng5YctlAZS4U4xpZs,6454
106
106
  mlrun/datastore/targets.py,sha256=8dRnLy1wBYJbVyommYkpGeztdT1CsfFHZY6Zh7o8X-Q,79165
107
- mlrun/datastore/utils.py,sha256=jxvq4lgQfgqb7dwKe4Kp51fYCCyOvitEdIfV2mzlqxg,11936
107
+ mlrun/datastore/utils.py,sha256=0EMNZpRHOi8zQBsE3rAe_7JmPojVc3-mIY_1n5SBkJI,12288
108
108
  mlrun/datastore/v3io.py,sha256=sMn5473k_bXyIJovNf0rahbVHRmO0YPdOwIhbs06clg,8201
109
109
  mlrun/datastore/vectorstore.py,sha256=k-yom5gfw20hnVG0Rg7aBEehuXwvAloZwn0cx0VGals,11708
110
110
  mlrun/datastore/model_provider/__init__.py,sha256=kXGBqhLN0rlAx0kTXhozGzFsIdSqW0uTSKMmsLgq_is,569
@@ -116,10 +116,10 @@ mlrun/datastore/wasbfs/__init__.py,sha256=s5Ul-0kAhYqFjKDR2X0O2vDGDbLQQduElb32Ev
116
116
  mlrun/datastore/wasbfs/fs.py,sha256=ge8NK__5vTcFT-krI155_8RDUywQw4SIRX6BWATXy9Q,6299
117
117
  mlrun/db/__init__.py,sha256=WqJ4x8lqJ7ZoKbhEyFqkYADd9P6E3citckx9e9ZLcIU,1163
118
118
  mlrun/db/auth_utils.py,sha256=hpg8D2r82oN0BWabuWN04BTNZ7jYMAF242YSUpK7LFM,5211
119
- mlrun/db/base.py,sha256=D4P8jhsp4j3ZPg2tKRTgFgm4hrGAx7kVnmio9qfJZDI,32295
119
+ mlrun/db/base.py,sha256=QNqL29xYs2yL4JKHfvljpf-UsIoUeMxun-eL33msJmc,32405
120
120
  mlrun/db/factory.py,sha256=yP2vVmveUE7LYTCHbS6lQIxP9rW--zdISWuPd_I3d_4,2111
121
- mlrun/db/httpdb.py,sha256=-Jl7WsZDFcTSpiSmBrutLoMPGALDjpDYI899i3F9hcw,238788
122
- mlrun/db/nopdb.py,sha256=SZqCaCnaijT8-vivdVjj0VvZcZyqzat4YFFhOJlrTtI,28661
121
+ mlrun/db/httpdb.py,sha256=1XEWpfZm2wW3d6eUqsE-13Nk4Zm2lLKg18J53E5vE10,238986
122
+ mlrun/db/nopdb.py,sha256=iClAugTqMPPQRkXb3uzf_vFhmnfuIKCLpK5M6QKHT4Y,28771
123
123
  mlrun/feature_store/__init__.py,sha256=SlI845bWt6xX34SXunHHqhmFAR9-5v2ak8N-qpcAPGo,1328
124
124
  mlrun/feature_store/api.py,sha256=qKj5Tk6prTab6XWatWhBuPRVp0eJEctoxRMN2wz48vA,32168
125
125
  mlrun/feature_store/common.py,sha256=JlQA7XWkg9fLuw7cXFmWpUneQqM3NBhwv7DU_xlenWI,12819
@@ -219,6 +219,8 @@ mlrun/frameworks/xgboost/__init__.py,sha256=NyFRxu5v5z8oegbJP05PFUmfJL3I3JeN1PYH
219
219
  mlrun/frameworks/xgboost/mlrun_interface.py,sha256=KINOf0udbY75raTewjEFGNlIRyE0evpoJAWQrSVu17Y,877
220
220
  mlrun/frameworks/xgboost/model_handler.py,sha256=bJq4D1VK3rzhALovqIV5mS0LvGiTlsgAkHanD25pU2c,11663
221
221
  mlrun/frameworks/xgboost/utils.py,sha256=4rShiFChzDbWJ4HoTo4qV_lj-Z89pHBAp6Z1yHmU8wA,1068
222
+ mlrun/hub/__init__.py,sha256=50cXcEk8i5G8KQ-nzF6iZDkMbXd-zMNd8nQZ7y7KTVI,620
223
+ mlrun/hub/module.py,sha256=EDdQ2nFfH-i_S1WAHgtxh8CYK-P1ByD95Eow74tdzOY,6726
222
224
  mlrun/launcher/__init__.py,sha256=JL8qkT1lLr1YvW6iP0hmwDTaSR2RfrMDx0-1gWRhTOE,571
223
225
  mlrun/launcher/base.py,sha256=IgBE-ZS1ZiGzucg5SElGtO4qOB0cqYQfGtZTcRc2S3Y,17378
224
226
  mlrun/launcher/client.py,sha256=cl40ZdF2fU1QbUKdl4Xnucb1u2h-8_dn095qIUyxbuM,6402
@@ -229,7 +231,7 @@ mlrun/model_monitoring/__init__.py,sha256=qDQnncjya9XPTlfvGyfWsZWiXc-glGZrrNja-5
229
231
  mlrun/model_monitoring/api.py,sha256=k0eOm-vW8z2u05PwMK2PI2mSAplK0xGIrUe_XWk7mRM,27000
230
232
  mlrun/model_monitoring/controller.py,sha256=2XOkOZRB03K9ph6TH-ICspHga-GQOURL0C8-0GTHaTY,43961
231
233
  mlrun/model_monitoring/features_drift_table.py,sha256=c6GpKtpOJbuT1u5uMWDL_S-6N4YPOmlktWMqPme3KFY,25308
232
- mlrun/model_monitoring/helpers.py,sha256=VQ_afyhqzFMOqPdqpkpX3md_afjlkFtsUWIg28zxp5g,23596
234
+ mlrun/model_monitoring/helpers.py,sha256=50oFqgIc5xFHYPIVgq3M-Gbr7epqAI5NgHmvOeMy52U,24667
233
235
  mlrun/model_monitoring/stream_processing.py,sha256=bryYO3D0cC10MAQ-liHxUZ79MrL-VFXCb7KNyj6bl-8,34655
234
236
  mlrun/model_monitoring/writer.py,sha256=rGRFzSOkqZWvD3Y6sVk2H1Gepfnkzkp9ce00PsApTLo,8288
235
237
  mlrun/model_monitoring/applications/__init__.py,sha256=BwlmRELlFJf2b2YMyv5kUSHNe8--OyqWhDgRlT8a_8g,779
@@ -253,7 +255,7 @@ mlrun/model_monitoring/db/tsdb/tdengine/tdengine_connection.py,sha256=dtkaHaWKWE
253
255
  mlrun/model_monitoring/db/tsdb/tdengine/tdengine_connector.py,sha256=Vj8eWZ6jxXs9nTlo5Du1jJjYutwSNp4ZtztvKsnrr4M,51333
254
256
  mlrun/model_monitoring/db/tsdb/v3io/__init__.py,sha256=aL3bfmQsUQ-sbvKGdNihFj8gLCK3mSys0qDcXtYOwgc,616
255
257
  mlrun/model_monitoring/db/tsdb/v3io/stream_graph_steps.py,sha256=sNQFj6qyJx5eSBKRC3gyTc1cfh1l2IkRpPtuZwtzCW0,6844
256
- mlrun/model_monitoring/db/tsdb/v3io/v3io_connector.py,sha256=fLzZrtZvJQk22eBT-zUzJfvbrlFwyBB3FbTSgivdLNQ,60242
258
+ mlrun/model_monitoring/db/tsdb/v3io/v3io_connector.py,sha256=3GNMudOpedhu_OId4Gp-r9nj1gtqh_353yn2gWta-BY,61459
257
259
  mlrun/model_monitoring/metrics/__init__.py,sha256=6CsTXAxeLbbf8yfCADTaxmiavqwrLEdYFJ-qc5kgDAY,569
258
260
  mlrun/model_monitoring/metrics/histogram_distance.py,sha256=E9_WIl2vd6qNvoHVHoFcnuQk3ekbFWOdi8aU7sHrfk4,4724
259
261
  mlrun/package/__init__.py,sha256=v7VDyK9kDOOuDvFo4oiGV2fx-vM1KL7fdN9pGLakhUQ,7008
@@ -276,11 +278,11 @@ mlrun/package/utils/type_hint_utils.py,sha256=Ic3A7C9KnbfdLe-nUgzGoefBnsvOJJP9ip
276
278
  mlrun/platforms/__init__.py,sha256=QgtpAt1lpfTKk0mLtesB1P8szK9cpNDPeYzu2qDbPCM,3580
277
279
  mlrun/platforms/iguazio.py,sha256=32_o95Ntx9z3ciowt2NcnX7tAiLBwX3VB0mbTQ-KrIQ,13848
278
280
  mlrun/projects/__init__.py,sha256=hdCOA6_fp8X4qGGGT7Bj7sPbkM1PayWuaVZL0DkpuZw,1240
279
- mlrun/projects/operations.py,sha256=Rc__P5ucNAY2G-lHc2LrnZs15PUbNFt8-NqNNT2Bjpk,20623
281
+ mlrun/projects/operations.py,sha256=dax9HGvs3S7FzZ2Hok1ixFoToIZI2mkUo0EhNUtsHGk,21020
280
282
  mlrun/projects/pipelines.py,sha256=ZOfuIEHOXfuc4qAkuWvbWhCjP6kqpLkv-yBBaY9RXhg,52219
281
- mlrun/projects/project.py,sha256=xbh6qXfU9ckkDSTcd-LyPWxHtHzz6gsqDI63ZZQPuhs,256413
283
+ mlrun/projects/project.py,sha256=Q70Fpxwghuxggdbcizj9pIQ0XsJYMGbmca6arcyrBog,256830
282
284
  mlrun/runtimes/__init__.py,sha256=8cqrYKy1a0_87XG7V_p96untQ4t8RocadM4LVEEN1JM,9029
283
- mlrun/runtimes/base.py,sha256=8AMJcTnm9_LSEKLlmmbEzGSCRAoCh3vAQudKzuIVXhY,38285
285
+ mlrun/runtimes/base.py,sha256=pagMAvF0nEElptqLnBiGx9fpFenEq052B80GaLzR8Y8,38895
284
286
  mlrun/runtimes/daskjob.py,sha256=IN6gKKrmCIjWooj5FgFm-pAb2i7ra1ERRzClfu_rYGI,20102
285
287
  mlrun/runtimes/funcdoc.py,sha256=zRFHrJsV8rhDLJwoUhcfZ7Cs0j-tQ76DxwUqdXV_Wyc,9810
286
288
  mlrun/runtimes/function_reference.py,sha256=fnMKUEieKgy4JyVLhFpDtr6JvKgOaQP8F_K2H3-Pk9U,5030
@@ -288,7 +290,7 @@ mlrun/runtimes/generators.py,sha256=X8NDlCEPveDDPOHtOGcSpbl3pAVM3DP7fuPj5xVhxEY,
288
290
  mlrun/runtimes/kubejob.py,sha256=wadCzmSgjv9OU_Ax8CQNHfXLo0v-ev9ZGHUFGcNc9Qw,8577
289
291
  mlrun/runtimes/local.py,sha256=R72VdrXnFdAhLsKJiWPOcfsi4jS-W5E1FnkT2Xllt8M,22150
290
292
  mlrun/runtimes/mounts.py,sha256=Q6oN1ilVcsFaVM1DAS-mfCD7vGWa7Wa9aEhRrctJPyk,19292
291
- mlrun/runtimes/pod.py,sha256=xqsPWJEHrXNi3AvhmEb6u9T-pyzkkVQ3aH881KeTjvY,58232
293
+ mlrun/runtimes/pod.py,sha256=HtSnhdfaT_rvYwybXjLowl3eOZSrRSyWqW7HYXuUT40,58252
292
294
  mlrun/runtimes/remotesparkjob.py,sha256=BalAea66GleaKeoYTw6ZL1Qr4wf1yRxfgk1-Fkc9Pqg,7864
293
295
  mlrun/runtimes/utils.py,sha256=iRL0U0L56RW26hfjo2n_pRof5XgCAtWSO3YYxPt_2NI,16982
294
296
  mlrun/runtimes/databricks_job/__init__.py,sha256=kXGBqhLN0rlAx0kTXhozGzFsIdSqW0uTSKMmsLgq_is,569
@@ -302,9 +304,9 @@ mlrun/runtimes/nuclio/__init__.py,sha256=osOVMN9paIOuUoOTizmkxMb_OXRP-SlPwXHJSSY
302
304
  mlrun/runtimes/nuclio/api_gateway.py,sha256=vH9ClKVP4Mb24rvA67xPuAvAhX-gAv6vVtjVxyplhdc,26969
303
305
  mlrun/runtimes/nuclio/function.py,sha256=jNlBbtdIoQdd2ZKljqDgKUTHuM4iE_JiO_ANzQyssZE,55168
304
306
  mlrun/runtimes/nuclio/nuclio.py,sha256=sLK8KdGO1LbftlL3HqPZlFOFTAAuxJACZCVl1c0Ha6E,2942
305
- mlrun/runtimes/nuclio/serving.py,sha256=0JEMW1_0Eqx5j-Wpksytm9GhUmoho4L7glIs1qEswMc,35641
307
+ mlrun/runtimes/nuclio/serving.py,sha256=NF0f7a6KV8GIb4QBUKiJa_L_5oqCsG7UHPs8Uo3K_Eo,36330
306
308
  mlrun/runtimes/nuclio/application/__init__.py,sha256=rRs5vasy_G9IyoTpYIjYDafGoL6ifFBKgBtsXn31Atw,614
307
- mlrun/runtimes/nuclio/application/application.py,sha256=TdDUuA3Qd9EOctTmrxt2kOr90b3IjS6u9jyvUu6bwiA,32911
309
+ mlrun/runtimes/nuclio/application/application.py,sha256=5bwGgB_isThhbk9BqAsgJYdd0rKCwcil-LyMPR0dVwQ,33210
308
310
  mlrun/runtimes/nuclio/application/reverse_proxy.go,sha256=lEHH74vr2PridIHp1Jkc_NjkrWb5b6zawRrNxHQhwGU,2913
309
311
  mlrun/runtimes/sparkjob/__init__.py,sha256=GPP_ekItxiU9Ydn3mJa4Obph02Bg6DO-JYs791_MV58,607
310
312
  mlrun/runtimes/sparkjob/spark3job.py,sha256=3dW7RG2T58F2dsUw0TsRvE3SIFcekx3CerLdcaG1f50,41458
@@ -314,7 +316,7 @@ mlrun/serving/remote.py,sha256=Igha2FipK3-6rV_PZ1K464kTbiTu8rhc6SMm-HiEJ6o,18817
314
316
  mlrun/serving/routers.py,sha256=pu5jlSLI4Ml68YP_FMFDhhwPfLcT6lRu5yL5QDgXPHQ,52889
315
317
  mlrun/serving/server.py,sha256=WvAQtkNhAcd2vGuMR04OdxfynMNWvtz6LpKEYPhK3z0,40959
316
318
  mlrun/serving/serving_wrapper.py,sha256=UL9hhWCfMPcTJO_XrkvNaFvck1U1E7oS8trTZyak0cA,835
317
- mlrun/serving/states.py,sha256=TkIKMu1ZVQl2_L2cq53O5ArgmPkrANyaXRidKt_AVT0,138334
319
+ mlrun/serving/states.py,sha256=urq7v4lWwaFP_ZheEqEO1IiX9gkVW3GkuiEbbrBoz90,139012
318
320
  mlrun/serving/system_steps.py,sha256=ZvGkUqiiYOrUlsDnsvzf9u9554mzyFwlKVrybqB7xao,20200
319
321
  mlrun/serving/utils.py,sha256=Zbfqm8TKNcTE8zRBezVBzpvR2WKeKeIRN7otNIaiYEc,4170
320
322
  mlrun/serving/v1_serving.py,sha256=c6J_MtpE-Tqu00-6r4eJOCO6rUasHDal9W2eBIcrl50,11853
@@ -329,7 +331,7 @@ mlrun/utils/async_http.py,sha256=8Olx8TNNeXB07nEGwlqhEgFgnFAD71vBU_bqaA9JW-w,122
329
331
  mlrun/utils/azure_vault.py,sha256=IEFizrDGDbAaoWwDr1WoA88S_EZ0T--vjYtY-i0cvYQ,3450
330
332
  mlrun/utils/clones.py,sha256=qbAGyEbSvlewn3Tw_DpQZP9z6MGzFhSaZfI1CblX8Fg,7515
331
333
  mlrun/utils/condition_evaluator.py,sha256=-nGfRmZzivn01rHTroiGY4rqEv8T1irMyhzxEei-sKc,1897
332
- mlrun/utils/helpers.py,sha256=cN_cVAaJh5T2xE_KgiXTWlXDLM_waIi8PDV3NBj6ioE,83104
334
+ mlrun/utils/helpers.py,sha256=wiFZ8E6Ony4eV4N_pGDPfLtDZNAuyIYL_zv6bEqTSk8,83666
333
335
  mlrun/utils/http.py,sha256=5ZU2VpokaUM_DT3HBSqTm8xjUqTPjZN5fKkSIvKlTl0,8704
334
336
  mlrun/utils/logger.py,sha256=uaCgI_ezzaXf7nJDCy-1Nrjds8vSXqDbzmjmb3IyCQo,14864
335
337
  mlrun/utils/regex.py,sha256=FcRwWD8x9X3HLhCCU2F0AVKTFah784Pr7ZAe3a02jw8,5199
@@ -348,11 +350,11 @@ mlrun/utils/notifications/notification/mail.py,sha256=ZyJ3eqd8simxffQmXzqd3bgbAq
348
350
  mlrun/utils/notifications/notification/slack.py,sha256=wSu_7W0EnGLBNwIgWCYEeTP8j9SPAMPDBnfUcPnVZYA,7299
349
351
  mlrun/utils/notifications/notification/webhook.py,sha256=FM5-LQAKAVJKp37MRzR3SsejalcnpM6r_9Oe7znxZEA,5313
350
352
  mlrun/utils/version/__init__.py,sha256=YnzE6tlf24uOQ8y7Z7l96QLAI6-QEii7-77g8ynmzy0,613
351
- mlrun/utils/version/version.json,sha256=4XxnjcO5M_JMzeQSt05p2f7kyBOjoyz8_C6-mXrlqUs,90
353
+ mlrun/utils/version/version.json,sha256=kPvnUtOTEKIy1wj05q50LE2z2MgUlEGLKrG5080-GnY,90
352
354
  mlrun/utils/version/version.py,sha256=M2hVhRrgkN3SxacZHs3ZqaOsqAA7B6a22ne324IQ1HE,1877
353
- mlrun-1.10.0rc27.dist-info/licenses/LICENSE,sha256=zTiv1CxWNkOk1q8eJS1G_8oD4gWpWLwWxj_Agcsi8Os,11337
354
- mlrun-1.10.0rc27.dist-info/METADATA,sha256=2-9lgsReCFdnK-z8X5FCT2rdbRvTrkUGErsiib9H1To,26017
355
- mlrun-1.10.0rc27.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
356
- mlrun-1.10.0rc27.dist-info/entry_points.txt,sha256=1Owd16eAclD5pfRCoJpYC2ZJSyGNTtUr0nCELMioMmU,46
357
- mlrun-1.10.0rc27.dist-info/top_level.txt,sha256=NObLzw3maSF9wVrgSeYBv-fgnHkAJ1kEkh12DLdd5KM,6
358
- mlrun-1.10.0rc27.dist-info/RECORD,,
355
+ mlrun-1.10.0rc29.dist-info/licenses/LICENSE,sha256=zTiv1CxWNkOk1q8eJS1G_8oD4gWpWLwWxj_Agcsi8Os,11337
356
+ mlrun-1.10.0rc29.dist-info/METADATA,sha256=SPTX_rI17peKzA0BjCzu9p6HAng5ROV94En25oMs2_Y,26017
357
+ mlrun-1.10.0rc29.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
358
+ mlrun-1.10.0rc29.dist-info/entry_points.txt,sha256=1Owd16eAclD5pfRCoJpYC2ZJSyGNTtUr0nCELMioMmU,46
359
+ mlrun-1.10.0rc29.dist-info/top_level.txt,sha256=NObLzw3maSF9wVrgSeYBv-fgnHkAJ1kEkh12DLdd5KM,6
360
+ mlrun-1.10.0rc29.dist-info/RECORD,,