mlrun 1.7.2rc3__py3-none-any.whl → 1.8.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of mlrun might be problematic. Click here for more details.
- mlrun/__init__.py +26 -22
- mlrun/__main__.py +15 -16
- mlrun/alerts/alert.py +150 -15
- mlrun/api/schemas/__init__.py +1 -9
- mlrun/artifacts/__init__.py +2 -3
- mlrun/artifacts/base.py +62 -19
- mlrun/artifacts/dataset.py +17 -17
- mlrun/artifacts/document.py +454 -0
- mlrun/artifacts/manager.py +28 -18
- mlrun/artifacts/model.py +91 -59
- mlrun/artifacts/plots.py +2 -2
- mlrun/common/constants.py +8 -0
- mlrun/common/formatters/__init__.py +1 -0
- mlrun/common/formatters/artifact.py +1 -1
- mlrun/common/formatters/feature_set.py +2 -0
- mlrun/common/formatters/function.py +1 -0
- mlrun/{model_monitoring/db/stores/v3io_kv/__init__.py → common/formatters/model_endpoint.py} +17 -0
- mlrun/common/formatters/pipeline.py +1 -2
- mlrun/common/formatters/project.py +9 -0
- mlrun/common/model_monitoring/__init__.py +0 -5
- mlrun/common/model_monitoring/helpers.py +12 -62
- mlrun/common/runtimes/constants.py +25 -4
- mlrun/common/schemas/__init__.py +9 -5
- mlrun/common/schemas/alert.py +114 -19
- mlrun/common/schemas/api_gateway.py +3 -3
- mlrun/common/schemas/artifact.py +22 -9
- mlrun/common/schemas/auth.py +8 -4
- mlrun/common/schemas/background_task.py +7 -7
- mlrun/common/schemas/client_spec.py +4 -4
- mlrun/common/schemas/clusterization_spec.py +2 -2
- mlrun/common/schemas/common.py +53 -3
- mlrun/common/schemas/constants.py +15 -0
- mlrun/common/schemas/datastore_profile.py +1 -1
- mlrun/common/schemas/feature_store.py +9 -9
- mlrun/common/schemas/frontend_spec.py +4 -4
- mlrun/common/schemas/function.py +10 -10
- mlrun/common/schemas/hub.py +1 -1
- mlrun/common/schemas/k8s.py +3 -3
- mlrun/common/schemas/memory_reports.py +3 -3
- mlrun/common/schemas/model_monitoring/__init__.py +4 -8
- mlrun/common/schemas/model_monitoring/constants.py +127 -46
- mlrun/common/schemas/model_monitoring/grafana.py +18 -12
- mlrun/common/schemas/model_monitoring/model_endpoints.py +154 -160
- mlrun/common/schemas/notification.py +24 -3
- mlrun/common/schemas/object.py +1 -1
- mlrun/common/schemas/pagination.py +4 -4
- mlrun/common/schemas/partition.py +142 -0
- mlrun/common/schemas/pipeline.py +3 -3
- mlrun/common/schemas/project.py +26 -18
- mlrun/common/schemas/runs.py +3 -3
- mlrun/common/schemas/runtime_resource.py +5 -5
- mlrun/common/schemas/schedule.py +1 -1
- mlrun/common/schemas/secret.py +1 -1
- mlrun/{model_monitoring/db/stores/sqldb/__init__.py → common/schemas/serving.py} +10 -1
- mlrun/common/schemas/tag.py +3 -3
- mlrun/common/schemas/workflow.py +6 -5
- mlrun/common/types.py +1 -0
- mlrun/config.py +157 -89
- mlrun/data_types/__init__.py +5 -3
- mlrun/data_types/infer.py +13 -3
- mlrun/data_types/spark.py +2 -1
- mlrun/datastore/__init__.py +59 -18
- mlrun/datastore/alibaba_oss.py +4 -1
- mlrun/datastore/azure_blob.py +4 -1
- mlrun/datastore/base.py +19 -24
- mlrun/datastore/datastore.py +10 -4
- mlrun/datastore/datastore_profile.py +178 -45
- mlrun/datastore/dbfs_store.py +4 -1
- mlrun/datastore/filestore.py +4 -1
- mlrun/datastore/google_cloud_storage.py +4 -1
- mlrun/datastore/hdfs.py +4 -1
- mlrun/datastore/inmem.py +4 -1
- mlrun/datastore/redis.py +4 -1
- mlrun/datastore/s3.py +14 -3
- mlrun/datastore/sources.py +89 -92
- mlrun/datastore/store_resources.py +7 -4
- mlrun/datastore/storeytargets.py +51 -16
- mlrun/datastore/targets.py +38 -31
- mlrun/datastore/utils.py +87 -4
- mlrun/datastore/v3io.py +4 -1
- mlrun/datastore/vectorstore.py +291 -0
- mlrun/datastore/wasbfs/fs.py +13 -12
- mlrun/db/base.py +286 -100
- mlrun/db/httpdb.py +1562 -490
- mlrun/db/nopdb.py +250 -83
- mlrun/errors.py +6 -2
- mlrun/execution.py +194 -50
- mlrun/feature_store/__init__.py +2 -10
- mlrun/feature_store/api.py +20 -458
- mlrun/feature_store/common.py +9 -9
- mlrun/feature_store/feature_set.py +20 -18
- mlrun/feature_store/feature_vector.py +105 -479
- mlrun/feature_store/feature_vector_utils.py +466 -0
- mlrun/feature_store/retrieval/base.py +15 -11
- mlrun/feature_store/retrieval/job.py +2 -1
- mlrun/feature_store/retrieval/storey_merger.py +1 -1
- mlrun/feature_store/steps.py +3 -3
- mlrun/features.py +30 -13
- mlrun/frameworks/__init__.py +1 -2
- mlrun/frameworks/_common/__init__.py +1 -2
- mlrun/frameworks/_common/artifacts_library.py +2 -2
- mlrun/frameworks/_common/mlrun_interface.py +10 -6
- mlrun/frameworks/_common/model_handler.py +31 -31
- mlrun/frameworks/_common/producer.py +3 -1
- mlrun/frameworks/_dl_common/__init__.py +1 -2
- mlrun/frameworks/_dl_common/loggers/__init__.py +1 -2
- mlrun/frameworks/_dl_common/loggers/mlrun_logger.py +4 -4
- mlrun/frameworks/_dl_common/loggers/tensorboard_logger.py +3 -3
- mlrun/frameworks/_ml_common/__init__.py +1 -2
- mlrun/frameworks/_ml_common/loggers/__init__.py +1 -2
- mlrun/frameworks/_ml_common/model_handler.py +21 -21
- mlrun/frameworks/_ml_common/plans/__init__.py +1 -2
- mlrun/frameworks/_ml_common/plans/confusion_matrix_plan.py +3 -1
- mlrun/frameworks/_ml_common/plans/dataset_plan.py +3 -3
- mlrun/frameworks/_ml_common/plans/roc_curve_plan.py +4 -4
- mlrun/frameworks/auto_mlrun/__init__.py +1 -2
- mlrun/frameworks/auto_mlrun/auto_mlrun.py +22 -15
- mlrun/frameworks/huggingface/__init__.py +1 -2
- mlrun/frameworks/huggingface/model_server.py +9 -9
- mlrun/frameworks/lgbm/__init__.py +47 -44
- mlrun/frameworks/lgbm/callbacks/__init__.py +1 -2
- mlrun/frameworks/lgbm/callbacks/logging_callback.py +4 -2
- mlrun/frameworks/lgbm/callbacks/mlrun_logging_callback.py +4 -2
- mlrun/frameworks/lgbm/mlrun_interfaces/__init__.py +1 -2
- mlrun/frameworks/lgbm/mlrun_interfaces/mlrun_interface.py +5 -5
- mlrun/frameworks/lgbm/model_handler.py +15 -11
- mlrun/frameworks/lgbm/model_server.py +11 -7
- mlrun/frameworks/lgbm/utils.py +2 -2
- mlrun/frameworks/onnx/__init__.py +1 -2
- mlrun/frameworks/onnx/dataset.py +3 -3
- mlrun/frameworks/onnx/mlrun_interface.py +2 -2
- mlrun/frameworks/onnx/model_handler.py +7 -5
- mlrun/frameworks/onnx/model_server.py +8 -6
- mlrun/frameworks/parallel_coordinates.py +11 -11
- mlrun/frameworks/pytorch/__init__.py +22 -23
- mlrun/frameworks/pytorch/callbacks/__init__.py +1 -2
- mlrun/frameworks/pytorch/callbacks/callback.py +2 -1
- mlrun/frameworks/pytorch/callbacks/logging_callback.py +15 -8
- mlrun/frameworks/pytorch/callbacks/mlrun_logging_callback.py +19 -12
- mlrun/frameworks/pytorch/callbacks/tensorboard_logging_callback.py +22 -15
- mlrun/frameworks/pytorch/callbacks_handler.py +36 -30
- mlrun/frameworks/pytorch/mlrun_interface.py +17 -17
- mlrun/frameworks/pytorch/model_handler.py +21 -17
- mlrun/frameworks/pytorch/model_server.py +13 -9
- mlrun/frameworks/sklearn/__init__.py +19 -18
- mlrun/frameworks/sklearn/estimator.py +2 -2
- mlrun/frameworks/sklearn/metric.py +3 -3
- mlrun/frameworks/sklearn/metrics_library.py +8 -6
- mlrun/frameworks/sklearn/mlrun_interface.py +3 -2
- mlrun/frameworks/sklearn/model_handler.py +4 -3
- mlrun/frameworks/tf_keras/__init__.py +11 -12
- mlrun/frameworks/tf_keras/callbacks/__init__.py +1 -2
- mlrun/frameworks/tf_keras/callbacks/logging_callback.py +17 -14
- mlrun/frameworks/tf_keras/callbacks/mlrun_logging_callback.py +15 -12
- mlrun/frameworks/tf_keras/callbacks/tensorboard_logging_callback.py +21 -18
- mlrun/frameworks/tf_keras/model_handler.py +17 -13
- mlrun/frameworks/tf_keras/model_server.py +12 -8
- mlrun/frameworks/xgboost/__init__.py +19 -18
- mlrun/frameworks/xgboost/model_handler.py +13 -9
- mlrun/k8s_utils.py +2 -5
- mlrun/launcher/base.py +3 -4
- mlrun/launcher/client.py +2 -2
- mlrun/launcher/local.py +6 -2
- mlrun/launcher/remote.py +1 -1
- mlrun/lists.py +8 -4
- mlrun/model.py +132 -46
- mlrun/model_monitoring/__init__.py +3 -5
- mlrun/model_monitoring/api.py +113 -98
- mlrun/model_monitoring/applications/__init__.py +0 -5
- mlrun/model_monitoring/applications/_application_steps.py +81 -50
- mlrun/model_monitoring/applications/base.py +467 -14
- mlrun/model_monitoring/applications/context.py +212 -134
- mlrun/model_monitoring/{db/stores/base → applications/evidently}/__init__.py +6 -2
- mlrun/model_monitoring/applications/evidently/base.py +146 -0
- mlrun/model_monitoring/applications/histogram_data_drift.py +89 -56
- mlrun/model_monitoring/applications/results.py +67 -15
- mlrun/model_monitoring/controller.py +701 -315
- mlrun/model_monitoring/db/__init__.py +0 -2
- mlrun/model_monitoring/db/_schedules.py +242 -0
- mlrun/model_monitoring/db/_stats.py +189 -0
- mlrun/model_monitoring/db/tsdb/__init__.py +33 -22
- mlrun/model_monitoring/db/tsdb/base.py +243 -49
- mlrun/model_monitoring/db/tsdb/tdengine/schemas.py +76 -36
- mlrun/model_monitoring/db/tsdb/tdengine/stream_graph_steps.py +33 -0
- mlrun/model_monitoring/db/tsdb/tdengine/tdengine_connection.py +213 -0
- mlrun/model_monitoring/db/tsdb/tdengine/tdengine_connector.py +534 -88
- mlrun/model_monitoring/db/tsdb/v3io/stream_graph_steps.py +1 -0
- mlrun/model_monitoring/db/tsdb/v3io/v3io_connector.py +436 -106
- mlrun/model_monitoring/helpers.py +356 -114
- mlrun/model_monitoring/stream_processing.py +190 -345
- mlrun/model_monitoring/tracking_policy.py +11 -4
- mlrun/model_monitoring/writer.py +49 -90
- mlrun/package/__init__.py +3 -6
- mlrun/package/context_handler.py +2 -2
- mlrun/package/packager.py +12 -9
- mlrun/package/packagers/__init__.py +0 -2
- mlrun/package/packagers/default_packager.py +14 -11
- mlrun/package/packagers/numpy_packagers.py +16 -7
- mlrun/package/packagers/pandas_packagers.py +18 -18
- mlrun/package/packagers/python_standard_library_packagers.py +25 -11
- mlrun/package/packagers_manager.py +35 -32
- mlrun/package/utils/__init__.py +0 -3
- mlrun/package/utils/_pickler.py +6 -6
- mlrun/platforms/__init__.py +47 -16
- mlrun/platforms/iguazio.py +4 -1
- mlrun/projects/operations.py +30 -30
- mlrun/projects/pipelines.py +116 -47
- mlrun/projects/project.py +1292 -329
- mlrun/render.py +5 -9
- mlrun/run.py +57 -14
- mlrun/runtimes/__init__.py +1 -3
- mlrun/runtimes/base.py +30 -22
- mlrun/runtimes/daskjob.py +9 -9
- mlrun/runtimes/databricks_job/databricks_runtime.py +6 -5
- mlrun/runtimes/function_reference.py +5 -2
- mlrun/runtimes/generators.py +3 -2
- mlrun/runtimes/kubejob.py +6 -7
- mlrun/runtimes/mounts.py +574 -0
- mlrun/runtimes/mpijob/__init__.py +0 -2
- mlrun/runtimes/mpijob/abstract.py +7 -6
- mlrun/runtimes/nuclio/api_gateway.py +7 -7
- mlrun/runtimes/nuclio/application/application.py +11 -13
- mlrun/runtimes/nuclio/application/reverse_proxy.go +66 -64
- mlrun/runtimes/nuclio/function.py +127 -70
- mlrun/runtimes/nuclio/serving.py +105 -37
- mlrun/runtimes/pod.py +159 -54
- mlrun/runtimes/remotesparkjob.py +3 -2
- mlrun/runtimes/sparkjob/__init__.py +0 -2
- mlrun/runtimes/sparkjob/spark3job.py +22 -12
- mlrun/runtimes/utils.py +7 -6
- mlrun/secrets.py +2 -2
- mlrun/serving/__init__.py +8 -0
- mlrun/serving/merger.py +7 -5
- mlrun/serving/remote.py +35 -22
- mlrun/serving/routers.py +186 -240
- mlrun/serving/server.py +41 -10
- mlrun/serving/states.py +432 -118
- mlrun/serving/utils.py +13 -2
- mlrun/serving/v1_serving.py +3 -2
- mlrun/serving/v2_serving.py +161 -203
- mlrun/track/__init__.py +1 -1
- mlrun/track/tracker.py +2 -2
- mlrun/track/trackers/mlflow_tracker.py +6 -5
- mlrun/utils/async_http.py +35 -22
- mlrun/utils/clones.py +7 -4
- mlrun/utils/helpers.py +511 -58
- mlrun/utils/logger.py +119 -13
- mlrun/utils/notifications/notification/__init__.py +22 -19
- mlrun/utils/notifications/notification/base.py +39 -15
- mlrun/utils/notifications/notification/console.py +6 -6
- mlrun/utils/notifications/notification/git.py +11 -11
- mlrun/utils/notifications/notification/ipython.py +10 -9
- mlrun/utils/notifications/notification/mail.py +176 -0
- mlrun/utils/notifications/notification/slack.py +16 -8
- mlrun/utils/notifications/notification/webhook.py +24 -8
- mlrun/utils/notifications/notification_pusher.py +191 -200
- mlrun/utils/regex.py +12 -2
- mlrun/utils/version/version.json +2 -2
- {mlrun-1.7.2rc3.dist-info → mlrun-1.8.0.dist-info}/METADATA +81 -54
- mlrun-1.8.0.dist-info/RECORD +351 -0
- {mlrun-1.7.2rc3.dist-info → mlrun-1.8.0.dist-info}/WHEEL +1 -1
- mlrun/model_monitoring/applications/evidently_base.py +0 -137
- mlrun/model_monitoring/db/stores/__init__.py +0 -136
- mlrun/model_monitoring/db/stores/base/store.py +0 -213
- mlrun/model_monitoring/db/stores/sqldb/models/__init__.py +0 -71
- mlrun/model_monitoring/db/stores/sqldb/models/base.py +0 -190
- mlrun/model_monitoring/db/stores/sqldb/models/mysql.py +0 -103
- mlrun/model_monitoring/db/stores/sqldb/models/sqlite.py +0 -40
- mlrun/model_monitoring/db/stores/sqldb/sql_store.py +0 -659
- mlrun/model_monitoring/db/stores/v3io_kv/kv_store.py +0 -726
- mlrun/model_monitoring/model_endpoint.py +0 -118
- mlrun-1.7.2rc3.dist-info/RECORD +0 -351
- {mlrun-1.7.2rc3.dist-info → mlrun-1.8.0.dist-info}/entry_points.txt +0 -0
- {mlrun-1.7.2rc3.dist-info → mlrun-1.8.0.dist-info/licenses}/LICENSE +0 -0
- {mlrun-1.7.2rc3.dist-info → mlrun-1.8.0.dist-info}/top_level.txt +0 -0
|
@@ -11,9 +11,8 @@
|
|
|
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
|
-
|
|
15
|
-
|
|
16
|
-
from typing import Union
|
|
14
|
+
|
|
15
|
+
from typing import Optional, Union
|
|
17
16
|
|
|
18
17
|
import xgboost as xgb
|
|
19
18
|
|
|
@@ -34,26 +33,28 @@ def apply_mlrun(
|
|
|
34
33
|
model: xgb.XGBModel = None,
|
|
35
34
|
model_name: str = "model",
|
|
36
35
|
tag: str = "",
|
|
37
|
-
model_path: str = None,
|
|
38
|
-
modules_map: Union[dict[str, Union[None, str, list[str]]], str] = None,
|
|
39
|
-
custom_objects_map: Union[dict[str, Union[str, list[str]]], str] = None,
|
|
40
|
-
custom_objects_directory: str = None,
|
|
36
|
+
model_path: Optional[str] = None,
|
|
37
|
+
modules_map: Optional[Union[dict[str, Union[None, str, list[str]]], str]] = None,
|
|
38
|
+
custom_objects_map: Optional[Union[dict[str, Union[str, list[str]]], str]] = None,
|
|
39
|
+
custom_objects_directory: Optional[str] = None,
|
|
41
40
|
context: mlrun.MLClientCtx = None,
|
|
42
|
-
artifacts: Union[list[MLPlan], list[str], dict[str, dict]] = None,
|
|
43
|
-
metrics:
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
41
|
+
artifacts: Optional[Union[list[MLPlan], list[str], dict[str, dict]]] = None,
|
|
42
|
+
metrics: Optional[
|
|
43
|
+
Union[
|
|
44
|
+
list[Metric],
|
|
45
|
+
list[XGBoostTypes.MetricEntryType],
|
|
46
|
+
dict[str, XGBoostTypes.MetricEntryType],
|
|
47
|
+
]
|
|
47
48
|
] = None,
|
|
48
49
|
x_test: XGBoostTypes.DatasetType = None,
|
|
49
50
|
y_test: XGBoostTypes.DatasetType = None,
|
|
50
51
|
sample_set: Union[XGBoostTypes.DatasetType, mlrun.DataItem, str] = None,
|
|
51
|
-
y_columns: Union[list[str], list[int]] = None,
|
|
52
|
-
feature_vector: str = None,
|
|
53
|
-
feature_weights: list[float] = None,
|
|
54
|
-
labels: dict[str, Union[str, int, float]] = None,
|
|
55
|
-
parameters: dict[str, Union[str, int, float]] = None,
|
|
56
|
-
extra_data: dict[str, XGBoostTypes.ExtraDataType] = None,
|
|
52
|
+
y_columns: Optional[Union[list[str], list[int]]] = None,
|
|
53
|
+
feature_vector: Optional[str] = None,
|
|
54
|
+
feature_weights: Optional[list[float]] = None,
|
|
55
|
+
labels: Optional[dict[str, Union[str, int, float]]] = None,
|
|
56
|
+
parameters: Optional[dict[str, Union[str, int, float]]] = None,
|
|
57
|
+
extra_data: Optional[dict[str, XGBoostTypes.ExtraDataType]] = None,
|
|
57
58
|
auto_log: bool = True,
|
|
58
59
|
**kwargs,
|
|
59
60
|
) -> XGBoostModelHandler:
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
#
|
|
15
15
|
import os
|
|
16
16
|
import pickle
|
|
17
|
-
from typing import Union
|
|
17
|
+
from typing import Optional, Union
|
|
18
18
|
|
|
19
19
|
import cloudpickle
|
|
20
20
|
|
|
@@ -45,11 +45,15 @@ class XGBoostModelHandler(MLModelHandler):
|
|
|
45
45
|
def __init__(
|
|
46
46
|
self,
|
|
47
47
|
model: XGBoostTypes.ModelType = None,
|
|
48
|
-
model_path: str = None,
|
|
49
|
-
model_name: str = None,
|
|
50
|
-
modules_map:
|
|
51
|
-
|
|
52
|
-
|
|
48
|
+
model_path: Optional[str] = None,
|
|
49
|
+
model_name: Optional[str] = None,
|
|
50
|
+
modules_map: Optional[
|
|
51
|
+
Union[dict[str, Union[None, str, list[str]]], str]
|
|
52
|
+
] = None,
|
|
53
|
+
custom_objects_map: Optional[
|
|
54
|
+
Union[dict[str, Union[str, list[str]]], str]
|
|
55
|
+
] = None,
|
|
56
|
+
custom_objects_directory: Optional[str] = None,
|
|
53
57
|
context: mlrun.MLClientCtx = None,
|
|
54
58
|
model_format: str = ModelFormats.PKL,
|
|
55
59
|
**kwargs,
|
|
@@ -152,7 +156,7 @@ class XGBoostModelHandler(MLModelHandler):
|
|
|
152
156
|
)
|
|
153
157
|
|
|
154
158
|
@without_mlrun_interface(interface=XGBModelMLRunInterface)
|
|
155
|
-
def save(self, output_path: str = None, **kwargs):
|
|
159
|
+
def save(self, output_path: Optional[str] = None, **kwargs):
|
|
156
160
|
"""
|
|
157
161
|
Save the handled model at the given output path. If a MLRun context is available, the saved model files will be
|
|
158
162
|
logged and returned as artifacts.
|
|
@@ -186,10 +190,10 @@ class XGBoostModelHandler(MLModelHandler):
|
|
|
186
190
|
|
|
187
191
|
def to_onnx(
|
|
188
192
|
self,
|
|
189
|
-
model_name: str = None,
|
|
193
|
+
model_name: Optional[str] = None,
|
|
190
194
|
optimize: bool = True,
|
|
191
195
|
input_sample: XGBoostTypes = None,
|
|
192
|
-
log: bool = None,
|
|
196
|
+
log: Optional[bool] = None,
|
|
193
197
|
):
|
|
194
198
|
"""
|
|
195
199
|
Convert the model in this handler to an ONNX model. The inputs names are optional, they do not change the
|
mlrun/k8s_utils.py
CHANGED
|
@@ -142,6 +142,7 @@ def verify_label_key(key: str, allow_k8s_prefix: bool = False):
|
|
|
142
142
|
if not key:
|
|
143
143
|
raise mlrun.errors.MLRunInvalidArgumentError("label key cannot be empty")
|
|
144
144
|
|
|
145
|
+
prefix = ""
|
|
145
146
|
parts = key.split("/")
|
|
146
147
|
if len(parts) == 1:
|
|
147
148
|
name = parts[0]
|
|
@@ -180,11 +181,7 @@ def verify_label_key(key: str, allow_k8s_prefix: bool = False):
|
|
|
180
181
|
|
|
181
182
|
# Allow the use of Kubernetes reserved prefixes ('k8s.io/' or 'kubernetes.io/')
|
|
182
183
|
# only when setting node selectors, not when adding new labels.
|
|
183
|
-
if
|
|
184
|
-
key.startswith("k8s.io/")
|
|
185
|
-
or key.startswith("kubernetes.io/")
|
|
186
|
-
and not allow_k8s_prefix
|
|
187
|
-
):
|
|
184
|
+
if not allow_k8s_prefix and prefix in {"k8s.io", "kubernetes.io"}:
|
|
188
185
|
raise mlrun.errors.MLRunInvalidArgumentError(
|
|
189
186
|
"Labels cannot start with 'k8s.io/' or 'kubernetes.io/'"
|
|
190
187
|
)
|
mlrun/launcher/base.py
CHANGED
|
@@ -18,8 +18,6 @@ import os
|
|
|
18
18
|
import uuid
|
|
19
19
|
from typing import Any, Callable, Optional, Union
|
|
20
20
|
|
|
21
|
-
import mlrun_pipelines.common.ops
|
|
22
|
-
|
|
23
21
|
import mlrun.common.schemas
|
|
24
22
|
import mlrun.config
|
|
25
23
|
import mlrun.errors
|
|
@@ -27,6 +25,7 @@ import mlrun.lists
|
|
|
27
25
|
import mlrun.model
|
|
28
26
|
import mlrun.runtimes
|
|
29
27
|
import mlrun.utils.regex
|
|
28
|
+
import mlrun_pipelines.common.ops
|
|
30
29
|
from mlrun.utils import logger
|
|
31
30
|
|
|
32
31
|
run_modes = ["pass"]
|
|
@@ -62,7 +61,7 @@ class BaseLauncher(abc.ABC):
|
|
|
62
61
|
schedule: Optional[
|
|
63
62
|
Union[str, mlrun.common.schemas.schedule.ScheduleCronTrigger]
|
|
64
63
|
] = None,
|
|
65
|
-
hyperparams: dict[str, list] = None,
|
|
64
|
+
hyperparams: Optional[dict[str, list]] = None,
|
|
66
65
|
hyper_param_options: Optional[mlrun.model.HyperParamOptions] = None,
|
|
67
66
|
verbose: Optional[bool] = None,
|
|
68
67
|
scrape_metrics: Optional[bool] = None,
|
|
@@ -238,7 +237,7 @@ class BaseLauncher(abc.ABC):
|
|
|
238
237
|
out_path=None,
|
|
239
238
|
artifact_path=None,
|
|
240
239
|
workdir=None,
|
|
241
|
-
notifications: list[mlrun.model.Notification] = None,
|
|
240
|
+
notifications: Optional[list[mlrun.model.Notification]] = None,
|
|
242
241
|
state_thresholds: Optional[dict[str, int]] = None,
|
|
243
242
|
):
|
|
244
243
|
run.spec.handler = (
|
mlrun/launcher/client.py
CHANGED
|
@@ -134,7 +134,7 @@ class ClientBaseLauncher(launcher.BaseLauncher, abc.ABC):
|
|
|
134
134
|
if mlrun.utils.is_jupyter and mlrun.mlconf.ipython_widget:
|
|
135
135
|
results_tbl.show()
|
|
136
136
|
print()
|
|
137
|
-
ui_url = mlrun.utils.
|
|
137
|
+
ui_url = mlrun.utils.get_run_url(project, uid=uid, name=run.metadata.name)
|
|
138
138
|
if ui_url:
|
|
139
139
|
ui_url = f' or <a href="{ui_url}" target="_blank">click here</a> to open in UI'
|
|
140
140
|
IPython.display.display(
|
|
@@ -150,6 +150,6 @@ class ClientBaseLauncher(launcher.BaseLauncher, abc.ABC):
|
|
|
150
150
|
mlrun.utils.logger.info(
|
|
151
151
|
"To track results use the CLI", info_cmd=info_cmd, logs_cmd=logs_cmd
|
|
152
152
|
)
|
|
153
|
-
ui_url = mlrun.utils.
|
|
153
|
+
ui_url = mlrun.utils.get_run_url(project, uid=uid, name=run.metadata.name)
|
|
154
154
|
if ui_url:
|
|
155
155
|
mlrun.utils.logger.info("Or click for UI", ui_url=ui_url)
|
mlrun/launcher/local.py
CHANGED
|
@@ -59,7 +59,7 @@ class ClientLocalLauncher(launcher.ClientBaseLauncher):
|
|
|
59
59
|
schedule: Optional[
|
|
60
60
|
Union[str, mlrun.common.schemas.schedule.ScheduleCronTrigger]
|
|
61
61
|
] = None,
|
|
62
|
-
hyperparams: dict[str, list] = None,
|
|
62
|
+
hyperparams: Optional[dict[str, list]] = None,
|
|
63
63
|
hyper_param_options: Optional[mlrun.model.HyperParamOptions] = None,
|
|
64
64
|
verbose: Optional[bool] = None,
|
|
65
65
|
scrape_metrics: Optional[bool] = None,
|
|
@@ -281,5 +281,9 @@ class ClientLocalLauncher(launcher.ClientBaseLauncher):
|
|
|
281
281
|
# once the run is completed, and we can just push the notifications.
|
|
282
282
|
# Only push from jupyter, not from the CLI.
|
|
283
283
|
# "handler" and "dask" kinds are special cases of local runs which don't set local=True
|
|
284
|
-
if self._is_run_local or runtime.kind in ["handler"
|
|
284
|
+
if self._is_run_local or runtime.kind in ["handler"]:
|
|
285
285
|
mlrun.utils.notifications.NotificationPusher([runobj]).push()
|
|
286
|
+
elif runtime.kind in ["dask"]:
|
|
287
|
+
runtime._get_db().push_run_notifications(
|
|
288
|
+
uid=runobj.metadata.uid, project=runobj.metadata.project
|
|
289
|
+
)
|
mlrun/launcher/remote.py
CHANGED
|
@@ -49,7 +49,7 @@ class ClientRemoteLauncher(launcher.ClientBaseLauncher):
|
|
|
49
49
|
schedule: Optional[
|
|
50
50
|
Union[str, mlrun.common.schemas.schedule.ScheduleCronTrigger]
|
|
51
51
|
] = None,
|
|
52
|
-
hyperparams: dict[str, list] = None,
|
|
52
|
+
hyperparams: Optional[dict[str, list]] = None,
|
|
53
53
|
hyper_param_options: Optional[mlrun.model.HyperParamOptions] = None,
|
|
54
54
|
verbose: Optional[bool] = None,
|
|
55
55
|
scrape_metrics: Optional[bool] = None,
|
mlrun/lists.py
CHANGED
|
@@ -12,6 +12,7 @@
|
|
|
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 Optional
|
|
15
16
|
|
|
16
17
|
import pandas as pd
|
|
17
18
|
|
|
@@ -28,6 +29,7 @@ list_header = [
|
|
|
28
29
|
"uid",
|
|
29
30
|
"iter",
|
|
30
31
|
"start",
|
|
32
|
+
"end",
|
|
31
33
|
"state",
|
|
32
34
|
"kind",
|
|
33
35
|
"name",
|
|
@@ -57,6 +59,7 @@ class RunList(list):
|
|
|
57
59
|
get_in(run, "metadata.uid", ""),
|
|
58
60
|
get_in(run, "metadata.iteration", ""),
|
|
59
61
|
get_in(run, "status.start_time", ""),
|
|
62
|
+
get_in(run, "status.end_time", ""),
|
|
60
63
|
get_in(run, "status.state", ""),
|
|
61
64
|
get_in(run, "step_kind", get_in(run, "kind", "")),
|
|
62
65
|
get_in(run, "metadata.name", ""),
|
|
@@ -102,7 +105,8 @@ class RunList(list):
|
|
|
102
105
|
return self._df
|
|
103
106
|
rows = self.to_rows(extend_iterations=extend_iterations)
|
|
104
107
|
df = pd.DataFrame(rows[1:], columns=rows[0]) # .set_index('iter')
|
|
105
|
-
|
|
108
|
+
for time_column in ["start", "end"]:
|
|
109
|
+
df[time_column] = pd.to_datetime(df[time_column])
|
|
106
110
|
|
|
107
111
|
if flat:
|
|
108
112
|
df = flatten(df, "labels")
|
|
@@ -129,11 +133,11 @@ class RunList(list):
|
|
|
129
133
|
def compare(
|
|
130
134
|
self,
|
|
131
135
|
hide_identical: bool = True,
|
|
132
|
-
exclude: list = None,
|
|
133
|
-
show: bool = None,
|
|
136
|
+
exclude: Optional[list] = None,
|
|
137
|
+
show: Optional[bool] = None,
|
|
134
138
|
extend_iterations=True,
|
|
135
139
|
filename=None,
|
|
136
|
-
colorscale: str = None,
|
|
140
|
+
colorscale: Optional[str] = None,
|
|
137
141
|
):
|
|
138
142
|
"""return/show parallel coordinates plot + table to compare between the list of runs
|
|
139
143
|
|
mlrun/model.py
CHANGED
|
@@ -24,7 +24,7 @@ from datetime import datetime
|
|
|
24
24
|
from os import environ
|
|
25
25
|
from typing import Any, Optional, Union
|
|
26
26
|
|
|
27
|
-
import pydantic.error_wrappers
|
|
27
|
+
import pydantic.v1.error_wrappers
|
|
28
28
|
|
|
29
29
|
import mlrun
|
|
30
30
|
import mlrun.common.constants as mlrun_constants
|
|
@@ -74,7 +74,10 @@ class ModelObj:
|
|
|
74
74
|
|
|
75
75
|
@mlrun.utils.filter_warnings("ignore", FutureWarning)
|
|
76
76
|
def to_dict(
|
|
77
|
-
self,
|
|
77
|
+
self,
|
|
78
|
+
fields: Optional[list] = None,
|
|
79
|
+
exclude: Optional[list] = None,
|
|
80
|
+
strip: bool = False,
|
|
78
81
|
) -> dict:
|
|
79
82
|
"""
|
|
80
83
|
Convert the object to a dict
|
|
@@ -114,6 +117,8 @@ class ModelObj:
|
|
|
114
117
|
# If one of the attributes is a third party object that has to_dict method (such as k8s objects), then
|
|
115
118
|
# add it to the object's _fields_to_serialize attribute and handle it in the _serialize_field method.
|
|
116
119
|
if hasattr(field_value, "to_dict"):
|
|
120
|
+
# TODO: Allow passing fields to exclude from the parent object to the child object
|
|
121
|
+
# e.g.: run.to_dict(exclude=["status.artifacts"])
|
|
117
122
|
field_value = field_value.to_dict(strip=strip)
|
|
118
123
|
if self._is_valid_field_value_for_serialization(
|
|
119
124
|
field_name, field_value, strip
|
|
@@ -141,7 +146,7 @@ class ModelObj:
|
|
|
141
146
|
self._apply_enrichment_before_to_dict_completion(struct, strip=strip)
|
|
142
147
|
return struct
|
|
143
148
|
|
|
144
|
-
def _resolve_initial_to_dict_fields(self, fields: list = None) -> list:
|
|
149
|
+
def _resolve_initial_to_dict_fields(self, fields: Optional[list] = None) -> list:
|
|
145
150
|
"""
|
|
146
151
|
Resolve fields to be used in to_dict method.
|
|
147
152
|
If fields is None, use `_dict_fields` attribute of the object.
|
|
@@ -184,7 +189,7 @@ class ModelObj:
|
|
|
184
189
|
self,
|
|
185
190
|
struct: dict,
|
|
186
191
|
method: typing.Callable,
|
|
187
|
-
fields: typing.Union[list, set] = None,
|
|
192
|
+
fields: Optional[typing.Union[list, set]] = None,
|
|
188
193
|
strip: bool = False,
|
|
189
194
|
) -> dict:
|
|
190
195
|
for field_name in fields:
|
|
@@ -196,14 +201,14 @@ class ModelObj:
|
|
|
196
201
|
return struct
|
|
197
202
|
|
|
198
203
|
def _serialize_field(
|
|
199
|
-
self, struct: dict, field_name: str = None, strip: bool = False
|
|
204
|
+
self, struct: dict, field_name: Optional[str] = None, strip: bool = False
|
|
200
205
|
) -> typing.Any:
|
|
201
206
|
# We pull the field from self and not from struct because it was excluded from the struct when looping over
|
|
202
207
|
# the fields to save.
|
|
203
208
|
return getattr(self, field_name, None)
|
|
204
209
|
|
|
205
210
|
def _enrich_field(
|
|
206
|
-
self, struct: dict, field_name: str = None, strip: bool = False
|
|
211
|
+
self, struct: dict, field_name: Optional[str] = None, strip: bool = False
|
|
207
212
|
) -> typing.Any:
|
|
208
213
|
# We first try to pull from struct because the field might have been already serialized and if not,
|
|
209
214
|
# we pull from self
|
|
@@ -215,7 +220,9 @@ class ModelObj:
|
|
|
215
220
|
return struct
|
|
216
221
|
|
|
217
222
|
@classmethod
|
|
218
|
-
def from_dict(
|
|
223
|
+
def from_dict(
|
|
224
|
+
cls, struct=None, fields=None, deprecated_fields: Optional[dict] = None
|
|
225
|
+
):
|
|
219
226
|
"""create an object from a python dictionary"""
|
|
220
227
|
struct = {} if struct is None else struct
|
|
221
228
|
deprecated_fields = deprecated_fields or {}
|
|
@@ -423,6 +430,19 @@ class ObjectList:
|
|
|
423
430
|
self._children[child_obj.name] = child_obj
|
|
424
431
|
return child_obj
|
|
425
432
|
|
|
433
|
+
def move_to_end(self, child, last=True):
|
|
434
|
+
self._children.move_to_end(child, last)
|
|
435
|
+
|
|
436
|
+
def update_list(self, object_list: "ObjectList", push_at_start: bool = False):
|
|
437
|
+
if push_at_start:
|
|
438
|
+
self._children = OrderedDict(
|
|
439
|
+
list(object_list._children.items()) + list(self._children.items())
|
|
440
|
+
)
|
|
441
|
+
else:
|
|
442
|
+
self._children = OrderedDict(
|
|
443
|
+
list(self._children.items()) + list(object_list._children.items())
|
|
444
|
+
)
|
|
445
|
+
|
|
426
446
|
|
|
427
447
|
class Credentials(ModelObj):
|
|
428
448
|
generate_access_key = "$generate"
|
|
@@ -430,7 +450,7 @@ class Credentials(ModelObj):
|
|
|
430
450
|
|
|
431
451
|
def __init__(
|
|
432
452
|
self,
|
|
433
|
-
access_key: str = None,
|
|
453
|
+
access_key: Optional[str] = None,
|
|
434
454
|
):
|
|
435
455
|
self.access_key = access_key
|
|
436
456
|
|
|
@@ -438,6 +458,7 @@ class Credentials(ModelObj):
|
|
|
438
458
|
class BaseMetadata(ModelObj):
|
|
439
459
|
_default_fields_to_strip = ModelObj._default_fields_to_strip + [
|
|
440
460
|
"hash",
|
|
461
|
+
"uid",
|
|
441
462
|
# Below are environment specific fields, no need to keep when stripping
|
|
442
463
|
"namespace",
|
|
443
464
|
"project",
|
|
@@ -460,10 +481,12 @@ class BaseMetadata(ModelObj):
|
|
|
460
481
|
categories=None,
|
|
461
482
|
updated=None,
|
|
462
483
|
credentials=None,
|
|
484
|
+
uid=None,
|
|
463
485
|
):
|
|
464
486
|
self.name = name
|
|
465
487
|
self.tag = tag
|
|
466
488
|
self.hash = hash
|
|
489
|
+
self.uid = uid
|
|
467
490
|
self.namespace = namespace
|
|
468
491
|
self.project = project or ""
|
|
469
492
|
self.labels = labels or {}
|
|
@@ -500,7 +523,7 @@ class ImageBuilder(ModelObj):
|
|
|
500
523
|
origin_filename=None,
|
|
501
524
|
with_mlrun=None,
|
|
502
525
|
auto_build=None,
|
|
503
|
-
requirements: list = None,
|
|
526
|
+
requirements: Optional[list] = None,
|
|
504
527
|
extra_args=None,
|
|
505
528
|
builder_env=None,
|
|
506
529
|
source_code_target_dir=None,
|
|
@@ -549,7 +572,7 @@ class ImageBuilder(ModelObj):
|
|
|
549
572
|
self,
|
|
550
573
|
image="",
|
|
551
574
|
base_image=None,
|
|
552
|
-
commands: list = None,
|
|
575
|
+
commands: Optional[list] = None,
|
|
553
576
|
secret=None,
|
|
554
577
|
source=None,
|
|
555
578
|
extra=None,
|
|
@@ -734,7 +757,7 @@ class Notification(ModelObj):
|
|
|
734
757
|
def validate_notification(self):
|
|
735
758
|
try:
|
|
736
759
|
mlrun.common.schemas.notification.Notification(**self.to_dict())
|
|
737
|
-
except pydantic.error_wrappers.ValidationError as exc:
|
|
760
|
+
except pydantic.v1.error_wrappers.ValidationError as exc:
|
|
738
761
|
raise mlrun.errors.MLRunInvalidArgumentError(
|
|
739
762
|
"Invalid notification object"
|
|
740
763
|
) from exc
|
|
@@ -750,14 +773,14 @@ class Notification(ModelObj):
|
|
|
750
773
|
"Notification params size exceeds max size of 1 MB"
|
|
751
774
|
)
|
|
752
775
|
|
|
753
|
-
def validate_notification_params(self):
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
776
|
+
def validate_notification_params(self, default_notification_params=None):
|
|
777
|
+
default_notification_params = default_notification_params or {}
|
|
778
|
+
notification_type = mlrun.utils.notifications.NotificationTypes(self.kind)
|
|
779
|
+
notification_class = notification_type.get_notification()
|
|
758
780
|
secret_params = self.secret_params or {}
|
|
759
781
|
params = self.params or {}
|
|
760
|
-
|
|
782
|
+
default_params = default_notification_params.get(notification_type, {})
|
|
783
|
+
params = notification_class.enrich_default_params(params, default_params)
|
|
761
784
|
# if the secret_params are already masked - no need to validate
|
|
762
785
|
params_secret = secret_params.get("secret", "")
|
|
763
786
|
if params_secret:
|
|
@@ -973,7 +996,7 @@ class RunSpec(ModelObj):
|
|
|
973
996
|
self.node_selector = node_selector or {}
|
|
974
997
|
|
|
975
998
|
def _serialize_field(
|
|
976
|
-
self, struct: dict, field_name: str = None, strip: bool = False
|
|
999
|
+
self, struct: dict, field_name: Optional[str] = None, strip: bool = False
|
|
977
1000
|
) -> Optional[str]:
|
|
978
1001
|
# We pull the field from self and not from struct because it was excluded from the struct
|
|
979
1002
|
if field_name == "handler":
|
|
@@ -1262,6 +1285,8 @@ class RunSpec(ModelObj):
|
|
|
1262
1285
|
class RunStatus(ModelObj):
|
|
1263
1286
|
"""Run status"""
|
|
1264
1287
|
|
|
1288
|
+
_default_fields_to_strip = ModelObj._default_fields_to_strip + ["artifacts"]
|
|
1289
|
+
|
|
1265
1290
|
def __init__(
|
|
1266
1291
|
self,
|
|
1267
1292
|
state=None,
|
|
@@ -1272,12 +1297,13 @@ class RunStatus(ModelObj):
|
|
|
1272
1297
|
results=None,
|
|
1273
1298
|
artifacts=None,
|
|
1274
1299
|
start_time=None,
|
|
1300
|
+
end_time=None,
|
|
1275
1301
|
last_update=None,
|
|
1276
1302
|
iterations=None,
|
|
1277
1303
|
ui_url=None,
|
|
1278
|
-
reason: str = None,
|
|
1279
|
-
notifications: dict[str, Notification] = None,
|
|
1280
|
-
artifact_uris: dict[str, str] = None,
|
|
1304
|
+
reason: Optional[str] = None,
|
|
1305
|
+
notifications: Optional[dict[str, Notification]] = None,
|
|
1306
|
+
artifact_uris: Optional[dict[str, str]] = None,
|
|
1281
1307
|
):
|
|
1282
1308
|
self.state = state or "created"
|
|
1283
1309
|
self.status_text = status_text
|
|
@@ -1285,15 +1311,68 @@ class RunStatus(ModelObj):
|
|
|
1285
1311
|
self.host = host
|
|
1286
1312
|
self.commit = commit
|
|
1287
1313
|
self.results = results
|
|
1288
|
-
self.
|
|
1314
|
+
self._artifacts = artifacts
|
|
1289
1315
|
self.start_time = start_time
|
|
1316
|
+
self.end_time = end_time
|
|
1290
1317
|
self.last_update = last_update
|
|
1291
1318
|
self.iterations = iterations
|
|
1292
1319
|
self.ui_url = ui_url
|
|
1293
1320
|
self.reason = reason
|
|
1294
1321
|
self.notifications = notifications or {}
|
|
1295
1322
|
# Artifact key -> URI mapping, since the full artifacts are not stored in the runs DB table
|
|
1296
|
-
self.
|
|
1323
|
+
self._artifact_uris = artifact_uris or {}
|
|
1324
|
+
|
|
1325
|
+
@classmethod
|
|
1326
|
+
def from_dict(
|
|
1327
|
+
cls, struct=None, fields=None, deprecated_fields: Optional[dict] = None
|
|
1328
|
+
):
|
|
1329
|
+
deprecated_fields = {
|
|
1330
|
+
# Set artifacts as deprecated for lazy loading
|
|
1331
|
+
"artifacts": "artifact_uris"
|
|
1332
|
+
}
|
|
1333
|
+
return super().from_dict(
|
|
1334
|
+
struct, fields=fields, deprecated_fields=deprecated_fields
|
|
1335
|
+
)
|
|
1336
|
+
|
|
1337
|
+
@property
|
|
1338
|
+
def artifacts(self):
|
|
1339
|
+
"""
|
|
1340
|
+
Artifacts are lazy loaded to reduce memory consumption.
|
|
1341
|
+
We keep artifact_uris (key -> store URI dictionary) to be able to get the run artifacts easily.
|
|
1342
|
+
If the artifact is not already in the cache, we get it from the store (DB).
|
|
1343
|
+
:return: List of artifact dictionaries
|
|
1344
|
+
"""
|
|
1345
|
+
self._artifacts = self._artifacts or []
|
|
1346
|
+
existing_artifact_keys = {
|
|
1347
|
+
artifact["metadata"]["key"] for artifact in self._artifacts
|
|
1348
|
+
}
|
|
1349
|
+
for key, uri in self.artifact_uris.items():
|
|
1350
|
+
if key not in existing_artifact_keys:
|
|
1351
|
+
artifact = mlrun.datastore.get_store_resource(uri)
|
|
1352
|
+
self._artifacts.append(artifact.to_dict())
|
|
1353
|
+
return self._artifacts
|
|
1354
|
+
|
|
1355
|
+
@artifacts.setter
|
|
1356
|
+
def artifacts(self, artifacts):
|
|
1357
|
+
self._artifacts = artifacts
|
|
1358
|
+
|
|
1359
|
+
@property
|
|
1360
|
+
def artifact_uris(self):
|
|
1361
|
+
return self._artifact_uris
|
|
1362
|
+
|
|
1363
|
+
@artifact_uris.setter
|
|
1364
|
+
def artifact_uris(self, artifact_uris):
|
|
1365
|
+
resolved_artifact_uris = {}
|
|
1366
|
+
if isinstance(artifact_uris, list):
|
|
1367
|
+
# artifact_uris is the deprecated list of artifacts - convert to new form
|
|
1368
|
+
for artifact in artifact_uris:
|
|
1369
|
+
if isinstance(artifact, dict):
|
|
1370
|
+
artifact = mlrun.artifacts.dict_to_artifact(artifact)
|
|
1371
|
+
resolved_artifact_uris[artifact.key] = artifact.uri
|
|
1372
|
+
else:
|
|
1373
|
+
resolved_artifact_uris = artifact_uris
|
|
1374
|
+
|
|
1375
|
+
self._artifact_uris = resolved_artifact_uris
|
|
1297
1376
|
|
|
1298
1377
|
def is_failed(self) -> Optional[bool]:
|
|
1299
1378
|
"""
|
|
@@ -1601,7 +1680,7 @@ class RunObject(RunTemplate):
|
|
|
1601
1680
|
|
|
1602
1681
|
return outputs
|
|
1603
1682
|
|
|
1604
|
-
def artifact(self, key: str) -> "mlrun.DataItem":
|
|
1683
|
+
def artifact(self, key: str) -> typing.Optional["mlrun.DataItem"]:
|
|
1605
1684
|
"""Return artifact DataItem by key.
|
|
1606
1685
|
|
|
1607
1686
|
This method waits for the outputs to complete, searches for the artifact matching the given key,
|
|
@@ -1644,7 +1723,7 @@ class RunObject(RunTemplate):
|
|
|
1644
1723
|
:param key: The key of the artifact to retrieve.
|
|
1645
1724
|
:return: The last artifact DataItem with the given key, or None if no such artifact is found.
|
|
1646
1725
|
"""
|
|
1647
|
-
if not self.status.artifacts:
|
|
1726
|
+
if not self.status.artifacts and not self.status.artifact_uris:
|
|
1648
1727
|
return None
|
|
1649
1728
|
|
|
1650
1729
|
# Collect artifacts that match the key
|
|
@@ -1655,7 +1734,12 @@ class RunObject(RunTemplate):
|
|
|
1655
1734
|
]
|
|
1656
1735
|
|
|
1657
1736
|
if not matching_artifacts:
|
|
1658
|
-
|
|
1737
|
+
if key not in self.status.artifact_uris:
|
|
1738
|
+
return None
|
|
1739
|
+
|
|
1740
|
+
# Get artifact by store URI sanity (should have been enriched by now in status.artifacts property)
|
|
1741
|
+
artifact_uri = self.status.artifact_uris[key]
|
|
1742
|
+
return mlrun.datastore.get_store_resource(artifact_uri)
|
|
1659
1743
|
|
|
1660
1744
|
# Sort matching artifacts by creation date in ascending order.
|
|
1661
1745
|
# The last element in the list will be the one created most recently.
|
|
@@ -1870,7 +1954,7 @@ class EntrypointParam(ModelObj):
|
|
|
1870
1954
|
default=None,
|
|
1871
1955
|
doc="",
|
|
1872
1956
|
required=None,
|
|
1873
|
-
choices: list = None,
|
|
1957
|
+
choices: Optional[list] = None,
|
|
1874
1958
|
):
|
|
1875
1959
|
self.name = name
|
|
1876
1960
|
self.type = type
|
|
@@ -2065,12 +2149,12 @@ class DataSource(ModelObj):
|
|
|
2065
2149
|
|
|
2066
2150
|
def __init__(
|
|
2067
2151
|
self,
|
|
2068
|
-
name: str = None,
|
|
2069
|
-
path: str = None,
|
|
2070
|
-
attributes: dict[str, object] = None,
|
|
2071
|
-
key_field: str = None,
|
|
2072
|
-
time_field: str = None,
|
|
2073
|
-
schedule: str = None,
|
|
2152
|
+
name: Optional[str] = None,
|
|
2153
|
+
path: Optional[str] = None,
|
|
2154
|
+
attributes: Optional[dict[str, object]] = None,
|
|
2155
|
+
key_field: Optional[str] = None,
|
|
2156
|
+
time_field: Optional[str] = None,
|
|
2157
|
+
schedule: Optional[str] = None,
|
|
2074
2158
|
start_time: Optional[Union[datetime, str]] = None,
|
|
2075
2159
|
end_time: Optional[Union[datetime, str]] = None,
|
|
2076
2160
|
):
|
|
@@ -2092,7 +2176,7 @@ class DataSource(ModelObj):
|
|
|
2092
2176
|
self._secrets = secrets
|
|
2093
2177
|
|
|
2094
2178
|
def _serialize_field(
|
|
2095
|
-
self, struct: dict, field_name: str = None, strip: bool = False
|
|
2179
|
+
self, struct: dict, field_name: Optional[str] = None, strip: bool = False
|
|
2096
2180
|
) -> typing.Any:
|
|
2097
2181
|
value = super()._serialize_field(struct, field_name, strip)
|
|
2098
2182
|
# We pull the field from self and not from struct because it was excluded from the struct when looping over
|
|
@@ -2124,7 +2208,9 @@ class DataTargetBase(ModelObj):
|
|
|
2124
2208
|
]
|
|
2125
2209
|
|
|
2126
2210
|
@classmethod
|
|
2127
|
-
def from_dict(
|
|
2211
|
+
def from_dict(
|
|
2212
|
+
cls, struct=None, fields=None, deprecated_fields: Optional[dict] = None
|
|
2213
|
+
):
|
|
2128
2214
|
return super().from_dict(struct, fields=fields)
|
|
2129
2215
|
|
|
2130
2216
|
def get_path(self):
|
|
@@ -2140,10 +2226,10 @@ class DataTargetBase(ModelObj):
|
|
|
2140
2226
|
|
|
2141
2227
|
def __init__(
|
|
2142
2228
|
self,
|
|
2143
|
-
kind: str = None,
|
|
2229
|
+
kind: Optional[str] = None,
|
|
2144
2230
|
name: str = "",
|
|
2145
2231
|
path=None,
|
|
2146
|
-
attributes: dict[str, str] = None,
|
|
2232
|
+
attributes: Optional[dict[str, str]] = None,
|
|
2147
2233
|
after_step=None,
|
|
2148
2234
|
partitioned: bool = False,
|
|
2149
2235
|
key_bucketing_number: Optional[int] = None,
|
|
@@ -2151,8 +2237,8 @@ class DataTargetBase(ModelObj):
|
|
|
2151
2237
|
time_partitioning_granularity: Optional[str] = None,
|
|
2152
2238
|
max_events: Optional[int] = None,
|
|
2153
2239
|
flush_after_seconds: Optional[int] = None,
|
|
2154
|
-
storage_options: dict[str, str] = None,
|
|
2155
|
-
schema: dict[str, Any] = None,
|
|
2240
|
+
storage_options: Optional[dict[str, str]] = None,
|
|
2241
|
+
schema: Optional[dict[str, Any]] = None,
|
|
2156
2242
|
credentials_prefix=None,
|
|
2157
2243
|
):
|
|
2158
2244
|
self.name = name
|
|
@@ -2208,7 +2294,7 @@ class DataTarget(DataTargetBase):
|
|
|
2208
2294
|
|
|
2209
2295
|
def __init__(
|
|
2210
2296
|
self,
|
|
2211
|
-
kind: str = None,
|
|
2297
|
+
kind: Optional[str] = None,
|
|
2212
2298
|
name: str = "",
|
|
2213
2299
|
path=None,
|
|
2214
2300
|
online=None,
|
|
@@ -2237,12 +2323,12 @@ class DataTarget(DataTargetBase):
|
|
|
2237
2323
|
class VersionedObjMetadata(ModelObj):
|
|
2238
2324
|
def __init__(
|
|
2239
2325
|
self,
|
|
2240
|
-
name: str = None,
|
|
2241
|
-
tag: str = None,
|
|
2242
|
-
uid: str = None,
|
|
2243
|
-
project: str = None,
|
|
2244
|
-
labels: dict[str, str] = None,
|
|
2245
|
-
annotations: dict[str, str] = None,
|
|
2326
|
+
name: Optional[str] = None,
|
|
2327
|
+
tag: Optional[str] = None,
|
|
2328
|
+
uid: Optional[str] = None,
|
|
2329
|
+
project: Optional[str] = None,
|
|
2330
|
+
labels: Optional[dict[str, str]] = None,
|
|
2331
|
+
annotations: Optional[dict[str, str]] = None,
|
|
2246
2332
|
updated=None,
|
|
2247
2333
|
):
|
|
2248
2334
|
self.name = name
|
|
@@ -11,11 +11,9 @@
|
|
|
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
|
-
#
|
|
15
|
-
# flake8: noqa - this is until we take care of the F401 violations with respect to __all__ & sphinx
|
|
16
|
-
# for backwards compatibility
|
|
17
14
|
|
|
18
|
-
from .
|
|
15
|
+
from mlrun.common.schemas import ModelEndpoint, ModelEndpointList
|
|
16
|
+
|
|
17
|
+
from .db import get_tsdb_connector
|
|
19
18
|
from .helpers import get_stream_path
|
|
20
|
-
from .model_endpoint import ModelEndpoint
|
|
21
19
|
from .tracking_policy import TrackingPolicy
|