mlrun 1.6.0rc35__py3-none-any.whl → 1.7.0rc2__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/__main__.py +3 -3
- mlrun/api/schemas/__init__.py +1 -1
- mlrun/artifacts/base.py +11 -6
- mlrun/artifacts/dataset.py +2 -2
- mlrun/artifacts/model.py +30 -24
- mlrun/artifacts/plots.py +2 -2
- mlrun/common/db/sql_session.py +5 -3
- mlrun/common/helpers.py +1 -2
- mlrun/common/schemas/artifact.py +3 -3
- mlrun/common/schemas/auth.py +3 -3
- mlrun/common/schemas/background_task.py +1 -1
- mlrun/common/schemas/client_spec.py +1 -1
- mlrun/common/schemas/feature_store.py +16 -16
- mlrun/common/schemas/frontend_spec.py +7 -7
- mlrun/common/schemas/function.py +1 -1
- mlrun/common/schemas/hub.py +4 -9
- mlrun/common/schemas/memory_reports.py +2 -2
- mlrun/common/schemas/model_monitoring/grafana.py +4 -4
- mlrun/common/schemas/model_monitoring/model_endpoints.py +14 -15
- mlrun/common/schemas/notification.py +4 -4
- mlrun/common/schemas/object.py +2 -2
- mlrun/common/schemas/pipeline.py +1 -1
- mlrun/common/schemas/project.py +3 -3
- mlrun/common/schemas/runtime_resource.py +8 -12
- mlrun/common/schemas/schedule.py +3 -3
- mlrun/common/schemas/tag.py +1 -2
- mlrun/common/schemas/workflow.py +2 -2
- mlrun/config.py +8 -4
- mlrun/data_types/to_pandas.py +1 -3
- mlrun/datastore/base.py +0 -28
- mlrun/datastore/datastore_profile.py +9 -9
- mlrun/datastore/filestore.py +0 -1
- mlrun/datastore/google_cloud_storage.py +1 -1
- mlrun/datastore/sources.py +7 -11
- mlrun/datastore/spark_utils.py +1 -2
- mlrun/datastore/targets.py +31 -31
- mlrun/datastore/utils.py +4 -6
- mlrun/datastore/v3io.py +70 -46
- mlrun/db/base.py +22 -23
- mlrun/db/httpdb.py +34 -34
- mlrun/db/nopdb.py +19 -19
- mlrun/errors.py +1 -1
- mlrun/execution.py +4 -4
- mlrun/feature_store/api.py +20 -21
- mlrun/feature_store/common.py +1 -1
- mlrun/feature_store/feature_set.py +28 -32
- mlrun/feature_store/feature_vector.py +24 -27
- mlrun/feature_store/retrieval/base.py +7 -7
- mlrun/feature_store/retrieval/conversion.py +2 -4
- mlrun/feature_store/steps.py +7 -15
- mlrun/features.py +5 -7
- mlrun/frameworks/_common/artifacts_library.py +9 -9
- mlrun/frameworks/_common/mlrun_interface.py +5 -5
- mlrun/frameworks/_common/model_handler.py +48 -48
- mlrun/frameworks/_common/plan.py +2 -3
- mlrun/frameworks/_common/producer.py +3 -4
- mlrun/frameworks/_common/utils.py +5 -5
- mlrun/frameworks/_dl_common/loggers/logger.py +6 -7
- mlrun/frameworks/_dl_common/loggers/mlrun_logger.py +9 -9
- mlrun/frameworks/_dl_common/loggers/tensorboard_logger.py +16 -35
- mlrun/frameworks/_ml_common/artifacts_library.py +1 -2
- mlrun/frameworks/_ml_common/loggers/logger.py +3 -4
- mlrun/frameworks/_ml_common/loggers/mlrun_logger.py +4 -5
- mlrun/frameworks/_ml_common/model_handler.py +24 -24
- mlrun/frameworks/_ml_common/pkl_model_server.py +2 -2
- mlrun/frameworks/_ml_common/plan.py +1 -1
- mlrun/frameworks/_ml_common/plans/calibration_curve_plan.py +2 -3
- mlrun/frameworks/_ml_common/plans/confusion_matrix_plan.py +2 -3
- mlrun/frameworks/_ml_common/plans/dataset_plan.py +3 -3
- mlrun/frameworks/_ml_common/plans/feature_importance_plan.py +3 -3
- mlrun/frameworks/_ml_common/plans/roc_curve_plan.py +4 -4
- mlrun/frameworks/_ml_common/utils.py +4 -4
- mlrun/frameworks/auto_mlrun/auto_mlrun.py +7 -7
- mlrun/frameworks/huggingface/model_server.py +4 -4
- mlrun/frameworks/lgbm/__init__.py +32 -32
- mlrun/frameworks/lgbm/callbacks/logging_callback.py +4 -5
- mlrun/frameworks/lgbm/callbacks/mlrun_logging_callback.py +4 -5
- mlrun/frameworks/lgbm/mlrun_interfaces/booster_mlrun_interface.py +1 -3
- mlrun/frameworks/lgbm/mlrun_interfaces/mlrun_interface.py +6 -6
- mlrun/frameworks/lgbm/model_handler.py +9 -9
- mlrun/frameworks/lgbm/model_server.py +6 -6
- mlrun/frameworks/lgbm/utils.py +5 -5
- mlrun/frameworks/onnx/dataset.py +8 -8
- mlrun/frameworks/onnx/mlrun_interface.py +3 -3
- mlrun/frameworks/onnx/model_handler.py +6 -6
- mlrun/frameworks/onnx/model_server.py +7 -7
- mlrun/frameworks/parallel_coordinates.py +2 -2
- mlrun/frameworks/pytorch/__init__.py +16 -16
- mlrun/frameworks/pytorch/callbacks/callback.py +4 -5
- mlrun/frameworks/pytorch/callbacks/logging_callback.py +17 -17
- mlrun/frameworks/pytorch/callbacks/mlrun_logging_callback.py +11 -11
- mlrun/frameworks/pytorch/callbacks/tensorboard_logging_callback.py +23 -29
- mlrun/frameworks/pytorch/callbacks_handler.py +38 -38
- mlrun/frameworks/pytorch/mlrun_interface.py +20 -20
- mlrun/frameworks/pytorch/model_handler.py +17 -17
- mlrun/frameworks/pytorch/model_server.py +7 -7
- mlrun/frameworks/sklearn/__init__.py +12 -12
- mlrun/frameworks/sklearn/estimator.py +4 -4
- mlrun/frameworks/sklearn/metrics_library.py +14 -14
- mlrun/frameworks/sklearn/mlrun_interface.py +3 -6
- mlrun/frameworks/sklearn/model_handler.py +2 -2
- mlrun/frameworks/tf_keras/__init__.py +5 -5
- mlrun/frameworks/tf_keras/callbacks/logging_callback.py +14 -14
- mlrun/frameworks/tf_keras/callbacks/mlrun_logging_callback.py +11 -11
- mlrun/frameworks/tf_keras/callbacks/tensorboard_logging_callback.py +19 -23
- mlrun/frameworks/tf_keras/mlrun_interface.py +7 -9
- mlrun/frameworks/tf_keras/model_handler.py +14 -14
- mlrun/frameworks/tf_keras/model_server.py +6 -6
- mlrun/frameworks/xgboost/__init__.py +12 -12
- mlrun/frameworks/xgboost/model_handler.py +6 -6
- mlrun/k8s_utils.py +4 -5
- mlrun/kfpops.py +2 -2
- mlrun/launcher/base.py +10 -10
- mlrun/launcher/local.py +8 -8
- mlrun/launcher/remote.py +7 -7
- mlrun/lists.py +3 -4
- mlrun/model.py +205 -55
- mlrun/model_monitoring/api.py +21 -24
- mlrun/model_monitoring/application.py +4 -4
- mlrun/model_monitoring/batch.py +17 -17
- mlrun/model_monitoring/controller.py +2 -1
- mlrun/model_monitoring/features_drift_table.py +44 -31
- mlrun/model_monitoring/prometheus.py +1 -4
- mlrun/model_monitoring/stores/kv_model_endpoint_store.py +11 -13
- mlrun/model_monitoring/stores/model_endpoint_store.py +9 -11
- mlrun/model_monitoring/stores/models/__init__.py +2 -2
- mlrun/model_monitoring/stores/sql_model_endpoint_store.py +11 -13
- mlrun/model_monitoring/stream_processing.py +16 -34
- mlrun/model_monitoring/tracking_policy.py +2 -1
- mlrun/package/__init__.py +6 -6
- mlrun/package/context_handler.py +5 -5
- mlrun/package/packager.py +7 -7
- mlrun/package/packagers/default_packager.py +6 -6
- mlrun/package/packagers/numpy_packagers.py +15 -15
- mlrun/package/packagers/pandas_packagers.py +5 -5
- mlrun/package/packagers/python_standard_library_packagers.py +10 -10
- mlrun/package/packagers_manager.py +18 -23
- mlrun/package/utils/_formatter.py +4 -4
- mlrun/package/utils/_pickler.py +2 -2
- mlrun/package/utils/_supported_format.py +4 -4
- mlrun/package/utils/log_hint_utils.py +2 -2
- mlrun/package/utils/type_hint_utils.py +4 -9
- mlrun/platforms/other.py +1 -2
- mlrun/projects/operations.py +5 -5
- mlrun/projects/pipelines.py +9 -9
- mlrun/projects/project.py +58 -46
- mlrun/render.py +1 -1
- mlrun/run.py +9 -9
- mlrun/runtimes/__init__.py +7 -4
- mlrun/runtimes/base.py +20 -23
- mlrun/runtimes/constants.py +5 -5
- mlrun/runtimes/daskjob.py +8 -8
- mlrun/runtimes/databricks_job/databricks_cancel_task.py +1 -1
- mlrun/runtimes/databricks_job/databricks_runtime.py +7 -7
- mlrun/runtimes/function_reference.py +1 -1
- mlrun/runtimes/local.py +1 -1
- mlrun/runtimes/mpijob/abstract.py +1 -2
- mlrun/runtimes/nuclio/__init__.py +20 -0
- mlrun/runtimes/{function.py → nuclio/function.py} +15 -16
- mlrun/runtimes/{nuclio.py → nuclio/nuclio.py} +6 -6
- mlrun/runtimes/{serving.py → nuclio/serving.py} +13 -12
- mlrun/runtimes/pod.py +95 -48
- mlrun/runtimes/remotesparkjob.py +1 -1
- mlrun/runtimes/sparkjob/spark3job.py +50 -33
- mlrun/runtimes/utils.py +1 -2
- mlrun/secrets.py +3 -3
- mlrun/serving/remote.py +0 -4
- mlrun/serving/routers.py +6 -6
- mlrun/serving/server.py +4 -4
- mlrun/serving/states.py +29 -0
- mlrun/serving/utils.py +3 -3
- mlrun/serving/v1_serving.py +6 -7
- mlrun/serving/v2_serving.py +50 -8
- mlrun/track/tracker_manager.py +3 -3
- mlrun/track/trackers/mlflow_tracker.py +1 -2
- mlrun/utils/async_http.py +5 -7
- mlrun/utils/azure_vault.py +1 -1
- mlrun/utils/clones.py +1 -2
- mlrun/utils/condition_evaluator.py +3 -3
- mlrun/utils/db.py +3 -3
- mlrun/utils/helpers.py +37 -119
- mlrun/utils/http.py +1 -4
- mlrun/utils/logger.py +49 -14
- mlrun/utils/notifications/notification/__init__.py +3 -3
- mlrun/utils/notifications/notification/base.py +2 -2
- mlrun/utils/notifications/notification/ipython.py +1 -1
- mlrun/utils/notifications/notification_pusher.py +8 -14
- mlrun/utils/retryer.py +207 -0
- mlrun/utils/singleton.py +1 -1
- mlrun/utils/v3io_clients.py +2 -3
- mlrun/utils/version/version.json +2 -2
- mlrun/utils/version/version.py +2 -6
- {mlrun-1.6.0rc35.dist-info → mlrun-1.7.0rc2.dist-info}/METADATA +9 -9
- mlrun-1.7.0rc2.dist-info/RECORD +315 -0
- mlrun-1.6.0rc35.dist-info/RECORD +0 -313
- {mlrun-1.6.0rc35.dist-info → mlrun-1.7.0rc2.dist-info}/LICENSE +0 -0
- {mlrun-1.6.0rc35.dist-info → mlrun-1.7.0rc2.dist-info}/WHEEL +0 -0
- {mlrun-1.6.0rc35.dist-info → mlrun-1.7.0rc2.dist-info}/entry_points.txt +0 -0
- {mlrun-1.6.0rc35.dist-info → mlrun-1.7.0rc2.dist-info}/top_level.txt +0 -0
mlrun/launcher/local.py
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
import os
|
|
15
15
|
import pathlib
|
|
16
|
-
from typing import Callable,
|
|
16
|
+
from typing import Callable, Optional, Union
|
|
17
17
|
|
|
18
18
|
import mlrun.common.schemas.schedule
|
|
19
19
|
import mlrun.errors
|
|
@@ -50,7 +50,7 @@ class ClientLocalLauncher(launcher.ClientBaseLauncher):
|
|
|
50
50
|
name: Optional[str] = "",
|
|
51
51
|
project: Optional[str] = "",
|
|
52
52
|
params: Optional[dict] = None,
|
|
53
|
-
inputs: Optional[
|
|
53
|
+
inputs: Optional[dict[str, str]] = None,
|
|
54
54
|
out_path: Optional[str] = "",
|
|
55
55
|
workdir: Optional[str] = "",
|
|
56
56
|
artifact_path: Optional[str] = "",
|
|
@@ -58,16 +58,16 @@ class ClientLocalLauncher(launcher.ClientBaseLauncher):
|
|
|
58
58
|
schedule: Optional[
|
|
59
59
|
Union[str, mlrun.common.schemas.schedule.ScheduleCronTrigger]
|
|
60
60
|
] = None,
|
|
61
|
-
hyperparams:
|
|
61
|
+
hyperparams: dict[str, list] = None,
|
|
62
62
|
hyper_param_options: Optional[mlrun.model.HyperParamOptions] = None,
|
|
63
63
|
verbose: Optional[bool] = None,
|
|
64
64
|
scrape_metrics: Optional[bool] = None,
|
|
65
65
|
local_code_path: Optional[str] = None,
|
|
66
66
|
auto_build: Optional[bool] = None,
|
|
67
|
-
param_file_secrets: Optional[
|
|
68
|
-
notifications: Optional[
|
|
69
|
-
returns: Optional[
|
|
70
|
-
state_thresholds: Optional[
|
|
67
|
+
param_file_secrets: Optional[dict[str, str]] = None,
|
|
68
|
+
notifications: Optional[list[mlrun.model.Notification]] = None,
|
|
69
|
+
returns: Optional[list[Union[str, dict[str, str]]]] = None,
|
|
70
|
+
state_thresholds: Optional[dict[str, int]] = None,
|
|
71
71
|
) -> "mlrun.run.RunObject":
|
|
72
72
|
# do not allow local function to be scheduled
|
|
73
73
|
if self._is_run_local and schedule is not None:
|
|
@@ -247,7 +247,7 @@ class ClientLocalLauncher(launcher.ClientBaseLauncher):
|
|
|
247
247
|
return fn
|
|
248
248
|
|
|
249
249
|
@staticmethod
|
|
250
|
-
def _resolve_local_code_path(local_code_path: str) -> (str,
|
|
250
|
+
def _resolve_local_code_path(local_code_path: str) -> (str, list[str]):
|
|
251
251
|
command = None
|
|
252
252
|
args = []
|
|
253
253
|
if local_code_path:
|
mlrun/launcher/remote.py
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
import os
|
|
15
|
-
from typing import
|
|
15
|
+
from typing import Optional, Union
|
|
16
16
|
|
|
17
17
|
import pandas as pd
|
|
18
18
|
import requests
|
|
@@ -40,7 +40,7 @@ class ClientRemoteLauncher(launcher.ClientBaseLauncher):
|
|
|
40
40
|
name: Optional[str] = "",
|
|
41
41
|
project: Optional[str] = "",
|
|
42
42
|
params: Optional[dict] = None,
|
|
43
|
-
inputs: Optional[
|
|
43
|
+
inputs: Optional[dict[str, str]] = None,
|
|
44
44
|
out_path: Optional[str] = "",
|
|
45
45
|
workdir: Optional[str] = "",
|
|
46
46
|
artifact_path: Optional[str] = "",
|
|
@@ -48,16 +48,16 @@ class ClientRemoteLauncher(launcher.ClientBaseLauncher):
|
|
|
48
48
|
schedule: Optional[
|
|
49
49
|
Union[str, mlrun.common.schemas.schedule.ScheduleCronTrigger]
|
|
50
50
|
] = None,
|
|
51
|
-
hyperparams:
|
|
51
|
+
hyperparams: dict[str, list] = None,
|
|
52
52
|
hyper_param_options: Optional[mlrun.model.HyperParamOptions] = None,
|
|
53
53
|
verbose: Optional[bool] = None,
|
|
54
54
|
scrape_metrics: Optional[bool] = None,
|
|
55
55
|
local_code_path: Optional[str] = None,
|
|
56
56
|
auto_build: Optional[bool] = None,
|
|
57
|
-
param_file_secrets: Optional[
|
|
58
|
-
notifications: Optional[
|
|
59
|
-
returns: Optional[
|
|
60
|
-
state_thresholds: Optional[
|
|
57
|
+
param_file_secrets: Optional[dict[str, str]] = None,
|
|
58
|
+
notifications: Optional[list[mlrun.model.Notification]] = None,
|
|
59
|
+
returns: Optional[list[Union[str, dict[str, str]]]] = None,
|
|
60
|
+
state_thresholds: Optional[dict[str, int]] = None,
|
|
61
61
|
) -> "mlrun.run.RunObject":
|
|
62
62
|
self.enrich_runtime(runtime, project)
|
|
63
63
|
run = self._create_run_object(task)
|
mlrun/lists.py
CHANGED
|
@@ -12,7 +12,6 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
from copy import copy
|
|
15
|
-
from typing import List
|
|
16
15
|
|
|
17
16
|
import pandas as pd
|
|
18
17
|
|
|
@@ -119,7 +118,7 @@ class RunList(list):
|
|
|
119
118
|
if not display:
|
|
120
119
|
return html
|
|
121
120
|
|
|
122
|
-
def to_objects(self) ->
|
|
121
|
+
def to_objects(self) -> list["mlrun.RunObject"]:
|
|
123
122
|
"""Return a list of Run Objects"""
|
|
124
123
|
return [mlrun.RunObject.from_dict(run) for run in self]
|
|
125
124
|
|
|
@@ -215,11 +214,11 @@ class ArtifactList(list):
|
|
|
215
214
|
if not display:
|
|
216
215
|
return html
|
|
217
216
|
|
|
218
|
-
def to_objects(self) ->
|
|
217
|
+
def to_objects(self) -> list[Artifact]:
|
|
219
218
|
"""return as a list of artifact objects"""
|
|
220
219
|
return [dict_to_artifact(artifact) for artifact in self]
|
|
221
220
|
|
|
222
|
-
def dataitems(self) ->
|
|
221
|
+
def dataitems(self) -> list["mlrun.DataItem"]:
|
|
223
222
|
"""return as a list of DataItem objects"""
|
|
224
223
|
dataitems = []
|
|
225
224
|
for item in self:
|
mlrun/model.py
CHANGED
|
@@ -22,7 +22,7 @@ from collections import OrderedDict
|
|
|
22
22
|
from copy import deepcopy
|
|
23
23
|
from datetime import datetime
|
|
24
24
|
from os import environ
|
|
25
|
-
from typing import Any,
|
|
25
|
+
from typing import Any, Optional, Union
|
|
26
26
|
|
|
27
27
|
import pydantic.error_wrappers
|
|
28
28
|
|
|
@@ -44,6 +44,15 @@ RUN_ID_PLACE_HOLDER = "{run_id}" # IMPORTANT: shouldn't be changed.
|
|
|
44
44
|
|
|
45
45
|
class ModelObj:
|
|
46
46
|
_dict_fields = []
|
|
47
|
+
# Bellow attributes are used in to_dict method
|
|
48
|
+
# Fields to strip from the object by default if strip=True
|
|
49
|
+
_default_fields_to_strip = []
|
|
50
|
+
# Fields that will be serialized by the object's _serialize_field method
|
|
51
|
+
_fields_to_serialize = []
|
|
52
|
+
# Fields that will be enriched by the object's _enrich_field method
|
|
53
|
+
_fields_to_enrich = []
|
|
54
|
+
# Fields that will be ignored by the object's _is_valid_field_value_for_serialization method
|
|
55
|
+
_fields_to_skip_validation = []
|
|
47
56
|
|
|
48
57
|
@staticmethod
|
|
49
58
|
def _verify_list(param, name):
|
|
@@ -62,26 +71,145 @@ class ModelObj:
|
|
|
62
71
|
return new_type.from_dict(param)
|
|
63
72
|
return param
|
|
64
73
|
|
|
65
|
-
def to_dict(
|
|
66
|
-
|
|
74
|
+
def to_dict(
|
|
75
|
+
self, fields: list = None, exclude: list = None, strip: bool = False
|
|
76
|
+
) -> dict:
|
|
77
|
+
"""
|
|
78
|
+
Convert the object to a dict
|
|
79
|
+
|
|
80
|
+
:param fields: A list of fields to include in the dictionary. If not provided, the default value is taken
|
|
81
|
+
from `self._dict_fields` or from the object __init__ params.
|
|
82
|
+
:param exclude: A list of fields to exclude from the dictionary.
|
|
83
|
+
:param strip: If True, the object's `_default_fields_to_strip` attribute is appended to the exclude list.
|
|
84
|
+
Strip purpose is to remove fields that are context / environment specific and not required for actually
|
|
85
|
+
define the object.
|
|
67
86
|
|
|
68
|
-
:
|
|
69
|
-
:param exclude: list of fields to exclude from the dict
|
|
87
|
+
:return: A dictionary representation of the object.
|
|
70
88
|
"""
|
|
71
89
|
struct = {}
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
90
|
+
|
|
91
|
+
fields = self._resolve_initial_to_dict_fields(fields)
|
|
92
|
+
fields_to_exclude = exclude or []
|
|
93
|
+
if strip:
|
|
94
|
+
fields_to_exclude += self._default_fields_to_strip
|
|
95
|
+
|
|
96
|
+
# fields_to_save is built from the fields list minus the fields to exclude minus the fields that requires
|
|
97
|
+
# serialization and enrichment (because they will be added later to the struct)
|
|
98
|
+
fields_to_save = (
|
|
99
|
+
set(fields)
|
|
100
|
+
- set(fields_to_exclude)
|
|
101
|
+
- set(self._fields_to_serialize)
|
|
102
|
+
- set(self._fields_to_enrich)
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
# Iterating over the fields to save and adding them to the struct
|
|
106
|
+
for field_name in fields_to_save:
|
|
107
|
+
field_value = getattr(self, field_name, None)
|
|
108
|
+
if self._is_valid_field_value_for_serialization(
|
|
109
|
+
field_name, field_value, strip
|
|
110
|
+
):
|
|
111
|
+
# If the field value has attribute to_dict, we call it.
|
|
112
|
+
# If one of the attributes is a third party object that has to_dict method (such as k8s objects), then
|
|
113
|
+
# add it to the object's _fields_to_serialize attribute and handle it in the _serialize_field method.
|
|
114
|
+
if hasattr(field_value, "to_dict"):
|
|
115
|
+
field_value = field_value.to_dict(strip=strip)
|
|
116
|
+
if self._is_valid_field_value_for_serialization(
|
|
117
|
+
field_name, field_value, strip
|
|
118
|
+
):
|
|
119
|
+
struct[field_name] = field_value
|
|
120
|
+
else:
|
|
121
|
+
struct[field_name] = field_value
|
|
122
|
+
|
|
123
|
+
# Subtracting the fields_to_exclude from the fields_to_serialize because if we want to exclude a field there
|
|
124
|
+
# is no need to serialize it.
|
|
125
|
+
fields_to_serialize = list(
|
|
126
|
+
set(self._fields_to_serialize) - set(fields_to_exclude)
|
|
127
|
+
)
|
|
128
|
+
self._resolve_field_value_by_method(
|
|
129
|
+
struct, self._serialize_field, fields_to_serialize, strip
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
# Subtracting the fields_to_exclude from the fields_to_enrich because if we want to exclude a field there
|
|
133
|
+
# is no need to enrich it.
|
|
134
|
+
fields_to_enrich = list(set(self._fields_to_enrich) - set(fields_to_exclude))
|
|
135
|
+
self._resolve_field_value_by_method(
|
|
136
|
+
struct, self._enrich_field, fields_to_enrich, strip
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
self._apply_enrichment_before_to_dict_completion(struct, strip=strip)
|
|
140
|
+
return struct
|
|
141
|
+
|
|
142
|
+
def _resolve_initial_to_dict_fields(self, fields: list = None) -> list:
|
|
143
|
+
"""
|
|
144
|
+
Resolve fields to be used in to_dict method.
|
|
145
|
+
If fields is None, use `_dict_fields` attribute of the object.
|
|
146
|
+
If fields is None and `_dict_fields` is empty, use the object's __init__ parameters.
|
|
147
|
+
:param fields: List of fields to iterate over.
|
|
148
|
+
|
|
149
|
+
:return: List of fields to iterate over.
|
|
150
|
+
"""
|
|
151
|
+
return (
|
|
152
|
+
fields
|
|
153
|
+
or self._dict_fields
|
|
154
|
+
or list(inspect.signature(self.__init__).parameters.keys())
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
def _is_valid_field_value_for_serialization(
|
|
158
|
+
self, field_name: str, field_value: str, strip: bool = False
|
|
159
|
+
) -> bool:
|
|
160
|
+
"""
|
|
161
|
+
Check if the field value is valid for serialization.
|
|
162
|
+
If field name is in `_fields_to_skip_validation` attribute, skip validation and return True.
|
|
163
|
+
If strip is False skip validation and return True.
|
|
164
|
+
If field value is None or empty dict/list, then no need to store it.
|
|
165
|
+
:param field_name: Field name.
|
|
166
|
+
:param field_value: Field value.
|
|
167
|
+
|
|
168
|
+
:return: True if the field value is valid for serialization, False otherwise.
|
|
169
|
+
"""
|
|
170
|
+
if field_name in self._fields_to_skip_validation:
|
|
171
|
+
return True
|
|
172
|
+
# TODO: remove when Runtime initialization will be refactored and enrichment will be moved to BE
|
|
173
|
+
# if not strip:
|
|
174
|
+
# return True
|
|
175
|
+
|
|
176
|
+
return field_value is not None and not (
|
|
177
|
+
(isinstance(field_value, dict) or isinstance(field_value, list))
|
|
178
|
+
and not field_value
|
|
179
|
+
)
|
|
180
|
+
|
|
181
|
+
def _resolve_field_value_by_method(
|
|
182
|
+
self,
|
|
183
|
+
struct: dict,
|
|
184
|
+
method: typing.Callable,
|
|
185
|
+
fields: typing.Union[list, set] = None,
|
|
186
|
+
strip: bool = False,
|
|
187
|
+
) -> dict:
|
|
188
|
+
for field_name in fields:
|
|
189
|
+
field_value = method(struct=struct, field_name=field_name, strip=strip)
|
|
190
|
+
if self._is_valid_field_value_for_serialization(
|
|
191
|
+
field_name, field_value, strip
|
|
192
|
+
):
|
|
193
|
+
struct[field_name] = field_value
|
|
194
|
+
return struct
|
|
195
|
+
|
|
196
|
+
def _serialize_field(
|
|
197
|
+
self, struct: dict, field_name: str = None, strip: bool = False
|
|
198
|
+
) -> typing.Any:
|
|
199
|
+
# We pull the field from self and not from struct because it was excluded from the struct when looping over
|
|
200
|
+
# the fields to save.
|
|
201
|
+
return getattr(self, field_name, None)
|
|
202
|
+
|
|
203
|
+
def _enrich_field(
|
|
204
|
+
self, struct: dict, field_name: str = None, strip: bool = False
|
|
205
|
+
) -> typing.Any:
|
|
206
|
+
# We first try to pull from struct because the field might have been already serialized and if not,
|
|
207
|
+
# we pull from self
|
|
208
|
+
return struct.get(field_name, None) or getattr(self, field_name, None)
|
|
209
|
+
|
|
210
|
+
def _apply_enrichment_before_to_dict_completion(
|
|
211
|
+
self, struct: dict, strip: bool = False
|
|
212
|
+
) -> dict:
|
|
85
213
|
return struct
|
|
86
214
|
|
|
87
215
|
@classmethod
|
|
@@ -110,19 +238,21 @@ class ModelObj:
|
|
|
110
238
|
|
|
111
239
|
return new_obj
|
|
112
240
|
|
|
113
|
-
def to_yaml(self, exclude=None) -> str:
|
|
241
|
+
def to_yaml(self, exclude=None, strip: bool = False) -> str:
|
|
114
242
|
"""convert the object to yaml
|
|
115
243
|
|
|
116
244
|
:param exclude: list of fields to exclude from the yaml
|
|
245
|
+
:param strip: if True, strip fields that are not required for actually define the object
|
|
117
246
|
"""
|
|
118
|
-
return dict_to_yaml(self.to_dict(exclude=exclude))
|
|
247
|
+
return dict_to_yaml(self.to_dict(exclude=exclude, strip=strip))
|
|
119
248
|
|
|
120
|
-
def to_json(self, exclude=None):
|
|
249
|
+
def to_json(self, exclude=None, strip: bool = False):
|
|
121
250
|
"""convert the object to json
|
|
122
251
|
|
|
123
252
|
:param exclude: list of fields to exclude from the json
|
|
253
|
+
:param strip: if True, strip fields that are not required for actually define the object
|
|
124
254
|
"""
|
|
125
|
-
return dict_to_json(self.to_dict(exclude=exclude))
|
|
255
|
+
return dict_to_json(self.to_dict(exclude=exclude, strip=strip))
|
|
126
256
|
|
|
127
257
|
def to_str(self):
|
|
128
258
|
"""convert the object to string (with dict layout)"""
|
|
@@ -174,8 +304,8 @@ class ObjectDict:
|
|
|
174
304
|
self._children[key] = child
|
|
175
305
|
return child
|
|
176
306
|
|
|
177
|
-
def to_dict(self):
|
|
178
|
-
return {k: v.to_dict() for k, v in self._children.items()}
|
|
307
|
+
def to_dict(self, strip: bool = False):
|
|
308
|
+
return {k: v.to_dict(strip=strip) for k, v in self._children.items()}
|
|
179
309
|
|
|
180
310
|
@classmethod
|
|
181
311
|
def from_dict(cls, classes_map: dict, children=None, default_kind=""):
|
|
@@ -257,9 +387,9 @@ class ObjectList:
|
|
|
257
387
|
def __delitem__(self, key):
|
|
258
388
|
del self._children[key]
|
|
259
389
|
|
|
260
|
-
def to_dict(self):
|
|
390
|
+
def to_dict(self, strip: bool = False):
|
|
261
391
|
# method used by ModelObj class to serialize the object to nested dict
|
|
262
|
-
return [t.to_dict() for t in self._children.values()]
|
|
392
|
+
return [t.to_dict(strip=strip) for t in self._children.values()]
|
|
263
393
|
|
|
264
394
|
@classmethod
|
|
265
395
|
def from_list(cls, child_class, children=None):
|
|
@@ -304,6 +434,18 @@ class Credentials(ModelObj):
|
|
|
304
434
|
|
|
305
435
|
|
|
306
436
|
class BaseMetadata(ModelObj):
|
|
437
|
+
_default_fields_to_strip = ModelObj._default_fields_to_strip + [
|
|
438
|
+
"hash",
|
|
439
|
+
# Below are environment specific fields, no need to keep when stripping
|
|
440
|
+
"namespace",
|
|
441
|
+
"project",
|
|
442
|
+
"labels",
|
|
443
|
+
"annotations",
|
|
444
|
+
"credentials",
|
|
445
|
+
# Below are state fields, no need to keep when stripping
|
|
446
|
+
"updated",
|
|
447
|
+
]
|
|
448
|
+
|
|
307
449
|
def __init__(
|
|
308
450
|
self,
|
|
309
451
|
name=None,
|
|
@@ -443,7 +585,7 @@ class ImageBuilder(ModelObj):
|
|
|
443
585
|
|
|
444
586
|
def with_commands(
|
|
445
587
|
self,
|
|
446
|
-
commands:
|
|
588
|
+
commands: list[str],
|
|
447
589
|
overwrite: bool = False,
|
|
448
590
|
):
|
|
449
591
|
"""add commands to build spec.
|
|
@@ -470,7 +612,7 @@ class ImageBuilder(ModelObj):
|
|
|
470
612
|
|
|
471
613
|
def with_requirements(
|
|
472
614
|
self,
|
|
473
|
-
requirements: Optional[
|
|
615
|
+
requirements: Optional[list[str]] = None,
|
|
474
616
|
requirements_file: str = "",
|
|
475
617
|
overwrite: bool = False,
|
|
476
618
|
):
|
|
@@ -503,7 +645,7 @@ class ImageBuilder(ModelObj):
|
|
|
503
645
|
|
|
504
646
|
# handle the requirements_file argument
|
|
505
647
|
if requirements_file:
|
|
506
|
-
with open(requirements_file
|
|
648
|
+
with open(requirements_file) as fp:
|
|
507
649
|
requirements_to_resolve.extend(fp.read().splitlines())
|
|
508
650
|
|
|
509
651
|
# handle the requirements argument
|
|
@@ -582,7 +724,7 @@ class Notification(ModelObj):
|
|
|
582
724
|
)
|
|
583
725
|
|
|
584
726
|
@staticmethod
|
|
585
|
-
def validate_notification_uniqueness(notifications:
|
|
727
|
+
def validate_notification_uniqueness(notifications: list["Notification"]):
|
|
586
728
|
"""Validate that all notifications in the list are unique by name"""
|
|
587
729
|
names = [notification.name for notification in notifications]
|
|
588
730
|
if len(names) != len(set(names)):
|
|
@@ -686,6 +828,10 @@ class HyperParamOptions(ModelObj):
|
|
|
686
828
|
class RunSpec(ModelObj):
|
|
687
829
|
"""Run specification"""
|
|
688
830
|
|
|
831
|
+
_fields_to_serialize = ModelObj._fields_to_serialize + [
|
|
832
|
+
"handler",
|
|
833
|
+
]
|
|
834
|
+
|
|
689
835
|
def __init__(
|
|
690
836
|
self,
|
|
691
837
|
parameters=None,
|
|
@@ -746,18 +892,22 @@ class RunSpec(ModelObj):
|
|
|
746
892
|
self._notifications = notifications or []
|
|
747
893
|
self.state_thresholds = state_thresholds or {}
|
|
748
894
|
|
|
749
|
-
def
|
|
750
|
-
struct =
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
895
|
+
def _serialize_field(
|
|
896
|
+
self, struct: dict, field_name: str = None, strip: bool = False
|
|
897
|
+
) -> Optional[str]:
|
|
898
|
+
# We pull the field from self and not from struct because it was excluded from the struct
|
|
899
|
+
if field_name == "handler":
|
|
900
|
+
if self.handler and isinstance(self.handler, str):
|
|
901
|
+
return self.handler
|
|
902
|
+
return None
|
|
903
|
+
return super()._serialize_field(struct, field_name, strip)
|
|
754
904
|
|
|
755
905
|
def is_hyper_job(self):
|
|
756
906
|
param_file = self.param_file or self.hyper_param_options.param_file
|
|
757
907
|
return param_file or self.hyperparams
|
|
758
908
|
|
|
759
909
|
@property
|
|
760
|
-
def inputs(self) ->
|
|
910
|
+
def inputs(self) -> dict[str, str]:
|
|
761
911
|
"""
|
|
762
912
|
Get the inputs dictionary. A dictionary of parameter names as keys and paths as values.
|
|
763
913
|
|
|
@@ -766,7 +916,7 @@ class RunSpec(ModelObj):
|
|
|
766
916
|
return self._inputs
|
|
767
917
|
|
|
768
918
|
@inputs.setter
|
|
769
|
-
def inputs(self, inputs:
|
|
919
|
+
def inputs(self, inputs: dict[str, str]):
|
|
770
920
|
"""
|
|
771
921
|
Set the given inputs in the spec. Inputs can include a type hint string in their keys following a colon, meaning
|
|
772
922
|
following this structure: "<input key : type hint>".
|
|
@@ -789,7 +939,7 @@ class RunSpec(ModelObj):
|
|
|
789
939
|
self._inputs = self._verify_dict(inputs, "inputs")
|
|
790
940
|
|
|
791
941
|
@property
|
|
792
|
-
def inputs_type_hints(self) ->
|
|
942
|
+
def inputs_type_hints(self) -> dict[str, str]:
|
|
793
943
|
"""
|
|
794
944
|
Get the input type hints. A dictionary of parameter names as keys and their type hints as values.
|
|
795
945
|
|
|
@@ -798,7 +948,7 @@ class RunSpec(ModelObj):
|
|
|
798
948
|
return self._inputs_type_hints
|
|
799
949
|
|
|
800
950
|
@inputs_type_hints.setter
|
|
801
|
-
def inputs_type_hints(self, inputs_type_hints:
|
|
951
|
+
def inputs_type_hints(self, inputs_type_hints: dict[str, str]):
|
|
802
952
|
"""
|
|
803
953
|
Set the inputs type hints to parse during a run.
|
|
804
954
|
|
|
@@ -819,7 +969,7 @@ class RunSpec(ModelObj):
|
|
|
819
969
|
return self._returns
|
|
820
970
|
|
|
821
971
|
@returns.setter
|
|
822
|
-
def returns(self, returns:
|
|
972
|
+
def returns(self, returns: list[Union[str, dict[str, str]]]):
|
|
823
973
|
"""
|
|
824
974
|
Set the returns list to log the returning values at the end of a run.
|
|
825
975
|
|
|
@@ -853,7 +1003,7 @@ class RunSpec(ModelObj):
|
|
|
853
1003
|
)
|
|
854
1004
|
|
|
855
1005
|
@property
|
|
856
|
-
def outputs(self) ->
|
|
1006
|
+
def outputs(self) -> list[str]:
|
|
857
1007
|
"""
|
|
858
1008
|
Get the expected outputs. The list is constructed from keys of both the `outputs` and `returns` properties.
|
|
859
1009
|
|
|
@@ -918,7 +1068,7 @@ class RunSpec(ModelObj):
|
|
|
918
1068
|
return self._state_thresholds
|
|
919
1069
|
|
|
920
1070
|
@state_thresholds.setter
|
|
921
|
-
def state_thresholds(self, state_thresholds:
|
|
1071
|
+
def state_thresholds(self, state_thresholds: dict[str, str]):
|
|
922
1072
|
"""
|
|
923
1073
|
Set the dictionary of k8s resource states to thresholds time strings.
|
|
924
1074
|
The state will be matched against the pod's status. The threshold should be a time string that conforms
|
|
@@ -970,8 +1120,8 @@ class RunSpec(ModelObj):
|
|
|
970
1120
|
|
|
971
1121
|
@staticmethod
|
|
972
1122
|
def join_outputs_and_returns(
|
|
973
|
-
outputs:
|
|
974
|
-
) ->
|
|
1123
|
+
outputs: list[str], returns: list[Union[str, dict[str, str]]]
|
|
1124
|
+
) -> list[str]:
|
|
975
1125
|
"""
|
|
976
1126
|
Get the outputs set in the spec. The outputs are constructed from both the 'outputs' and 'returns' properties
|
|
977
1127
|
that were set by the user.
|
|
@@ -1002,7 +1152,7 @@ class RunSpec(ModelObj):
|
|
|
1002
1152
|
return outputs
|
|
1003
1153
|
|
|
1004
1154
|
@staticmethod
|
|
1005
|
-
def _separate_type_hint_from_input_key(input_key: str) ->
|
|
1155
|
+
def _separate_type_hint_from_input_key(input_key: str) -> tuple[str, str]:
|
|
1006
1156
|
"""
|
|
1007
1157
|
An input key in the `inputs` dictionary parameter of a task (or `Runtime.run` method) or the docs setting of a
|
|
1008
1158
|
`Runtime` handler can be provided with a colon to specify its type hint in the following structure:
|
|
@@ -1046,7 +1196,7 @@ class RunStatus(ModelObj):
|
|
|
1046
1196
|
iterations=None,
|
|
1047
1197
|
ui_url=None,
|
|
1048
1198
|
reason: str = None,
|
|
1049
|
-
notifications:
|
|
1199
|
+
notifications: dict[str, Notification] = None,
|
|
1050
1200
|
):
|
|
1051
1201
|
self.state = state or "created"
|
|
1052
1202
|
self.status_text = status_text
|
|
@@ -1291,7 +1441,7 @@ class RunObject(RunTemplate):
|
|
|
1291
1441
|
"""UI URL (for relevant runtimes)"""
|
|
1292
1442
|
self.refresh()
|
|
1293
1443
|
if not self._status.ui_url:
|
|
1294
|
-
print("UI currently not available (status={
|
|
1444
|
+
print(f"UI currently not available (status={self._status.state})")
|
|
1295
1445
|
return self._status.ui_url
|
|
1296
1446
|
|
|
1297
1447
|
@property
|
|
@@ -1454,7 +1604,7 @@ class RunObject(RunTemplate):
|
|
|
1454
1604
|
return f"{project}@{uid}#{iteration}{tag}"
|
|
1455
1605
|
|
|
1456
1606
|
@staticmethod
|
|
1457
|
-
def parse_uri(uri: str) ->
|
|
1607
|
+
def parse_uri(uri: str) -> tuple[str, str, str, str]:
|
|
1458
1608
|
uri_pattern = (
|
|
1459
1609
|
r"^(?P<project>.*)@(?P<uid>.*)\#(?P<iteration>.*?)(:(?P<tag>.*))?$"
|
|
1460
1610
|
)
|
|
@@ -1675,7 +1825,7 @@ class DataSource(ModelObj):
|
|
|
1675
1825
|
self,
|
|
1676
1826
|
name: str = None,
|
|
1677
1827
|
path: str = None,
|
|
1678
|
-
attributes:
|
|
1828
|
+
attributes: dict[str, object] = None,
|
|
1679
1829
|
key_field: str = None,
|
|
1680
1830
|
time_field: str = None,
|
|
1681
1831
|
schedule: str = None,
|
|
@@ -1741,16 +1891,16 @@ class DataTargetBase(ModelObj):
|
|
|
1741
1891
|
kind: str = None,
|
|
1742
1892
|
name: str = "",
|
|
1743
1893
|
path=None,
|
|
1744
|
-
attributes:
|
|
1894
|
+
attributes: dict[str, str] = None,
|
|
1745
1895
|
after_step=None,
|
|
1746
1896
|
partitioned: bool = False,
|
|
1747
1897
|
key_bucketing_number: Optional[int] = None,
|
|
1748
|
-
partition_cols: Optional[
|
|
1898
|
+
partition_cols: Optional[list[str]] = None,
|
|
1749
1899
|
time_partitioning_granularity: Optional[str] = None,
|
|
1750
1900
|
max_events: Optional[int] = None,
|
|
1751
1901
|
flush_after_seconds: Optional[int] = None,
|
|
1752
|
-
storage_options:
|
|
1753
|
-
schema:
|
|
1902
|
+
storage_options: dict[str, str] = None,
|
|
1903
|
+
schema: dict[str, Any] = None,
|
|
1754
1904
|
credentials_prefix=None,
|
|
1755
1905
|
):
|
|
1756
1906
|
self.name = name
|
|
@@ -1837,8 +1987,8 @@ class VersionedObjMetadata(ModelObj):
|
|
|
1837
1987
|
tag: str = None,
|
|
1838
1988
|
uid: str = None,
|
|
1839
1989
|
project: str = None,
|
|
1840
|
-
labels:
|
|
1841
|
-
annotations:
|
|
1990
|
+
labels: dict[str, str] = None,
|
|
1991
|
+
annotations: dict[str, str] = None,
|
|
1842
1992
|
updated=None,
|
|
1843
1993
|
):
|
|
1844
1994
|
self.name = name
|