mlrun 1.7.0rc23__py3-none-any.whl → 1.7.0rc25__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of mlrun might be problematic. Click here for more details.

Files changed (36) hide show
  1. mlrun/__main__.py +3 -1
  2. mlrun/common/formatters/__init__.py +1 -0
  3. mlrun/common/formatters/artifact.py +26 -3
  4. mlrun/common/formatters/run.py +26 -0
  5. mlrun/common/helpers.py +11 -0
  6. mlrun/common/schemas/__init__.py +2 -0
  7. mlrun/common/schemas/alert.py +1 -1
  8. mlrun/common/schemas/api_gateway.py +57 -16
  9. mlrun/common/schemas/artifact.py +11 -0
  10. mlrun/common/schemas/feature_store.py +2 -22
  11. mlrun/common/schemas/pipeline.py +16 -0
  12. mlrun/common/schemas/project.py +17 -0
  13. mlrun/common/schemas/runs.py +17 -0
  14. mlrun/common/types.py +5 -0
  15. mlrun/config.py +1 -19
  16. mlrun/datastore/targets.py +12 -1
  17. mlrun/db/base.py +53 -2
  18. mlrun/db/httpdb.py +82 -9
  19. mlrun/db/nopdb.py +33 -2
  20. mlrun/model.py +2 -0
  21. mlrun/model_monitoring/applications/histogram_data_drift.py +1 -1
  22. mlrun/projects/pipelines.py +10 -9
  23. mlrun/projects/project.py +16 -6
  24. mlrun/run.py +11 -6
  25. mlrun/runtimes/base.py +11 -4
  26. mlrun/serving/server.py +10 -0
  27. mlrun/serving/states.py +29 -0
  28. mlrun/utils/helpers.py +3 -0
  29. mlrun/utils/notifications/notification_pusher.py +2 -8
  30. mlrun/utils/version/version.json +2 -2
  31. {mlrun-1.7.0rc23.dist-info → mlrun-1.7.0rc25.dist-info}/METADATA +2 -2
  32. {mlrun-1.7.0rc23.dist-info → mlrun-1.7.0rc25.dist-info}/RECORD +36 -35
  33. {mlrun-1.7.0rc23.dist-info → mlrun-1.7.0rc25.dist-info}/WHEEL +1 -1
  34. {mlrun-1.7.0rc23.dist-info → mlrun-1.7.0rc25.dist-info}/LICENSE +0 -0
  35. {mlrun-1.7.0rc23.dist-info → mlrun-1.7.0rc25.dist-info}/entry_points.txt +0 -0
  36. {mlrun-1.7.0rc23.dist-info → mlrun-1.7.0rc25.dist-info}/top_level.txt +0 -0
mlrun/__main__.py CHANGED
@@ -102,7 +102,9 @@ def main():
102
102
  )
103
103
  @click.option("--uid", help="unique run ID")
104
104
  @click.option("--name", help="run name")
105
- @click.option("--workflow", help="workflow name/id")
105
+ @click.option(
106
+ "--workflow", help="sets the run labels to match the given workflow name/id"
107
+ )
106
108
  @click.option("--project", help="project name/id")
107
109
  @click.option("--db", default="", help="save run results to path or DB url")
108
110
  @click.option(
@@ -17,3 +17,4 @@ from .artifact import ArtifactFormat # noqa
17
17
  from .function import FunctionFormat # noqa
18
18
  from .pipeline import PipelineFormat # noqa
19
19
  from .project import ProjectFormat # noqa
20
+ from .run import RunFormat # noqa
@@ -13,9 +13,32 @@
13
13
  # limitations under the License.
14
14
  #
15
15
 
16
+ import typing
17
+
16
18
  import mlrun.common.types
17
19
 
20
+ from .base import ObjectFormat
21
+
22
+
23
+ class ArtifactFormat(ObjectFormat, mlrun.common.types.StrEnum):
24
+ minimal = "minimal"
18
25
 
19
- # TODO: add a format that returns a minimal response with ObjectFormat
20
- class ArtifactFormat(mlrun.common.types.StrEnum):
21
- full = "full"
26
+ @staticmethod
27
+ def format_method(_format: str) -> typing.Optional[typing.Callable]:
28
+ return {
29
+ ArtifactFormat.full: None,
30
+ ArtifactFormat.minimal: ArtifactFormat.filter_obj_method(
31
+ [
32
+ "kind",
33
+ "metadata",
34
+ "status",
35
+ "project",
36
+ "spec.producer",
37
+ "spec.db_key",
38
+ "spec.size",
39
+ "spec.framework",
40
+ "spec.metrics",
41
+ "spec.target_path",
42
+ ]
43
+ ),
44
+ }[_format]
@@ -0,0 +1,26 @@
1
+ # Copyright 2024 Iguazio
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ #
15
+
16
+
17
+ import mlrun.common.types
18
+ from mlrun.common.formatters.base import ObjectFormat
19
+
20
+
21
+ class RunFormat(ObjectFormat, mlrun.common.types.StrEnum):
22
+ # No enrichment, data is pulled as-is from the database.
23
+ standard = "standard"
24
+
25
+ # Performs run enrichment, including the run's artifacts. Only available for the `get` run API.
26
+ full = "full"
mlrun/common/helpers.py CHANGED
@@ -34,3 +34,14 @@ def parse_versioned_object_uri(
34
34
  uri = uri[:loc]
35
35
 
36
36
  return project, uri, tag, hash_key
37
+
38
+
39
+ def generate_api_gateway_name(project: str, name: str) -> str:
40
+ """
41
+ Generate a unique (within project) api gateway name
42
+ :param project: project name
43
+ :param name: api gateway name
44
+
45
+ :return: the resolved api gateway name
46
+ """
47
+ return f"{project}-{name}" if project else name
@@ -91,7 +91,9 @@ from .feature_store import (
91
91
  FeatureRecord,
92
92
  FeatureSet,
93
93
  FeatureSetDigestOutput,
94
+ FeatureSetDigestOutputV2,
94
95
  FeatureSetDigestSpec,
96
+ FeatureSetDigestSpecV2,
95
97
  FeatureSetIngestInput,
96
98
  FeatureSetIngestOutput,
97
99
  FeatureSetRecord,
@@ -104,7 +104,7 @@ class AlertCriteria(pydantic.BaseModel):
104
104
  pydantic.Field(
105
105
  description="Number of events to wait until notification is sent"
106
106
  ),
107
- ] = 0
107
+ ] = 1
108
108
  period: Annotated[
109
109
  str,
110
110
  pydantic.Field(
@@ -17,8 +17,10 @@ from typing import Optional
17
17
 
18
18
  import pydantic
19
19
 
20
+ import mlrun.common.constants as mlrun_constants
20
21
  import mlrun.common.types
21
22
  from mlrun.common.constants import MLRUN_FUNCTIONS_ANNOTATION
23
+ from mlrun.common.helpers import generate_api_gateway_name
22
24
 
23
25
 
24
26
  class APIGatewayAuthenticationMode(mlrun.common.types.StrEnum):
@@ -100,7 +102,51 @@ class APIGateway(_APIGatewayBaseModel):
100
102
  if upstream.nucliofunction.get("name")
101
103
  ]
102
104
 
103
- def enrich_mlrun_function_names(self):
105
+ def enrich_mlrun_names(self):
106
+ self._enrich_api_gateway_mlrun_name()
107
+ self._enrich_mlrun_function_names()
108
+ return self
109
+
110
+ def replace_nuclio_names_with_mlrun_names(self):
111
+ self._replace_nuclio_api_gateway_name_with_mlrun_name()
112
+ self._replace_nuclio_function_names_with_mlrun_names()
113
+ return self
114
+
115
+ def _replace_nuclio_function_names_with_mlrun_names(self):
116
+ # replace function names from nuclio names to mlrun names
117
+ # and adds mlrun function URI's to an api gateway annotations
118
+ # so when we then get api gateway entity from nuclio, we are able to get mlrun function names
119
+ mlrun_functions = self.metadata.annotations.get(MLRUN_FUNCTIONS_ANNOTATION)
120
+ if mlrun_functions:
121
+ mlrun_function_uris = (
122
+ mlrun_functions.split("&")
123
+ if "&" in mlrun_functions
124
+ else [mlrun_functions]
125
+ )
126
+ if len(mlrun_function_uris) != len(self.spec.upstreams):
127
+ raise mlrun.errors.MLRunValueError(
128
+ "Error when translating nuclio names to mlrun names in api gateway:"
129
+ " number of functions doesn't match the mlrun functions in annotation"
130
+ )
131
+ for i in range(len(mlrun_function_uris)):
132
+ self.spec.upstreams[i].nucliofunction["name"] = mlrun_function_uris[i]
133
+ return self
134
+
135
+ def _replace_nuclio_api_gateway_name_with_mlrun_name(self):
136
+ # replace api gateway name
137
+ # in Nuclio, api gateways are named as `<project>-<mlrun-api-gateway-name>`
138
+ # remove the project prefix from the name if it exists
139
+ project_name = self.metadata.labels.get(
140
+ mlrun_constants.MLRunInternalLabels.nuclio_project_name
141
+ )
142
+ if project_name and self.spec.name.startswith(f"{project_name}-"):
143
+ self.spec.name = self.spec.name[len(project_name) + 1 :]
144
+ self.metadata.name = self.spec.name
145
+ return self
146
+
147
+ def _enrich_mlrun_function_names(self):
148
+ # enrich mlrun names with nuclio prefixes
149
+ # and add mlrun function's URIs to Nuclio function annotations
104
150
  upstream_with_nuclio_names = []
105
151
  mlrun_function_uris = []
106
152
  for upstream in self.spec.upstreams:
@@ -126,21 +172,16 @@ class APIGateway(_APIGatewayBaseModel):
126
172
  )
127
173
  return self
128
174
 
129
- def replace_nuclio_names_with_mlrun_uri(self):
130
- mlrun_functions = self.metadata.annotations.get(MLRUN_FUNCTIONS_ANNOTATION)
131
- if mlrun_functions:
132
- mlrun_function_uris = (
133
- mlrun_functions.split("&")
134
- if "&" in mlrun_functions
135
- else [mlrun_functions]
136
- )
137
- if len(mlrun_function_uris) != len(self.spec.upstreams):
138
- raise mlrun.errors.MLRunValueError(
139
- "Error when translating nuclio names to mlrun names in api gateway:"
140
- " number of functions doesn't match the mlrun functions in annotation"
141
- )
142
- for i in range(len(mlrun_function_uris)):
143
- self.spec.upstreams[i].nucliofunction["name"] = mlrun_function_uris[i]
175
+ def _enrich_api_gateway_mlrun_name(self):
176
+ # replace api gateway name
177
+ # in Nuclio, api gateways are named as `<project>-<mlrun-api-gateway-name>`
178
+ # add the project prefix to the name
179
+ project_name = self.metadata.labels.get(
180
+ mlrun_constants.MLRunInternalLabels.nuclio_project_name
181
+ )
182
+ if project_name:
183
+ self.spec.name = generate_api_gateway_name(project_name, self.spec.name)
184
+ self.metadata.name = self.spec.name
144
185
  return self
145
186
 
146
187
 
@@ -15,6 +15,7 @@
15
15
  import typing
16
16
 
17
17
  import pydantic
18
+ from deprecated import deprecated
18
19
 
19
20
  import mlrun.common.types
20
21
 
@@ -58,6 +59,16 @@ class ArtifactIdentifier(pydantic.BaseModel):
58
59
  # hash: typing.Optional[str]
59
60
 
60
61
 
62
+ @deprecated(
63
+ version="1.7.0",
64
+ reason="mlrun.common.schemas.ArtifactsFormat is deprecated and will be removed in 1.9.0. "
65
+ "Use mlrun.common.formatters.ArtifactFormat instead.",
66
+ category=FutureWarning,
67
+ )
68
+ class ArtifactsFormat(mlrun.common.types.StrEnum):
69
+ full = "full"
70
+
71
+
61
72
  class ArtifactMetadata(pydantic.BaseModel):
62
73
  key: str
63
74
  project: str
@@ -46,16 +46,6 @@ class Feature(FeatureStoreBaseModel):
46
46
  extra = pydantic.Extra.allow
47
47
 
48
48
 
49
- class QualifiedFeature(FeatureStoreBaseModel):
50
- name: str
51
- value_type: str
52
- feature_set_index: int
53
- labels: Optional[dict] = {}
54
-
55
- class Config:
56
- extra = pydantic.Extra.allow
57
-
58
-
59
49
  class Entity(FeatureStoreBaseModel):
60
50
  name: str
61
51
  value_type: str
@@ -65,16 +55,6 @@ class Entity(FeatureStoreBaseModel):
65
55
  extra = pydantic.Extra.allow
66
56
 
67
57
 
68
- class QualifiedEntity(FeatureStoreBaseModel):
69
- name: str
70
- value_type: str
71
- feature_set_index: int
72
- labels: Optional[dict] = {}
73
-
74
- class Config:
75
- extra = pydantic.Extra.allow
76
-
77
-
78
58
  class FeatureSetSpec(ObjectSpec):
79
59
  entities: list[Entity] = []
80
60
  features: list[Feature] = []
@@ -156,7 +136,7 @@ class FeaturesOutput(FeatureStoreBaseModel):
156
136
 
157
137
 
158
138
  class FeaturesOutputV2(FeatureStoreBaseModel):
159
- features: list[QualifiedFeature]
139
+ features: list[Feature]
160
140
  feature_set_digests: list[FeatureSetDigestOutputV2]
161
141
 
162
142
 
@@ -166,7 +146,7 @@ class EntityListOutput(FeatureStoreBaseModel):
166
146
 
167
147
 
168
148
  class EntitiesOutputV2(FeatureStoreBaseModel):
169
- entities: list[QualifiedEntity]
149
+ entities: list[Entity]
170
150
  feature_set_digests: list[FeatureSetDigestOutputV2]
171
151
 
172
152
 
@@ -15,6 +15,22 @@
15
15
  import typing
16
16
 
17
17
  import pydantic
18
+ from deprecated import deprecated
19
+
20
+ import mlrun.common.types
21
+
22
+
23
+ @deprecated(
24
+ version="1.7.0",
25
+ reason="mlrun.common.schemas.PipelinesFormat is deprecated and will be removed in 1.9.0. "
26
+ "Use mlrun.common.formatters.PipelineFormat instead.",
27
+ category=FutureWarning,
28
+ )
29
+ class PipelinesFormat(mlrun.common.types.StrEnum):
30
+ full = "full"
31
+ metadata_only = "metadata_only"
32
+ summary = "summary"
33
+ name_only = "name_only"
18
34
 
19
35
 
20
36
  class PipelinesPagination(str):
@@ -16,6 +16,7 @@ import datetime
16
16
  import typing
17
17
 
18
18
  import pydantic
19
+ from deprecated import deprecated
19
20
 
20
21
  import mlrun.common.types
21
22
 
@@ -23,6 +24,22 @@ from .common import ImageBuilder
23
24
  from .object import ObjectKind, ObjectStatus
24
25
 
25
26
 
27
+ @deprecated(
28
+ version="1.7.0",
29
+ reason="mlrun.common.schemas.ProjectsFormat is deprecated and will be removed in 1.9.0. "
30
+ "Use mlrun.common.formatters.ProjectFormat instead.",
31
+ category=FutureWarning,
32
+ )
33
+ class ProjectsFormat(mlrun.common.types.StrEnum):
34
+ full = "full"
35
+ name_only = "name_only"
36
+ # minimal format removes large fields from the response (e.g. functions, workflows, artifacts)
37
+ # and is used for faster response times (in the UI)
38
+ minimal = "minimal"
39
+ # internal - allowed only in follower mode, only for the leader for upgrade purposes
40
+ leader = "leader"
41
+
42
+
26
43
  class ProjectMetadata(pydantic.BaseModel):
27
44
  name: str
28
45
  created: typing.Optional[datetime.datetime] = None
@@ -15,9 +15,26 @@
15
15
  import typing
16
16
 
17
17
  import pydantic
18
+ from deprecated import deprecated
19
+
20
+ import mlrun.common.types
18
21
 
19
22
 
20
23
  class RunIdentifier(pydantic.BaseModel):
21
24
  kind: typing.Literal["run"] = "run"
22
25
  uid: typing.Optional[str]
23
26
  iter: typing.Optional[int]
27
+
28
+
29
+ @deprecated(
30
+ version="1.7.0",
31
+ reason="mlrun.common.schemas.RunsFormat is deprecated and will be removed in 1.9.0. "
32
+ "Use mlrun.common.formatters.RunFormat instead.",
33
+ category=FutureWarning,
34
+ )
35
+ class RunsFormat(mlrun.common.types.StrEnum):
36
+ # No enrichment, data is pulled as-is from the database.
37
+ standard = "standard"
38
+
39
+ # Performs run enrichment, including the run's artifacts. Only available for the `get` run API.
40
+ full = "full"
mlrun/common/types.py CHANGED
@@ -30,3 +30,8 @@ class HTTPMethod(StrEnum):
30
30
  GET = "GET"
31
31
  POST = "POST"
32
32
  DELETE = "DELETE"
33
+
34
+
35
+ class Operation(StrEnum):
36
+ ADD = "add"
37
+ REMOVE = "remove"
mlrun/config.py CHANGED
@@ -707,7 +707,7 @@ default_config = {
707
707
  "mode": "enabled",
708
708
  # maximum number of alerts we allow to be configured.
709
709
  # user will get an error when exceeding this
710
- "max_allowed": 1000,
710
+ "max_allowed": 10000,
711
711
  },
712
712
  "auth_with_client_id": {
713
713
  "enabled": False,
@@ -938,24 +938,6 @@ class Config:
938
938
  f"is not allowed for iguazio version: {igz_version} < 3.5.1"
939
939
  )
940
940
 
941
- def resolve_kfp_url(self, namespace=None):
942
- if config.kfp_url:
943
- return config.kfp_url
944
- igz_version = self.get_parsed_igz_version()
945
- # TODO: When Iguazio 3.4 will deprecate we can remove this line
946
- if igz_version and igz_version <= semver.VersionInfo.parse("3.6.0-b1"):
947
- if namespace is None:
948
- if not config.namespace:
949
- raise mlrun.errors.MLRunNotFoundError(
950
- "For KubeFlow Pipelines to function, a namespace must be configured"
951
- )
952
- namespace = config.namespace
953
- # When instead of host we provided namespace we tackled this issue
954
- # https://github.com/canonical/bundle-kubeflow/issues/412
955
- # TODO: When we'll move to kfp 1.4.0 (server side) it should be resolved
956
- return f"http://ml-pipeline.{namespace}.svc.cluster.local:8888"
957
- return None
958
-
959
941
  def resolve_chief_api_url(self) -> str:
960
942
  if self.httpdb.clusterization.chief.url:
961
943
  return self.httpdb.clusterization.chief.url
@@ -696,6 +696,7 @@ class BaseStoreTarget(DataTargetBase):
696
696
  self.kind, self.name, self.get_target_templated_path()
697
697
  )
698
698
  target = self._target
699
+ target.attributes = self.attributes
699
700
  target.run_id = self.run_id
700
701
  target.status = status or target.status or "created"
701
702
  target.updated = now_date().isoformat()
@@ -727,8 +728,18 @@ class BaseStoreTarget(DataTargetBase):
727
728
  raise NotImplementedError()
728
729
 
729
730
  def purge(self):
731
+ """
732
+ Delete the files of the target.
733
+
734
+ Do not use this function directly from the sdk. Use FeatureSet.purge_targets.
735
+ """
730
736
  store, path_in_store, target_path = self._get_store_and_path()
731
- store.rm(target_path, recursive=True)
737
+ if path_in_store not in ["", "/"]:
738
+ store.rm(path_in_store, recursive=True)
739
+ else:
740
+ raise mlrun.errors.MLRunInvalidArgumentError(
741
+ "Unable to delete target. Please Use purge_targets from FeatureSet object."
742
+ )
732
743
 
733
744
  def as_df(
734
745
  self,
mlrun/db/base.py CHANGED
@@ -16,6 +16,8 @@ import datetime
16
16
  from abc import ABC, abstractmethod
17
17
  from typing import Optional, Union
18
18
 
19
+ from deprecated import deprecated
20
+
19
21
  import mlrun.alerts
20
22
  import mlrun.common
21
23
  import mlrun.common.formatters
@@ -56,7 +58,13 @@ class RunDBInterface(ABC):
56
58
  pass
57
59
 
58
60
  @abstractmethod
59
- def read_run(self, uid, project="", iter=0):
61
+ def read_run(
62
+ self,
63
+ uid: str,
64
+ project: str = "",
65
+ iter: int = 0,
66
+ format_: mlrun.common.formatters.RunFormat = mlrun.common.formatters.RunFormat.full,
67
+ ):
60
68
  pass
61
69
 
62
70
  @abstractmethod
@@ -103,7 +111,16 @@ class RunDBInterface(ABC):
103
111
  pass
104
112
 
105
113
  @abstractmethod
106
- def read_artifact(self, key, tag="", iter=None, project="", tree=None, uid=None):
114
+ def read_artifact(
115
+ self,
116
+ key,
117
+ tag="",
118
+ iter=None,
119
+ project="",
120
+ tree=None,
121
+ uid=None,
122
+ format_: mlrun.common.formatters.ArtifactFormat = mlrun.common.formatters.ArtifactFormat.full,
123
+ ):
107
124
  pass
108
125
 
109
126
  @abstractmethod
@@ -120,6 +137,7 @@ class RunDBInterface(ABC):
120
137
  kind: str = None,
121
138
  category: Union[str, mlrun.common.schemas.ArtifactCategories] = None,
122
139
  tree: str = None,
140
+ format_: mlrun.common.formatters.ArtifactFormat = mlrun.common.formatters.ArtifactFormat.full,
123
141
  ):
124
142
  pass
125
143
 
@@ -302,6 +320,12 @@ class RunDBInterface(ABC):
302
320
  ) -> dict:
303
321
  pass
304
322
 
323
+ # TODO: remove in 1.9.0
324
+ @deprecated(
325
+ version="1.9.0",
326
+ reason="'list_features' will be removed in 1.9.0, use 'list_features_v2' instead",
327
+ category=FutureWarning,
328
+ )
305
329
  @abstractmethod
306
330
  def list_features(
307
331
  self,
@@ -313,6 +337,23 @@ class RunDBInterface(ABC):
313
337
  ) -> mlrun.common.schemas.FeaturesOutput:
314
338
  pass
315
339
 
340
+ @abstractmethod
341
+ def list_features_v2(
342
+ self,
343
+ project: str,
344
+ name: str = None,
345
+ tag: str = None,
346
+ entities: list[str] = None,
347
+ labels: list[str] = None,
348
+ ) -> mlrun.common.schemas.FeaturesOutputV2:
349
+ pass
350
+
351
+ # TODO: remove in 1.9.0
352
+ @deprecated(
353
+ version="1.9.0",
354
+ reason="'list_entities' will be removed in 1.9.0, use 'list_entities_v2' instead",
355
+ category=FutureWarning,
356
+ )
316
357
  @abstractmethod
317
358
  def list_entities(
318
359
  self,
@@ -323,6 +364,16 @@ class RunDBInterface(ABC):
323
364
  ) -> mlrun.common.schemas.EntitiesOutput:
324
365
  pass
325
366
 
367
+ @abstractmethod
368
+ def list_entities_v2(
369
+ self,
370
+ project: str,
371
+ name: str = None,
372
+ tag: str = None,
373
+ labels: list[str] = None,
374
+ ) -> mlrun.common.schemas.EntitiesOutputV2:
375
+ pass
376
+
326
377
  @abstractmethod
327
378
  def list_feature_sets(
328
379
  self,