mlrun 1.10.0rc38__py3-none-any.whl → 1.10.0rc39__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.
@@ -359,7 +359,12 @@ class DocumentArtifact(Artifact):
359
359
  self,
360
360
  splitter: Optional["TextSplitter"] = None, # noqa: F821
361
361
  ) -> list["Document"]: # noqa: F821
362
- from langchain.schema import Document
362
+ # Try new langchain 1.0+ import path first
363
+ try:
364
+ from langchain_core.documents import Document
365
+ except ImportError:
366
+ # Fall back to old langchain <1.0 import path
367
+ from langchain.schema import Document
363
368
 
364
369
  """
365
370
  Create LC documents from the artifact
mlrun/common/constants.py CHANGED
@@ -27,6 +27,12 @@ DASK_LABEL_PREFIX = "dask.org/"
27
27
  NUCLIO_LABEL_PREFIX = "nuclio.io/"
28
28
  RESERVED_TAG_NAME_LATEST = "latest"
29
29
 
30
+ # Kubernetes DNS-1123 label name length limit
31
+ K8S_DNS_1123_LABEL_MAX_LENGTH = 63
32
+
33
+
34
+ RESERVED_BATCH_JOB_SUFFIX = "-batch"
35
+
30
36
  JOB_TYPE_WORKFLOW_RUNNER = "workflow-runner"
31
37
  JOB_TYPE_PROJECT_LOADER = "project-loader"
32
38
  JOB_TYPE_RERUN_WORKFLOW_RUNNER = "rerun-workflow-runner"
@@ -486,8 +486,6 @@ class ModelMonitoringLabels:
486
486
 
487
487
  _RESERVED_FUNCTION_NAMES = MonitoringFunctionNames.list() + [SpecialApps.MLRUN_INFRA]
488
488
 
489
- _RESERVED_EVALUATE_FUNCTION_SUFFIX = "-batch"
490
-
491
489
 
492
490
  class ModelEndpointMonitoringMetricType(StrEnum):
493
491
  RESULT = "result"
mlrun/common/secrets.py CHANGED
@@ -11,10 +11,18 @@
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
-
14
+ import re
15
15
  from abc import ABC, abstractmethod
16
16
 
17
17
  import mlrun.common.schemas
18
+ from mlrun.config import config as mlconf
19
+
20
+ _AUTH_SECRET_NAME_TEMPLATE = re.escape(
21
+ mlconf.secret_stores.kubernetes.auth_secret_name.format(
22
+ hashed_access_key="",
23
+ )
24
+ )
25
+ AUTH_SECRET_PATTERN = re.compile(f"^{_AUTH_SECRET_NAME_TEMPLATE}.*")
18
26
 
19
27
 
20
28
  class SecretProviderInterface(ABC):
mlrun/launcher/local.py CHANGED
@@ -243,6 +243,8 @@ class ClientLocalLauncher(launcher.ClientBaseLauncher):
243
243
 
244
244
  # if the handler has module prefix force "local" (vs "handler") runtime
245
245
  kind = "local" if isinstance(handler, str) and "." in handler else ""
246
+
247
+ # Create temporary local function for execution
246
248
  fn = mlrun.new_function(meta.name, command=command, args=args, kind=kind)
247
249
  fn.metadata = meta
248
250
  setattr(fn, "_is_run_local", True)
mlrun/model.py CHANGED
@@ -29,6 +29,7 @@ import pydantic.v1.error_wrappers
29
29
  import mlrun
30
30
  import mlrun.common.constants as mlrun_constants
31
31
  import mlrun.common.schemas.notification
32
+ import mlrun.common.secrets
32
33
  import mlrun.utils.regex
33
34
 
34
35
  from .utils import (
@@ -1616,7 +1617,14 @@ class RunTemplate(ModelObj):
1616
1617
 
1617
1618
  :returns: The RunTemplate object
1618
1619
  """
1619
-
1620
+ if kind == "azure_vault" and isinstance(source, dict):
1621
+ candidate_secret_name = (source.get("k8s_secret") or "").strip()
1622
+ if candidate_secret_name and mlrun.common.secrets.AUTH_SECRET_PATTERN.match(
1623
+ candidate_secret_name
1624
+ ):
1625
+ raise mlrun.errors.MLRunInvalidArgumentError(
1626
+ f"Forbidden secret '{candidate_secret_name}' matches MLRun auth-secret pattern."
1627
+ )
1620
1628
  if kind == "vault" and isinstance(source, list):
1621
1629
  source = {"project": self.metadata.project, "secrets": source}
1622
1630
 
@@ -563,9 +563,10 @@ def _create_model_monitoring_function_base(
563
563
  "An application cannot have the following names: "
564
564
  f"{mm_constants._RESERVED_FUNCTION_NAMES}"
565
565
  )
566
- if name and name.endswith(mm_constants._RESERVED_EVALUATE_FUNCTION_SUFFIX):
566
+ _, has_valid_suffix, suffix = mlrun.utils.helpers.ensure_batch_job_suffix(name)
567
+ if name and not has_valid_suffix:
567
568
  raise mlrun.errors.MLRunValueError(
568
- "Model monitoring application names cannot end with `-batch`"
569
+ f"Model monitoring application names cannot end with `{suffix}`"
569
570
  )
570
571
  if func is None:
571
572
  func = ""
@@ -799,10 +799,13 @@ class ModelMonitoringApplicationBase(MonitoringApplicationToDict, ABC):
799
799
  f"`{mm_constants.APP_NAME_REGEX.pattern}`. "
800
800
  "Please choose another `func_name`."
801
801
  )
802
- if not job_name.endswith(mm_constants._RESERVED_EVALUATE_FUNCTION_SUFFIX):
803
- job_name += mm_constants._RESERVED_EVALUATE_FUNCTION_SUFFIX
802
+ job_name, was_renamed, suffix = mlrun.utils.helpers.ensure_batch_job_suffix(
803
+ job_name
804
+ )
805
+ if was_renamed:
804
806
  mlrun.utils.logger.info(
805
- 'Changing function name - adding `"-batch"` suffix', func_name=job_name
807
+ f'Changing function name - adding `"{suffix}"` suffix',
808
+ func_name=job_name,
806
809
  )
807
810
 
808
811
  return job_name
mlrun/projects/project.py CHANGED
@@ -45,6 +45,7 @@ import mlrun.common.runtimes.constants
45
45
  import mlrun.common.schemas.alert
46
46
  import mlrun.common.schemas.artifact
47
47
  import mlrun.common.schemas.model_monitoring.constants as mm_constants
48
+ import mlrun.common.secrets
48
49
  import mlrun.datastore.datastore_profile
49
50
  import mlrun.db
50
51
  import mlrun.errors
@@ -3418,7 +3419,12 @@ class MlrunProject(ModelObj):
3418
3419
  self._initialized = True
3419
3420
  return self.spec._function_objects
3420
3421
 
3421
- def with_secrets(self, kind, source, prefix=""):
3422
+ def with_secrets(
3423
+ self,
3424
+ kind,
3425
+ source,
3426
+ prefix="",
3427
+ ):
3422
3428
  """register a secrets source (file, env or dict)
3423
3429
 
3424
3430
  read secrets from a source provider to be used in workflows, example::
@@ -3440,12 +3446,21 @@ class MlrunProject(ModelObj):
3440
3446
 
3441
3447
  This will enable access to all secrets in vault registered to the current project.
3442
3448
 
3443
- :param kind: secret type (file, inline, env, vault)
3449
+ :param kind: secret type (file, inline, env, vault, azure_vault)
3444
3450
  :param source: secret data or link (see example)
3445
3451
  :param prefix: add a prefix to the keys in this source
3446
3452
 
3447
3453
  :returns: project object
3448
3454
  """
3455
+ # Block using mlrun-auth-secrets.* via azure_vault's k8s_secret param (client-side only)
3456
+ if kind == "azure_vault" and isinstance(source, dict):
3457
+ candidate_secret_name = (source.get("k8s_secret") or "").strip()
3458
+ if candidate_secret_name and mlrun.common.secrets.AUTH_SECRET_PATTERN.match(
3459
+ candidate_secret_name
3460
+ ):
3461
+ raise mlrun.errors.MLRunInvalidArgumentError(
3462
+ f"Forbidden secret '{candidate_secret_name}' matches MLRun auth-secret pattern."
3463
+ )
3449
3464
 
3450
3465
  if kind == "vault" and isinstance(source, list):
3451
3466
  source = {"project": self.metadata.name, "secrets": source}
mlrun/run.py CHANGED
@@ -555,6 +555,7 @@ def new_function(
555
555
 
556
556
  # make sure function name is valid
557
557
  name = mlrun.utils.helpers.normalize_name(name)
558
+ mlrun.utils.helpers.validate_function_name(name)
558
559
 
559
560
  runner.metadata.name = name
560
561
  runner.metadata.project = (
@@ -594,6 +595,7 @@ def new_function(
594
595
  )
595
596
 
596
597
  runner.prepare_image_for_deploy()
598
+
597
599
  return runner
598
600
 
599
601
 
@@ -798,6 +800,9 @@ def code_to_function(
798
800
  kind=sub_kind,
799
801
  ignored_tags=ignored_tags,
800
802
  )
803
+
804
+ mlrun.utils.helpers.validate_function_name(name)
805
+
801
806
  spec["spec"]["env"].append(
802
807
  {
803
808
  "name": "MLRUN_HTTPDB__NUCLIO__EXPLICIT_ACK",
@@ -850,6 +855,7 @@ def code_to_function(
850
855
  runtime.spec.build.code_origin = code_origin
851
856
  runtime.spec.build.origin_filename = filename or (name + ".ipynb")
852
857
  update_common(runtime, spec)
858
+
853
859
  return runtime
854
860
 
855
861
  if kind is None or kind in ["", "Function"]:
@@ -863,6 +869,7 @@ def code_to_function(
863
869
 
864
870
  if not name:
865
871
  raise ValueError("name must be specified")
872
+
866
873
  h = get_in(spec, "spec.handler", "").split(":")
867
874
  runtime.handler = h[0] if len(h) <= 1 else h[1]
868
875
  runtime.metadata = get_in(spec, "spec.metadata")
@@ -221,6 +221,24 @@ class RuntimeKinds:
221
221
  return True
222
222
  return False
223
223
 
224
+ @staticmethod
225
+ def requires_k8s_name_validation(kind: str) -> bool:
226
+ """
227
+ Returns True if the runtime kind creates Kubernetes resources that use the function name.
228
+
229
+ Function names for k8s-deployed runtimes must conform to DNS-1123 label requirements:
230
+ - Lowercase alphanumeric characters or '-'
231
+ - Start and end with an alphanumeric character
232
+ - Maximum 63 characters
233
+
234
+ Local runtimes (local, handler) run on the local machine and don't create k8s resources,
235
+ so they don't require k8s naming validation.
236
+
237
+ :param kind: Runtime kind string (job, spark, serving, local, etc.)
238
+ :return: True if function name needs k8s DNS-1123 validation, False otherwise
239
+ """
240
+ return not RuntimeKinds.is_local_runtime(kind)
241
+
224
242
  @staticmethod
225
243
  def requires_absolute_artifacts_path(kind):
226
244
  """
mlrun/runtimes/base.py CHANGED
@@ -393,6 +393,9 @@ class BaseRuntime(ModelObj):
393
393
  FutureWarning,
394
394
  )
395
395
  output_path = output_path or out_path or artifact_path
396
+
397
+ mlrun.utils.helpers.validate_function_name(self.metadata.name)
398
+
396
399
  launcher = mlrun.launcher.factory.LauncherFactory().create_launcher(
397
400
  self._is_remote, local=local, **launcher_kwargs
398
401
  )
mlrun/runtimes/local.py CHANGED
@@ -29,12 +29,12 @@ from os import environ, remove
29
29
  from pathlib import Path
30
30
  from subprocess import PIPE, Popen
31
31
  from sys import executable
32
+ from typing import Optional
32
33
 
33
34
  from nuclio import Event
34
35
 
35
36
  import mlrun
36
37
  import mlrun.common.constants as mlrun_constants
37
- import mlrun.common.runtimes.constants
38
38
  from mlrun.lists import RunList
39
39
 
40
40
  from ..errors import err_to_str
@@ -201,9 +201,12 @@ class LocalRuntime(BaseRuntime, ParallelRunner):
201
201
  kind = "local"
202
202
  _is_remote = False
203
203
 
204
- def to_job(self, image=""):
204
+ def to_job(self, image="", func_name: Optional[str] = None):
205
205
  struct = self.to_dict()
206
206
  obj = KubejobRuntime.from_dict(struct)
207
+ obj.kind = "job" # Ensure kind is set to 'job' for KubejobRuntime
208
+ if func_name:
209
+ obj.metadata.name = func_name
207
210
  if image:
208
211
  obj.spec.image = image
209
212
  return obj
mlrun/runtimes/mounts.py CHANGED
@@ -17,6 +17,8 @@ import typing
17
17
  import warnings
18
18
  from collections import namedtuple
19
19
 
20
+ import mlrun.common.secrets
21
+ import mlrun.errors
20
22
  from mlrun.config import config
21
23
  from mlrun.config import config as mlconf
22
24
  from mlrun.errors import MLRunInvalidArgumentError
@@ -412,6 +414,13 @@ def mount_secret(
412
414
  the specified paths, and unlisted keys will not be
413
415
  present."""
414
416
 
417
+ if secret_name and mlrun.common.secrets.AUTH_SECRET_PATTERN.match(
418
+ secret_name.strip()
419
+ ):
420
+ raise mlrun.errors.MLRunInvalidArgumentError(
421
+ f"Forbidden secret '{secret_name}' matches MLRun auth-secret pattern."
422
+ )
423
+
415
424
  def _mount_secret(runtime: "KubeResource"):
416
425
  # Define the secret volume source
417
426
  secret_volume_source = {
@@ -400,6 +400,8 @@ class ApplicationRuntime(RemoteRuntime):
400
400
 
401
401
  :return: The default API gateway URL if created or True if the function is ready (deployed)
402
402
  """
403
+ mlrun.utils.helpers.validate_function_name(self.metadata.name)
404
+
403
405
  if (self.requires_build() and not self.spec.image) or force_build:
404
406
  self._fill_credentials()
405
407
  self._build_application_image(
@@ -655,6 +655,8 @@ class RemoteRuntime(KubeResource):
655
655
  if tag:
656
656
  self.metadata.tag = tag
657
657
 
658
+ mlrun.utils.helpers.validate_function_name(self.metadata.name)
659
+
658
660
  # Attempt auto-mounting, before sending to remote build
659
661
  self.try_auto_mount_based_on_config()
660
662
  self._fill_credentials()
@@ -44,6 +44,7 @@ from mlrun.serving.states import (
44
44
  )
45
45
  from mlrun.utils import get_caller_globals, logger, set_paths
46
46
 
47
+ from ...common.secrets import AUTH_SECRET_PATTERN
47
48
  from .. import KubejobRuntime
48
49
  from ..pod import KubeResourceSpec
49
50
  from .function import NuclioSpec, RemoteRuntime, min_nuclio_versions
@@ -635,7 +636,14 @@ class ServingRuntime(RemoteRuntime):
635
636
 
636
637
  :returns: The Runtime (function) object
637
638
  """
638
-
639
+ if kind == "azure_vault" and isinstance(source, dict):
640
+ candidate_secret_name = (source.get("k8s_secret") or "").strip()
641
+ if candidate_secret_name and AUTH_SECRET_PATTERN.match(
642
+ candidate_secret_name
643
+ ):
644
+ raise mlrun.errors.MLRunInvalidArgumentError(
645
+ f"Forbidden secret '{candidate_secret_name}' matches MLRun auth-secret pattern."
646
+ )
639
647
  if kind == "vault" and isinstance(source, list):
640
648
  source = {"project": self.metadata.project, "secrets": source}
641
649
 
@@ -659,6 +667,9 @@ class ServingRuntime(RemoteRuntime):
659
667
  :param builder_env: env vars dict for source archive config/credentials e.g. builder_env={"GIT_TOKEN": token}
660
668
  :param force_build: set True for force building the image
661
669
  """
670
+ # Validate function name before deploying to k8s
671
+ mlrun.utils.helpers.validate_function_name(self.metadata.name)
672
+
662
673
  load_mode = self.spec.load_mode
663
674
  if load_mode and load_mode not in ["sync", "async"]:
664
675
  raise ValueError(f"illegal model loading mode {load_mode}")
@@ -855,8 +866,20 @@ class ServingRuntime(RemoteRuntime):
855
866
  )
856
867
  self._mock_server = self.to_mock_server()
857
868
 
858
- def to_job(self) -> KubejobRuntime:
859
- """Convert this ServingRuntime to a KubejobRuntime, so that the graph can be run as a standalone job."""
869
+ def to_job(self, func_name: Optional[str] = None) -> KubejobRuntime:
870
+ """Convert this ServingRuntime to a KubejobRuntime, so that the graph can be run as a standalone job.
871
+
872
+ Args:
873
+ func_name: Optional custom name for the job function. If not provided, automatically
874
+ appends '-batch' suffix to the serving function name to prevent database collision.
875
+
876
+ Returns:
877
+ KubejobRuntime configured to execute the serving graph as a batch job.
878
+
879
+ Note:
880
+ The job will have a different name than the serving function to prevent database collision.
881
+ The original serving function remains unchanged and can still be invoked after running the job.
882
+ """
860
883
  if self.spec.function_refs:
861
884
  raise mlrun.errors.MLRunInvalidArgumentError(
862
885
  f"Cannot convert function '{self.metadata.name}' to a job because it has child functions"
@@ -890,8 +913,50 @@ class ServingRuntime(RemoteRuntime):
890
913
  parameters=self.spec.parameters,
891
914
  graph=self.spec.graph,
892
915
  )
916
+
917
+ job_metadata = deepcopy(self.metadata)
918
+ original_name = job_metadata.name
919
+
920
+ if func_name:
921
+ # User provided explicit job name
922
+ job_metadata.name = func_name
923
+ logger.debug(
924
+ "Creating job from serving function with custom name",
925
+ new_name=func_name,
926
+ )
927
+ else:
928
+ job_metadata.name, was_renamed, suffix = (
929
+ mlrun.utils.helpers.ensure_batch_job_suffix(job_metadata.name)
930
+ )
931
+
932
+ # Check if the resulting name exceeds Kubernetes length limit
933
+ if (
934
+ len(job_metadata.name)
935
+ > mlrun.common.constants.K8S_DNS_1123_LABEL_MAX_LENGTH
936
+ ):
937
+ raise mlrun.errors.MLRunInvalidArgumentError(
938
+ f"Cannot convert serving function '{original_name}' to batch job: "
939
+ f"the resulting name '{job_metadata.name}' ({len(job_metadata.name)} characters) "
940
+ f"exceeds Kubernetes limit of {mlrun.common.constants.K8S_DNS_1123_LABEL_MAX_LENGTH} characters. "
941
+ f"Please provide a custom name via the func_name parameter, "
942
+ f"with at most {mlrun.common.constants.K8S_DNS_1123_LABEL_MAX_LENGTH} characters."
943
+ )
944
+
945
+ if was_renamed:
946
+ logger.info(
947
+ "Creating job from serving function (auto-appended suffix to prevent collision)",
948
+ new_name=job_metadata.name,
949
+ suffix=suffix,
950
+ )
951
+ else:
952
+ logger.debug(
953
+ "Creating job from serving function (name already has suffix)",
954
+ name=original_name,
955
+ suffix=suffix,
956
+ )
957
+
893
958
  job = KubejobRuntime(
894
959
  spec=spec,
895
- metadata=self.metadata,
960
+ metadata=job_metadata,
896
961
  )
897
962
  return job
mlrun/runtimes/pod.py CHANGED
@@ -20,6 +20,7 @@ import typing
20
20
  import warnings
21
21
  from collections.abc import Iterable
22
22
  from enum import Enum
23
+ from typing import Optional
23
24
 
24
25
  import dotenv
25
26
  import kubernetes.client as k8s_client
@@ -34,6 +35,7 @@ from mlrun.common.schemas import (
34
35
  SecurityContextEnrichmentModes,
35
36
  )
36
37
 
38
+ from ..common.secrets import AUTH_SECRET_PATTERN
37
39
  from ..config import config as mlconf
38
40
  from ..k8s_utils import (
39
41
  generate_preemptible_nodes_affinity_terms,
@@ -708,19 +710,44 @@ class KubeResource(BaseRuntime):
708
710
  def spec(self, spec):
709
711
  self._spec = self._verify_dict(spec, "spec", KubeResourceSpec)
710
712
 
711
- def set_env_from_secret(self, name, secret=None, secret_key=None):
712
- """set pod environment var from secret"""
713
+ def set_env_from_secret(
714
+ self,
715
+ name: str,
716
+ secret: Optional[str] = None,
717
+ secret_key: Optional[str] = None,
718
+ ):
719
+ """Set env var from secret; block auth-secret usage on client side."""
720
+ self._validate_no_auth_secret(
721
+ secret_name=secret,
722
+ )
713
723
  secret_key = secret_key or name
714
724
  value_from = k8s_client.V1EnvVarSource(
715
- secret_key_ref=k8s_client.V1SecretKeySelector(name=secret, key=secret_key)
725
+ secret_key_ref=k8s_client.V1SecretKeySelector(
726
+ name=secret,
727
+ key=secret_key,
728
+ )
729
+ )
730
+ return self._set_env(
731
+ name=name,
732
+ value_from=value_from,
716
733
  )
717
- return self._set_env(name, value_from=value_from)
718
734
 
719
- def set_env(self, name, value=None, value_from=None):
720
- """set pod environment var from value"""
721
- if value is not None:
722
- return self._set_env(name, value=str(value))
723
- return self._set_env(name, value_from=value_from)
735
+ def set_env(
736
+ self,
737
+ name: str,
738
+ value: Optional[str] = None,
739
+ value_from: Optional[typing.Any] = None,
740
+ ):
741
+ """Set env var; block auth-secret usage when coming from a secret."""
742
+ if value_from is not None:
743
+ secret_name = self._extract_secret_name_from_value_from(
744
+ value_from=value_from,
745
+ )
746
+ self._validate_no_auth_secret(
747
+ secret_name=secret_name,
748
+ )
749
+ return self._set_env(name, value_from=value_from)
750
+ return self._set_env(name, value=str(value) if value is not None else None)
724
751
 
725
752
  def with_annotations(self, annotations: dict):
726
753
  """set a key/value annotations in the metadata of the pod"""
@@ -1366,6 +1393,37 @@ class KubeResource(BaseRuntime):
1366
1393
 
1367
1394
  return self.status.state
1368
1395
 
1396
+ @staticmethod
1397
+ def _validate_no_auth_secret(
1398
+ secret_name: Optional[str],
1399
+ ):
1400
+ """Raise if secret name matches MLRun auth-secret pattern."""
1401
+ if secret_name and AUTH_SECRET_PATTERN.match(secret_name):
1402
+ raise mlrun.errors.MLRunInvalidArgumentError(
1403
+ f"Forbidden secret '{secret_name}' matches MLRun auth-secret pattern."
1404
+ )
1405
+
1406
+ @staticmethod
1407
+ def _extract_secret_name_from_value_from(
1408
+ value_from: typing.Any,
1409
+ ) -> Optional[str]:
1410
+ """Extract secret name from a V1EnvVarSource or dict representation."""
1411
+ if isinstance(value_from, k8s_client.V1EnvVarSource):
1412
+ if value_from.secret_key_ref:
1413
+ return value_from.secret_key_ref.name
1414
+ elif isinstance(value_from, dict):
1415
+ value_from = (
1416
+ value_from.get("valueFrom")
1417
+ or value_from.get("value_from")
1418
+ or value_from
1419
+ )
1420
+ secret_key_ref = (value_from or {}).get("secretKeyRef") or (
1421
+ value_from or {}
1422
+ ).get("secret_key_ref")
1423
+ if isinstance(secret_key_ref, dict):
1424
+ return secret_key_ref.get("name")
1425
+ return None
1426
+
1369
1427
 
1370
1428
  def _resolve_if_type_sanitized(attribute_name, attribute):
1371
1429
  attribute_config = sanitized_attributes[attribute_name]
mlrun/utils/helpers.py CHANGED
@@ -253,6 +253,40 @@ def verify_field_regex(
253
253
  return False
254
254
 
255
255
 
256
+ def validate_function_name(name: str) -> None:
257
+ """
258
+ Validate that a function name conforms to Kubernetes DNS-1123 label requirements.
259
+
260
+ Function names for Kubernetes resources must:
261
+ - Be lowercase alphanumeric characters or '-'
262
+ - Start and end with an alphanumeric character
263
+ - Be at most 63 characters long
264
+
265
+ This validation should be called AFTER normalize_name() has been applied.
266
+
267
+ Refer to https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#dns-label-names
268
+
269
+ :param name: The function name to validate (after normalization)
270
+ :raises MLRunInvalidArgumentError: If the function name is invalid for Kubernetes
271
+ """
272
+ if not name:
273
+ return
274
+
275
+ verify_field_regex(
276
+ "function.metadata.name",
277
+ name,
278
+ mlrun.utils.regex.dns_1123_label,
279
+ raise_on_failure=True,
280
+ log_message=(
281
+ f"Function name '{name}' is invalid. "
282
+ "Kubernetes function names must be DNS-1123 labels: "
283
+ "lowercase alphanumeric characters or '-', "
284
+ "starting and ending with an alphanumeric character, "
285
+ "and at most 63 characters long."
286
+ ),
287
+ )
288
+
289
+
256
290
  def validate_builder_source(
257
291
  source: str, pull_at_runtime: bool = False, workdir: Optional[str] = None
258
292
  ):
@@ -476,6 +510,40 @@ def normalize_name(name: str):
476
510
  return name.lower()
477
511
 
478
512
 
513
+ def ensure_batch_job_suffix(
514
+ function_name: typing.Optional[str],
515
+ ) -> tuple[typing.Optional[str], bool, str]:
516
+ """
517
+ Ensure that a function name has the batch job suffix appended to prevent database collision.
518
+
519
+ This helper is used by to_job() methods in runtimes that convert online functions (serving, local)
520
+ to batch processing jobs. The suffix prevents the job from overwriting the original function in
521
+ the database when both are stored with the same (project, name) key.
522
+
523
+ :param function_name: The original function name (can be None or empty string)
524
+
525
+ :return: A tuple of (modified_name, was_renamed, suffix) where:
526
+ - modified_name: The function name with the batch suffix (if not already present),
527
+ or empty string if input was empty
528
+ - was_renamed: True if the suffix was added, False if it was already present or if name was empty/None
529
+ - suffix: The suffix value that was used (or would have been used)
530
+
531
+ """
532
+ suffix = mlrun_constants.RESERVED_BATCH_JOB_SUFFIX
533
+
534
+ # Handle None or empty string
535
+ if not function_name:
536
+ return function_name, False, suffix
537
+
538
+ if not function_name.endswith(suffix):
539
+ return (
540
+ f"{function_name}{suffix}",
541
+ True,
542
+ suffix,
543
+ )
544
+ return function_name, False, suffix
545
+
546
+
479
547
  class LogBatchWriter:
480
548
  def __init__(self, func, batch=16, maxtime=5):
481
549
  self.batch = batch
@@ -970,8 +1038,15 @@ def enrich_image_url(
970
1038
  else:
971
1039
  image_url = "mlrun/mlrun"
972
1040
 
973
- if is_mlrun_image and tag and ":" not in image_url:
974
- image_url = f"{image_url}:{tag}"
1041
+ if is_mlrun_image and tag:
1042
+ if ":" not in image_url:
1043
+ image_url = f"{image_url}:{tag}"
1044
+ elif enrich_kfp_python_version:
1045
+ # For mlrun-kfp >= 1.10.0-rc0, append python suffix to existing tag
1046
+ python_suffix = resolve_image_tag_suffix(
1047
+ mlrun_version, client_python_version
1048
+ )
1049
+ image_url = f"{image_url}{python_suffix}" if python_suffix else image_url
975
1050
 
976
1051
  registry = (
977
1052
  config.images_registry if is_mlrun_image else config.vendor_images_registry
@@ -1,4 +1,4 @@
1
1
  {
2
- "git_commit": "cc5c5639d721f37d6a1d0d0b7cf9f853f38e4707",
3
- "version": "1.10.0-rc38"
2
+ "git_commit": "a8c2a4e78b2c7ad2c929bb0edce5d9db47c2baea",
3
+ "version": "1.10.0-rc39"
4
4
  }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mlrun
3
- Version: 1.10.0rc38
3
+ Version: 1.10.0rc39
4
4
  Summary: Tracking and config of machine learning runs
5
5
  Home-page: https://github.com/mlrun/mlrun
6
6
  Author: Yaron Haviv
@@ -113,7 +113,7 @@ Requires-Dist: apscheduler<4,>=3.11; extra == "api"
113
113
  Requires-Dist: objgraph~=3.6; extra == "api"
114
114
  Requires-Dist: igz-mgmt~=0.4.1; extra == "api"
115
115
  Requires-Dist: humanfriendly~=10.0; extra == "api"
116
- Requires-Dist: fastapi~=0.116.0; extra == "api"
116
+ Requires-Dist: fastapi~=0.120.0; extra == "api"
117
117
  Requires-Dist: sqlalchemy~=2.0; extra == "api"
118
118
  Requires-Dist: sqlalchemy-utils~=0.41.2; extra == "api"
119
119
  Requires-Dist: pymysql~=1.1; extra == "api"
@@ -203,7 +203,7 @@ Requires-Dist: dask~=2023.12.1; python_version < "3.11" and extra == "complete-a
203
203
  Requires-Dist: databricks-sdk~=0.20.0; extra == "complete-api"
204
204
  Requires-Dist: distributed==2024.8; python_version >= "3.11" and extra == "complete-api"
205
205
  Requires-Dist: distributed~=2023.12.1; python_version < "3.11" and extra == "complete-api"
206
- Requires-Dist: fastapi~=0.116.0; extra == "complete-api"
206
+ Requires-Dist: fastapi~=0.120.0; extra == "complete-api"
207
207
  Requires-Dist: gcsfs<=2025.7.0,>=2025.5.1; extra == "complete-api"
208
208
  Requires-Dist: google-cloud-bigquery-storage~=2.17; extra == "complete-api"
209
209
  Requires-Dist: google-cloud-bigquery[bqstorage,pandas]==3.14.1; extra == "complete-api"
@@ -6,25 +6,25 @@ mlrun/execution.py,sha256=Ozu8SjO-nQ6l5vHwqrTQjmP6koMpUqNQpp6qn6jvhVE,58802
6
6
  mlrun/features.py,sha256=jMEXo6NB36A6iaxNEJWzdtYwUmglYD90OIKTIEeWhE8,15841
7
7
  mlrun/k8s_utils.py,sha256=zIacVyvsXrXVO-DdxAoGQOGEDWOGJEFJzYPhPVnn3z8,24548
8
8
  mlrun/lists.py,sha256=OlaV2QIFUzmenad9kxNJ3k4whlDyxI3zFbGwr6vpC5Y,8561
9
- mlrun/model.py,sha256=JxYWYfMvRMloVEsxfghjH8gq5vsVCVk-OJmHGhbPJuU,88954
9
+ mlrun/model.py,sha256=KnLnJjGa7SsJO1LSTvoMQbmp3JN4LExA7yJqCXvgAY4,89444
10
10
  mlrun/render.py,sha256=5DlhD6JtzHgmj5RVlpaYiHGhX84Q7qdi4RCEUj2UMgw,13195
11
- mlrun/run.py,sha256=DRlXYf9C4ZJeGeXdbQxgeCKhoV2892u0v0yIfsyDSkA,49730
11
+ mlrun/run.py,sha256=BA0CPJqtcM3c-hMmnGl6AccRMyIejJxvCcrSXTwcRwU,49841
12
12
  mlrun/secrets.py,sha256=VFETVDJFZ0AGDivYjhYscO_YHnzeBnAebxlio7Svkq0,9633
13
13
  mlrun/alerts/__init__.py,sha256=0gtG1BG0DXxFrXegIkjbM1XEN4sP9ODo0ucXrNld1hU,601
14
14
  mlrun/alerts/alert.py,sha256=QQFZGydQbx9RvAaSiaH-ALQZVcDKQX5lgizqj_rXW2k,15948
15
15
  mlrun/artifacts/__init__.py,sha256=ZrEUNto7tGdnBGteCp9zOyO8b78z7O3xgcpzUt9UHE4,1240
16
16
  mlrun/artifacts/base.py,sha256=6x_2KPMNOciiNNUsiKgJ-b6ejxAHm_Ro22xODLoTc44,28559
17
17
  mlrun/artifacts/dataset.py,sha256=bhb5Kfbs8P28yjnpN76th5lLEUl5nAqD4VqVzHEVPrM,16421
18
- mlrun/artifacts/document.py,sha256=p5HsWdmIIJ0NahS7y3EEQN2tfHtUrUmUG-8BEEyi_Jc,17373
18
+ mlrun/artifacts/document.py,sha256=VYoWcFUB45B-z_nhbedFCpiorZsDBxkTNRLWjYvri0Q,17585
19
19
  mlrun/artifacts/helpers.py,sha256=ejTEC9vkI2w5FHn5Gopw3VEIxuni0bazWUnR6BBWZfU,1662
20
20
  mlrun/artifacts/llm_prompt.py,sha256=pshXzYXPDBAe6C0vecn9MyRNyPdxrah3c80oZUKkYWA,9840
21
21
  mlrun/artifacts/manager.py,sha256=_cDNCS7wwmFIsucJ2uOgHxZQECmIGb8Wye64b6oLgKU,16642
22
22
  mlrun/artifacts/model.py,sha256=9yU9NZlxxY_ifSyXOgMnPi_RMDmawY9A-rLi-_VJs4c,25662
23
23
  mlrun/artifacts/plots.py,sha256=wmaxVXiAPSCyn3M7pIlcBu9pP3O8lrq0Ewx6iHRDF9s,4238
24
24
  mlrun/common/__init__.py,sha256=kXGBqhLN0rlAx0kTXhozGzFsIdSqW0uTSKMmsLgq_is,569
25
- mlrun/common/constants.py,sha256=H2Qh65elADGD1vgMzI6gYT5RAA2q8uFL6UByIwYBV34,4173
25
+ mlrun/common/constants.py,sha256=BbKFJN6EoFSOmUmvos20ZAty8hWtwG0quTrfbLzrWO4,4294
26
26
  mlrun/common/helpers.py,sha256=DIdqs_eN3gO5bZ8iFobIvx8cEiOxYxhFIyut6-O69T0,1385
27
- mlrun/common/secrets.py,sha256=8g9xtIw-9DGcwiZRT62a5ozSQM-aYo8yK5Ghey9WM0g,5179
27
+ mlrun/common/secrets.py,sha256=SCNLDIzC9-4r7CcJuJJxSAA89dUDcKD7g3yvSKIhqN4,5439
28
28
  mlrun/common/types.py,sha256=1gxThbmC0Vd0U1ffIkEwz4T4S7JOgHt70rvw8TCO21c,1073
29
29
  mlrun/common/db/__init__.py,sha256=kXGBqhLN0rlAx0kTXhozGzFsIdSqW0uTSKMmsLgq_is,569
30
30
  mlrun/common/db/dialects.py,sha256=QN9bx7CTo32IIdJ2J3ZrsX8IUdp_BPxBtl0LyjMEC9g,868
@@ -74,7 +74,7 @@ mlrun/common/schemas/serving.py,sha256=4ek9JZDagkdeXyfkX6P6xp4deUNSf_kqXUaXcKSuv
74
74
  mlrun/common/schemas/tag.py,sha256=1wqEiAujsElojWb3qmuyfcaLFjXSNAAQdafkDx7fkn0,891
75
75
  mlrun/common/schemas/workflow.py,sha256=Y-FHJnxs5c86yetuOAPdEJPkne__tLPCxjSXSb4lrjo,2541
76
76
  mlrun/common/schemas/model_monitoring/__init__.py,sha256=ndeGXCJTE_GvMSb1FfQ5fXvhs0I8nO_yWy1UBSZIifY,1956
77
- mlrun/common/schemas/model_monitoring/constants.py,sha256=uQ3ataL-tAcwGY1GQLEvu05gGgMb2kBr6YRzjJS6yYs,13953
77
+ mlrun/common/schemas/model_monitoring/constants.py,sha256=GimtHVQmMkCh4e5Fy0YLeeMWP8D5uCvVcWdpM63SPJg,13906
78
78
  mlrun/common/schemas/model_monitoring/functions.py,sha256=Ej8ChjmMZq1HP32THNABoktQHN1mdlkSqKbofxu10i4,2536
79
79
  mlrun/common/schemas/model_monitoring/grafana.py,sha256=THQlLfPBevBksta8p5OaIsBaJtsNSXexLvHrDxOaVns,2095
80
80
  mlrun/common/schemas/model_monitoring/model_endpoints.py,sha256=aevkfKWRbRj2cxabeUrVka49lJ2SRDA7I8rD-Fihr2Q,13648
@@ -225,10 +225,10 @@ mlrun/launcher/__init__.py,sha256=JL8qkT1lLr1YvW6iP0hmwDTaSR2RfrMDx0-1gWRhTOE,57
225
225
  mlrun/launcher/base.py,sha256=IgBE-ZS1ZiGzucg5SElGtO4qOB0cqYQfGtZTcRc2S3Y,17378
226
226
  mlrun/launcher/client.py,sha256=cl40ZdF2fU1QbUKdl4Xnucb1u2h-8_dn095qIUyxbuM,6402
227
227
  mlrun/launcher/factory.py,sha256=RW7mfzEFi8fR0M-4W1JQg1iq3_muUU6OTqT_3l4Ubrk,2338
228
- mlrun/launcher/local.py,sha256=3gv-IQYoIChSmRaZ0vLUh0Tu26oLMCx9GbBYh4fWygQ,12161
228
+ mlrun/launcher/local.py,sha256=sBpVxNoVLiPGDam_PFLJUb0vvKAWjMgqNY0A_RiR0hQ,12218
229
229
  mlrun/launcher/remote.py,sha256=zFXE52Cq_7EkC8lfNKT0ceIbye0CfFiundF7O1YU4Xw,7810
230
230
  mlrun/model_monitoring/__init__.py,sha256=qDQnncjya9XPTlfvGyfWsZWiXc-glGZrrNja-5QmCZk,782
231
- mlrun/model_monitoring/api.py,sha256=g9st30YgcApT42ZU-aSlnLiLdDwATkujXg_5UrAFt1M,27738
231
+ mlrun/model_monitoring/api.py,sha256=yxADX4V7rNPgh2Zh95hIDtWuhkinItay-SfMwm9bqGY,27783
232
232
  mlrun/model_monitoring/controller.py,sha256=2XOkOZRB03K9ph6TH-ICspHga-GQOURL0C8-0GTHaTY,43961
233
233
  mlrun/model_monitoring/features_drift_table.py,sha256=c6GpKtpOJbuT1u5uMWDL_S-6N4YPOmlktWMqPme3KFY,25308
234
234
  mlrun/model_monitoring/helpers.py,sha256=50oFqgIc5xFHYPIVgq3M-Gbr7epqAI5NgHmvOeMy52U,24667
@@ -236,7 +236,7 @@ mlrun/model_monitoring/stream_processing.py,sha256=bryYO3D0cC10MAQ-liHxUZ79MrL-V
236
236
  mlrun/model_monitoring/writer.py,sha256=l2D_5Ms5Wq5jfyQRVJbGBBRTMLjMmIAxwPeHWmrc9Kg,16382
237
237
  mlrun/model_monitoring/applications/__init__.py,sha256=BwlmRELlFJf2b2YMyv5kUSHNe8--OyqWhDgRlT8a_8g,779
238
238
  mlrun/model_monitoring/applications/_application_steps.py,sha256=t9LDIqQUGE10cyjyhlg0QqN1yVx0apD1HpERYLJfm8U,7409
239
- mlrun/model_monitoring/applications/base.py,sha256=f3WWMoXinsqzWtYebQnsMCGhi7M50E8LdeYmQl5QXjg,51339
239
+ mlrun/model_monitoring/applications/base.py,sha256=Bd8bD2kJlS4ZaGAkj88o4iwRjXIE76gYdhXqAjXfUCk,51344
240
240
  mlrun/model_monitoring/applications/context.py,sha256=3W3AW4oyJgx_nW_5mDsV59Iy5D3frkfYMQSc6DgBc4c,17004
241
241
  mlrun/model_monitoring/applications/histogram_data_drift.py,sha256=2qgfFmrpHf-x0_EaHD-0T28piwSQzw-HH71aV1GwbZs,15389
242
242
  mlrun/model_monitoring/applications/results.py,sha256=LfBQOmkpKGvVGNrcj5QiXsRIG2IRgcv_Xqe4QJBmauk,5699
@@ -281,17 +281,17 @@ mlrun/platforms/iguazio.py,sha256=32_o95Ntx9z3ciowt2NcnX7tAiLBwX3VB0mbTQ-KrIQ,13
281
281
  mlrun/projects/__init__.py,sha256=hdCOA6_fp8X4qGGGT7Bj7sPbkM1PayWuaVZL0DkpuZw,1240
282
282
  mlrun/projects/operations.py,sha256=Oo7h0TMztI_RVmj0rQxNS1igS_c94HpQZwMIFjiWt0E,21038
283
283
  mlrun/projects/pipelines.py,sha256=ZOfuIEHOXfuc4qAkuWvbWhCjP6kqpLkv-yBBaY9RXhg,52219
284
- mlrun/projects/project.py,sha256=jSJ65upJ6zYRHly6aOQxBR6414Ypueg2iXE6XBjc-uQ,257695
285
- mlrun/runtimes/__init__.py,sha256=8cqrYKy1a0_87XG7V_p96untQ4t8RocadM4LVEEN1JM,9029
286
- mlrun/runtimes/base.py,sha256=txynS-hiNLR97PBd49mc5q9ZX3gMf3VdJ2rJ-fz5bZU,38913
284
+ mlrun/projects/project.py,sha256=alWbBKoOl_fej8IyFB397r7JYPZkSlRXrSsmVaaQw8U,258335
285
+ mlrun/runtimes/__init__.py,sha256=NSIk1xlUduSY3ZZ2tLmXegw1Z1im5_KjtbmsL874Z6s,9829
286
+ mlrun/runtimes/base.py,sha256=CpIaml8nJbbPt8PQXDzy_AXbJ0LObRWk1lprRBDRYdI,38986
287
287
  mlrun/runtimes/daskjob.py,sha256=IN6gKKrmCIjWooj5FgFm-pAb2i7ra1ERRzClfu_rYGI,20102
288
288
  mlrun/runtimes/funcdoc.py,sha256=zRFHrJsV8rhDLJwoUhcfZ7Cs0j-tQ76DxwUqdXV_Wyc,9810
289
289
  mlrun/runtimes/function_reference.py,sha256=fnMKUEieKgy4JyVLhFpDtr6JvKgOaQP8F_K2H3-Pk9U,5030
290
290
  mlrun/runtimes/generators.py,sha256=X8NDlCEPveDDPOHtOGcSpbl3pAVM3DP7fuPj5xVhxEY,7290
291
291
  mlrun/runtimes/kubejob.py,sha256=wadCzmSgjv9OU_Ax8CQNHfXLo0v-ev9ZGHUFGcNc9Qw,8577
292
- mlrun/runtimes/local.py,sha256=R72VdrXnFdAhLsKJiWPOcfsi4jS-W5E1FnkT2Xllt8M,22150
293
- mlrun/runtimes/mounts.py,sha256=Q6oN1ilVcsFaVM1DAS-mfCD7vGWa7Wa9aEhRrctJPyk,19292
294
- mlrun/runtimes/pod.py,sha256=HtSnhdfaT_rvYwybXjLowl3eOZSrRSyWqW7HYXuUT40,58252
292
+ mlrun/runtimes/local.py,sha256=sbIFQdU-GBfAwESJGU06hiqXUiwjP6IVvbCieIPGQn4,22311
293
+ mlrun/runtimes/mounts.py,sha256=S2nC5UaZFAl8N5HRyLkD9AUj7RqlPVSYVJcP9W8v4sg,19594
294
+ mlrun/runtimes/pod.py,sha256=4GZCobICnLcIBCjIbdCRuL-4k7tu0CKXzv3iatKD_gg,60192
295
295
  mlrun/runtimes/remotesparkjob.py,sha256=BalAea66GleaKeoYTw6ZL1Qr4wf1yRxfgk1-Fkc9Pqg,7864
296
296
  mlrun/runtimes/utils.py,sha256=b0T5Qm0WmbHk_I4d14ikzhhjymjIVedaifBi-ymKwOc,17733
297
297
  mlrun/runtimes/databricks_job/__init__.py,sha256=kXGBqhLN0rlAx0kTXhozGzFsIdSqW0uTSKMmsLgq_is,569
@@ -303,11 +303,11 @@ mlrun/runtimes/mpijob/abstract.py,sha256=QjAG4OZ6JEQ58w5-qYNd6hUGwvaW8ynLtlr9jNf
303
303
  mlrun/runtimes/mpijob/v1.py,sha256=zSlRkiWHz4B3yht66sVf4mlfDs8YT9EnP9DfBLn5VNs,3372
304
304
  mlrun/runtimes/nuclio/__init__.py,sha256=osOVMN9paIOuUoOTizmkxMb_OXRP-SlPwXHJSSYK_wk,834
305
305
  mlrun/runtimes/nuclio/api_gateway.py,sha256=vH9ClKVP4Mb24rvA67xPuAvAhX-gAv6vVtjVxyplhdc,26969
306
- mlrun/runtimes/nuclio/function.py,sha256=yL6PVyddDFEhXxY93g8YiywBERi-oqlpEw8IE3BVGmQ,56006
306
+ mlrun/runtimes/nuclio/function.py,sha256=vcW7IqCeLzxJ9YFBErqtEkp4MbgomFC1qWFTznBbNEY,56078
307
307
  mlrun/runtimes/nuclio/nuclio.py,sha256=sLK8KdGO1LbftlL3HqPZlFOFTAAuxJACZCVl1c0Ha6E,2942
308
- mlrun/runtimes/nuclio/serving.py,sha256=eXffwn6xTvEwC-HEk42DRxywOrin7RMUze3JWjeBxzA,36429
308
+ mlrun/runtimes/nuclio/serving.py,sha256=Y7wyqPrBS3Z-0QR6suGbqX36Cq-dKUwHI7zvO1fuLLo,39425
309
309
  mlrun/runtimes/nuclio/application/__init__.py,sha256=rRs5vasy_G9IyoTpYIjYDafGoL6ifFBKgBtsXn31Atw,614
310
- mlrun/runtimes/nuclio/application/application.py,sha256=usovOWonpzHQ1B_El7l60y-jpUXyYwppjmrHlP5RMW8,33993
310
+ mlrun/runtimes/nuclio/application/application.py,sha256=eVOdGXZF23VMxRhR_cZYArxxaUKKXtEshtomFf-vp3E,34065
311
311
  mlrun/runtimes/nuclio/application/reverse_proxy.go,sha256=lEHH74vr2PridIHp1Jkc_NjkrWb5b6zawRrNxHQhwGU,2913
312
312
  mlrun/runtimes/sparkjob/__init__.py,sha256=GPP_ekItxiU9Ydn3mJa4Obph02Bg6DO-JYs791_MV58,607
313
313
  mlrun/runtimes/sparkjob/spark3job.py,sha256=3dW7RG2T58F2dsUw0TsRvE3SIFcekx3CerLdcaG1f50,41458
@@ -333,7 +333,7 @@ mlrun/utils/async_http.py,sha256=8Olx8TNNeXB07nEGwlqhEgFgnFAD71vBU_bqaA9JW-w,122
333
333
  mlrun/utils/azure_vault.py,sha256=IEFizrDGDbAaoWwDr1WoA88S_EZ0T--vjYtY-i0cvYQ,3450
334
334
  mlrun/utils/clones.py,sha256=qbAGyEbSvlewn3Tw_DpQZP9z6MGzFhSaZfI1CblX8Fg,7515
335
335
  mlrun/utils/condition_evaluator.py,sha256=-nGfRmZzivn01rHTroiGY4rqEv8T1irMyhzxEei-sKc,1897
336
- mlrun/utils/helpers.py,sha256=zwaGatCEJphJEcTwvEOjiyGDWNSEDkzzYcR4IWsu378,84268
336
+ mlrun/utils/helpers.py,sha256=95nTQRqqsWeDzt19AEvz2pAkbEOfamvWg1es4cC6_us,87120
337
337
  mlrun/utils/http.py,sha256=5ZU2VpokaUM_DT3HBSqTm8xjUqTPjZN5fKkSIvKlTl0,8704
338
338
  mlrun/utils/logger.py,sha256=uaCgI_ezzaXf7nJDCy-1Nrjds8vSXqDbzmjmb3IyCQo,14864
339
339
  mlrun/utils/regex.py,sha256=FcRwWD8x9X3HLhCCU2F0AVKTFah784Pr7ZAe3a02jw8,5199
@@ -352,11 +352,11 @@ mlrun/utils/notifications/notification/mail.py,sha256=ZyJ3eqd8simxffQmXzqd3bgbAq
352
352
  mlrun/utils/notifications/notification/slack.py,sha256=wSu_7W0EnGLBNwIgWCYEeTP8j9SPAMPDBnfUcPnVZYA,7299
353
353
  mlrun/utils/notifications/notification/webhook.py,sha256=FM5-LQAKAVJKp37MRzR3SsejalcnpM6r_9Oe7znxZEA,5313
354
354
  mlrun/utils/version/__init__.py,sha256=YnzE6tlf24uOQ8y7Z7l96QLAI6-QEii7-77g8ynmzy0,613
355
- mlrun/utils/version/version.json,sha256=hHIsu87_e3inXvZwxyAJBc1LtA2aFWqipBV_Mhx1n5o,90
355
+ mlrun/utils/version/version.json,sha256=0zf1ul8-GHaXcJBnhG8fhsvEvZAHbHo2DlsdZIEg4mk,90
356
356
  mlrun/utils/version/version.py,sha256=M2hVhRrgkN3SxacZHs3ZqaOsqAA7B6a22ne324IQ1HE,1877
357
- mlrun-1.10.0rc38.dist-info/licenses/LICENSE,sha256=zTiv1CxWNkOk1q8eJS1G_8oD4gWpWLwWxj_Agcsi8Os,11337
358
- mlrun-1.10.0rc38.dist-info/METADATA,sha256=OGc4TY9eDtdLJ9NU5R8OsR_go-Wcm1VheehWzXs5yeE,26104
359
- mlrun-1.10.0rc38.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
360
- mlrun-1.10.0rc38.dist-info/entry_points.txt,sha256=1Owd16eAclD5pfRCoJpYC2ZJSyGNTtUr0nCELMioMmU,46
361
- mlrun-1.10.0rc38.dist-info/top_level.txt,sha256=NObLzw3maSF9wVrgSeYBv-fgnHkAJ1kEkh12DLdd5KM,6
362
- mlrun-1.10.0rc38.dist-info/RECORD,,
357
+ mlrun-1.10.0rc39.dist-info/licenses/LICENSE,sha256=zTiv1CxWNkOk1q8eJS1G_8oD4gWpWLwWxj_Agcsi8Os,11337
358
+ mlrun-1.10.0rc39.dist-info/METADATA,sha256=ZwFeqUwSkgA190q2yKK3LxcboenfDmI8VitS_siZVy0,26104
359
+ mlrun-1.10.0rc39.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
360
+ mlrun-1.10.0rc39.dist-info/entry_points.txt,sha256=1Owd16eAclD5pfRCoJpYC2ZJSyGNTtUr0nCELMioMmU,46
361
+ mlrun-1.10.0rc39.dist-info/top_level.txt,sha256=NObLzw3maSF9wVrgSeYBv-fgnHkAJ1kEkh12DLdd5KM,6
362
+ mlrun-1.10.0rc39.dist-info/RECORD,,