mlrun 1.3.3rc1__py3-none-any.whl → 1.4.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 +3 -3
- mlrun/__main__.py +79 -37
- mlrun/api/__init__.py +1 -1
- mlrun/api/api/__init__.py +1 -1
- mlrun/api/api/api.py +4 -4
- mlrun/api/api/deps.py +10 -21
- mlrun/api/api/endpoints/__init__.py +1 -1
- mlrun/api/api/endpoints/artifacts.py +64 -36
- mlrun/api/api/endpoints/auth.py +4 -4
- mlrun/api/api/endpoints/background_tasks.py +11 -11
- mlrun/api/api/endpoints/client_spec.py +5 -5
- mlrun/api/api/endpoints/clusterization_spec.py +6 -4
- mlrun/api/api/endpoints/feature_store.py +124 -115
- mlrun/api/api/endpoints/files.py +22 -14
- mlrun/api/api/endpoints/frontend_spec.py +28 -21
- mlrun/api/api/endpoints/functions.py +142 -87
- mlrun/api/api/endpoints/grafana_proxy.py +89 -442
- mlrun/api/api/endpoints/healthz.py +20 -7
- mlrun/api/api/endpoints/hub.py +320 -0
- mlrun/api/api/endpoints/internal/__init__.py +1 -1
- mlrun/api/api/endpoints/internal/config.py +1 -1
- mlrun/api/api/endpoints/internal/memory_reports.py +9 -9
- mlrun/api/api/endpoints/logs.py +11 -11
- mlrun/api/api/endpoints/model_endpoints.py +74 -70
- mlrun/api/api/endpoints/operations.py +13 -9
- mlrun/api/api/endpoints/pipelines.py +93 -88
- mlrun/api/api/endpoints/projects.py +35 -35
- mlrun/api/api/endpoints/runs.py +69 -27
- mlrun/api/api/endpoints/runtime_resources.py +28 -28
- mlrun/api/api/endpoints/schedules.py +98 -41
- mlrun/api/api/endpoints/secrets.py +37 -32
- mlrun/api/api/endpoints/submit.py +12 -12
- mlrun/api/api/endpoints/tags.py +20 -22
- mlrun/api/api/utils.py +251 -42
- mlrun/api/constants.py +1 -1
- mlrun/api/crud/__init__.py +18 -15
- mlrun/api/crud/artifacts.py +10 -10
- mlrun/api/crud/client_spec.py +4 -4
- mlrun/api/crud/clusterization_spec.py +3 -3
- mlrun/api/crud/feature_store.py +54 -46
- mlrun/api/crud/functions.py +3 -3
- mlrun/api/crud/hub.py +312 -0
- mlrun/api/crud/logs.py +11 -9
- mlrun/api/crud/model_monitoring/__init__.py +3 -3
- mlrun/api/crud/model_monitoring/grafana.py +435 -0
- mlrun/api/crud/model_monitoring/model_endpoints.py +352 -129
- mlrun/api/crud/notifications.py +149 -0
- mlrun/api/crud/pipelines.py +67 -52
- mlrun/api/crud/projects.py +51 -23
- mlrun/api/crud/runs.py +7 -5
- mlrun/api/crud/runtime_resources.py +13 -13
- mlrun/api/{db/filedb → crud/runtimes}/__init__.py +1 -1
- mlrun/api/crud/runtimes/nuclio/__init__.py +14 -0
- mlrun/api/crud/runtimes/nuclio/function.py +505 -0
- mlrun/api/crud/runtimes/nuclio/helpers.py +310 -0
- mlrun/api/crud/secrets.py +88 -46
- mlrun/api/crud/tags.py +5 -5
- mlrun/api/db/__init__.py +1 -1
- mlrun/api/db/base.py +102 -54
- mlrun/api/db/init_db.py +2 -3
- mlrun/api/db/session.py +4 -12
- mlrun/api/db/sqldb/__init__.py +1 -1
- mlrun/api/db/sqldb/db.py +439 -196
- mlrun/api/db/sqldb/helpers.py +1 -1
- mlrun/api/db/sqldb/models/__init__.py +3 -3
- mlrun/api/db/sqldb/models/models_mysql.py +82 -64
- mlrun/api/db/sqldb/models/models_sqlite.py +76 -64
- mlrun/api/db/sqldb/session.py +27 -20
- mlrun/api/initial_data.py +82 -24
- mlrun/api/launcher.py +196 -0
- mlrun/api/main.py +91 -22
- mlrun/api/middlewares.py +6 -5
- mlrun/api/migrations_mysql/env.py +1 -1
- mlrun/api/migrations_mysql/versions/28383af526f3_market_place_to_hub.py +40 -0
- mlrun/api/migrations_mysql/versions/32bae1b0e29c_increase_timestamp_fields_precision.py +1 -1
- mlrun/api/migrations_mysql/versions/4903aef6a91d_tag_foreign_key_and_cascades.py +1 -1
- mlrun/api/migrations_mysql/versions/5f1351c88a19_adding_background_tasks_table.py +1 -1
- mlrun/api/migrations_mysql/versions/88e656800d6a_add_requested_logs_column_and_index_to_.py +1 -1
- mlrun/api/migrations_mysql/versions/9d16de5f03a7_adding_data_versions_table.py +1 -1
- mlrun/api/migrations_mysql/versions/b86f5b53f3d7_adding_name_and_updated_to_runs_table.py +1 -1
- mlrun/api/migrations_mysql/versions/c4af40b0bf61_init.py +1 -1
- mlrun/api/migrations_mysql/versions/c905d15bd91d_notifications.py +72 -0
- mlrun/api/migrations_mysql/versions/ee041e8fdaa0_adding_next_run_time_column_to_schedule_.py +1 -1
- mlrun/api/migrations_sqlite/env.py +1 -1
- mlrun/api/migrations_sqlite/versions/11f8dd2dc9fe_init.py +1 -1
- mlrun/api/migrations_sqlite/versions/1c954f8cb32d_schedule_last_run_uri.py +1 -1
- mlrun/api/migrations_sqlite/versions/2b6d23c715aa_adding_feature_sets.py +1 -1
- mlrun/api/migrations_sqlite/versions/4acd9430b093_market_place_to_hub.py +77 -0
- mlrun/api/migrations_sqlite/versions/6401142f2d7c_adding_next_run_time_column_to_schedule_.py +1 -1
- mlrun/api/migrations_sqlite/versions/64d90a1a69bc_adding_background_tasks_table.py +1 -1
- mlrun/api/migrations_sqlite/versions/803438ecd005_add_requested_logs_column_to_runs.py +1 -1
- mlrun/api/migrations_sqlite/versions/863114f0c659_refactoring_feature_set.py +1 -1
- mlrun/api/migrations_sqlite/versions/959ae00528ad_notifications.py +63 -0
- mlrun/api/migrations_sqlite/versions/accf9fc83d38_adding_data_versions_table.py +1 -1
- mlrun/api/migrations_sqlite/versions/b68e8e897a28_schedule_labels.py +1 -1
- mlrun/api/migrations_sqlite/versions/bcd0c1f9720c_adding_project_labels.py +1 -1
- mlrun/api/migrations_sqlite/versions/cf21882f938e_schedule_id.py +1 -1
- mlrun/api/migrations_sqlite/versions/d781f58f607f_tag_object_name_string.py +1 -1
- mlrun/api/migrations_sqlite/versions/deac06871ace_adding_marketplace_sources_table.py +1 -1
- mlrun/api/migrations_sqlite/versions/e1dd5983c06b_schedule_concurrency_limit.py +1 -1
- mlrun/api/migrations_sqlite/versions/e5594ed3ab53_adding_name_and_updated_to_runs_table.py +1 -1
- mlrun/api/migrations_sqlite/versions/f4249b4ba6fa_adding_feature_vectors.py +1 -1
- mlrun/api/migrations_sqlite/versions/f7b5a1a03629_adding_feature_labels.py +1 -1
- mlrun/api/schemas/__init__.py +216 -138
- mlrun/api/utils/__init__.py +1 -1
- mlrun/api/utils/asyncio.py +1 -1
- mlrun/api/utils/auth/__init__.py +1 -1
- mlrun/api/utils/auth/providers/__init__.py +1 -1
- mlrun/api/utils/auth/providers/base.py +7 -7
- mlrun/api/utils/auth/providers/nop.py +6 -7
- mlrun/api/utils/auth/providers/opa.py +17 -17
- mlrun/api/utils/auth/verifier.py +36 -34
- mlrun/api/utils/background_tasks.py +24 -24
- mlrun/{builder.py → api/utils/builder.py} +216 -123
- mlrun/api/utils/clients/__init__.py +1 -1
- mlrun/api/utils/clients/chief.py +19 -4
- mlrun/api/utils/clients/iguazio.py +106 -60
- mlrun/api/utils/clients/log_collector.py +1 -1
- mlrun/api/utils/clients/nuclio.py +23 -23
- mlrun/api/utils/clients/protocols/grpc.py +2 -2
- mlrun/api/utils/db/__init__.py +1 -1
- mlrun/api/utils/db/alembic.py +1 -1
- mlrun/api/utils/db/backup.py +1 -1
- mlrun/api/utils/db/mysql.py +24 -25
- mlrun/api/utils/db/sql_collation.py +1 -1
- mlrun/api/utils/db/sqlite_migration.py +2 -2
- mlrun/api/utils/events/__init__.py +14 -0
- mlrun/api/utils/events/base.py +57 -0
- mlrun/api/utils/events/events_factory.py +41 -0
- mlrun/api/utils/events/iguazio.py +217 -0
- mlrun/api/utils/events/nop.py +55 -0
- mlrun/api/utils/helpers.py +16 -13
- mlrun/api/utils/memory_reports.py +1 -1
- mlrun/api/utils/periodic.py +6 -3
- mlrun/api/utils/projects/__init__.py +1 -1
- mlrun/api/utils/projects/follower.py +33 -33
- mlrun/api/utils/projects/leader.py +36 -34
- mlrun/api/utils/projects/member.py +27 -27
- mlrun/api/utils/projects/remotes/__init__.py +1 -1
- mlrun/api/utils/projects/remotes/follower.py +13 -13
- mlrun/api/utils/projects/remotes/leader.py +10 -10
- mlrun/api/utils/projects/remotes/nop_follower.py +27 -21
- mlrun/api/utils/projects/remotes/nop_leader.py +17 -16
- mlrun/api/utils/scheduler.py +140 -51
- mlrun/api/utils/singletons/__init__.py +1 -1
- mlrun/api/utils/singletons/db.py +9 -15
- mlrun/api/utils/singletons/k8s.py +677 -5
- mlrun/api/utils/singletons/logs_dir.py +1 -1
- mlrun/api/utils/singletons/project_member.py +1 -1
- mlrun/api/utils/singletons/scheduler.py +1 -1
- mlrun/artifacts/__init__.py +2 -2
- mlrun/artifacts/base.py +8 -2
- mlrun/artifacts/dataset.py +5 -3
- mlrun/artifacts/manager.py +7 -1
- mlrun/artifacts/model.py +15 -4
- mlrun/artifacts/plots.py +1 -1
- mlrun/common/__init__.py +1 -1
- mlrun/common/constants.py +15 -0
- mlrun/common/model_monitoring.py +209 -0
- mlrun/common/schemas/__init__.py +167 -0
- mlrun/{api → common}/schemas/artifact.py +13 -14
- mlrun/{api → common}/schemas/auth.py +10 -8
- mlrun/{api → common}/schemas/background_task.py +3 -3
- mlrun/{api → common}/schemas/client_spec.py +1 -1
- mlrun/{api → common}/schemas/clusterization_spec.py +3 -3
- mlrun/{api → common}/schemas/constants.py +21 -8
- mlrun/common/schemas/events.py +36 -0
- mlrun/{api → common}/schemas/feature_store.py +2 -1
- mlrun/{api → common}/schemas/frontend_spec.py +7 -6
- mlrun/{api → common}/schemas/function.py +5 -5
- mlrun/{api → common}/schemas/http.py +3 -3
- mlrun/common/schemas/hub.py +134 -0
- mlrun/{api → common}/schemas/k8s.py +3 -3
- mlrun/{api → common}/schemas/memory_reports.py +1 -1
- mlrun/common/schemas/model_endpoints.py +342 -0
- mlrun/common/schemas/notification.py +57 -0
- mlrun/{api → common}/schemas/object.py +6 -6
- mlrun/{api → common}/schemas/pipeline.py +3 -3
- mlrun/{api → common}/schemas/project.py +6 -5
- mlrun/common/schemas/regex.py +24 -0
- mlrun/common/schemas/runs.py +30 -0
- mlrun/{api → common}/schemas/runtime_resource.py +3 -3
- mlrun/{api → common}/schemas/schedule.py +19 -7
- mlrun/{api → common}/schemas/secret.py +3 -3
- mlrun/{api → common}/schemas/tag.py +2 -2
- mlrun/common/types.py +25 -0
- mlrun/config.py +152 -20
- mlrun/data_types/__init__.py +7 -2
- mlrun/data_types/data_types.py +4 -2
- mlrun/data_types/infer.py +1 -1
- mlrun/data_types/spark.py +10 -3
- mlrun/datastore/__init__.py +10 -3
- mlrun/datastore/azure_blob.py +1 -1
- mlrun/datastore/base.py +185 -53
- mlrun/datastore/datastore.py +1 -1
- mlrun/datastore/filestore.py +1 -1
- mlrun/datastore/google_cloud_storage.py +1 -1
- mlrun/datastore/inmem.py +4 -1
- mlrun/datastore/redis.py +1 -1
- mlrun/datastore/s3.py +1 -1
- mlrun/datastore/sources.py +192 -70
- mlrun/datastore/spark_udf.py +44 -0
- mlrun/datastore/store_resources.py +4 -4
- mlrun/datastore/targets.py +115 -45
- mlrun/datastore/utils.py +127 -5
- mlrun/datastore/v3io.py +1 -1
- mlrun/datastore/wasbfs/__init__.py +1 -1
- mlrun/datastore/wasbfs/fs.py +1 -1
- mlrun/db/__init__.py +7 -5
- mlrun/db/base.py +112 -68
- mlrun/db/httpdb.py +445 -277
- mlrun/db/nopdb.py +491 -0
- mlrun/db/sqldb.py +112 -65
- mlrun/errors.py +6 -1
- mlrun/execution.py +44 -22
- mlrun/feature_store/__init__.py +1 -1
- mlrun/feature_store/api.py +143 -95
- mlrun/feature_store/common.py +16 -20
- mlrun/feature_store/feature_set.py +42 -12
- mlrun/feature_store/feature_vector.py +32 -21
- mlrun/feature_store/ingestion.py +9 -12
- mlrun/feature_store/retrieval/__init__.py +3 -2
- mlrun/feature_store/retrieval/base.py +388 -66
- mlrun/feature_store/retrieval/dask_merger.py +63 -151
- mlrun/feature_store/retrieval/job.py +30 -12
- mlrun/feature_store/retrieval/local_merger.py +40 -133
- mlrun/feature_store/retrieval/spark_merger.py +129 -127
- mlrun/feature_store/retrieval/storey_merger.py +173 -0
- mlrun/feature_store/steps.py +132 -15
- mlrun/features.py +8 -3
- mlrun/frameworks/__init__.py +1 -1
- mlrun/frameworks/_common/__init__.py +1 -1
- mlrun/frameworks/_common/artifacts_library.py +1 -1
- mlrun/frameworks/_common/mlrun_interface.py +1 -1
- mlrun/frameworks/_common/model_handler.py +1 -1
- mlrun/frameworks/_common/plan.py +1 -1
- mlrun/frameworks/_common/producer.py +1 -1
- mlrun/frameworks/_common/utils.py +1 -1
- mlrun/frameworks/_dl_common/__init__.py +1 -1
- mlrun/frameworks/_dl_common/loggers/__init__.py +1 -1
- mlrun/frameworks/_dl_common/loggers/logger.py +1 -1
- mlrun/frameworks/_dl_common/loggers/mlrun_logger.py +1 -1
- mlrun/frameworks/_dl_common/loggers/tensorboard_logger.py +1 -1
- mlrun/frameworks/_dl_common/model_handler.py +1 -1
- mlrun/frameworks/_dl_common/utils.py +1 -1
- mlrun/frameworks/_ml_common/__init__.py +1 -1
- mlrun/frameworks/_ml_common/artifacts_library.py +1 -1
- mlrun/frameworks/_ml_common/loggers/__init__.py +1 -1
- mlrun/frameworks/_ml_common/loggers/logger.py +1 -1
- mlrun/frameworks/_ml_common/loggers/mlrun_logger.py +1 -1
- mlrun/frameworks/_ml_common/model_handler.py +1 -1
- mlrun/frameworks/_ml_common/pkl_model_server.py +13 -1
- mlrun/frameworks/_ml_common/plan.py +1 -1
- mlrun/frameworks/_ml_common/plans/__init__.py +1 -1
- mlrun/frameworks/_ml_common/plans/calibration_curve_plan.py +1 -6
- mlrun/frameworks/_ml_common/plans/confusion_matrix_plan.py +1 -1
- mlrun/frameworks/_ml_common/plans/dataset_plan.py +1 -1
- mlrun/frameworks/_ml_common/plans/feature_importance_plan.py +1 -1
- mlrun/frameworks/_ml_common/plans/roc_curve_plan.py +1 -1
- mlrun/frameworks/_ml_common/producer.py +1 -1
- mlrun/frameworks/_ml_common/utils.py +1 -1
- mlrun/frameworks/auto_mlrun/__init__.py +1 -1
- mlrun/frameworks/auto_mlrun/auto_mlrun.py +1 -1
- mlrun/frameworks/huggingface/__init__.py +1 -1
- mlrun/frameworks/huggingface/model_server.py +1 -1
- mlrun/frameworks/lgbm/__init__.py +1 -1
- mlrun/frameworks/lgbm/callbacks/__init__.py +1 -1
- mlrun/frameworks/lgbm/callbacks/callback.py +1 -1
- mlrun/frameworks/lgbm/callbacks/logging_callback.py +1 -1
- mlrun/frameworks/lgbm/callbacks/mlrun_logging_callback.py +1 -1
- mlrun/frameworks/lgbm/mlrun_interfaces/__init__.py +1 -1
- mlrun/frameworks/lgbm/mlrun_interfaces/booster_mlrun_interface.py +1 -1
- mlrun/frameworks/lgbm/mlrun_interfaces/mlrun_interface.py +1 -1
- mlrun/frameworks/lgbm/mlrun_interfaces/model_mlrun_interface.py +1 -1
- mlrun/frameworks/lgbm/model_handler.py +1 -1
- mlrun/frameworks/lgbm/model_server.py +1 -1
- mlrun/frameworks/lgbm/utils.py +1 -1
- mlrun/frameworks/onnx/__init__.py +1 -1
- mlrun/frameworks/onnx/dataset.py +1 -1
- mlrun/frameworks/onnx/mlrun_interface.py +1 -1
- mlrun/frameworks/onnx/model_handler.py +1 -1
- mlrun/frameworks/onnx/model_server.py +1 -1
- mlrun/frameworks/parallel_coordinates.py +1 -1
- mlrun/frameworks/pytorch/__init__.py +1 -1
- mlrun/frameworks/pytorch/callbacks/__init__.py +1 -1
- mlrun/frameworks/pytorch/callbacks/callback.py +1 -1
- mlrun/frameworks/pytorch/callbacks/logging_callback.py +1 -1
- mlrun/frameworks/pytorch/callbacks/mlrun_logging_callback.py +1 -1
- mlrun/frameworks/pytorch/callbacks/tensorboard_logging_callback.py +1 -1
- mlrun/frameworks/pytorch/callbacks_handler.py +1 -1
- mlrun/frameworks/pytorch/mlrun_interface.py +1 -1
- mlrun/frameworks/pytorch/model_handler.py +1 -1
- mlrun/frameworks/pytorch/model_server.py +1 -1
- mlrun/frameworks/pytorch/utils.py +1 -1
- mlrun/frameworks/sklearn/__init__.py +1 -1
- mlrun/frameworks/sklearn/estimator.py +1 -1
- mlrun/frameworks/sklearn/metric.py +1 -1
- mlrun/frameworks/sklearn/metrics_library.py +1 -1
- mlrun/frameworks/sklearn/mlrun_interface.py +1 -1
- mlrun/frameworks/sklearn/model_handler.py +1 -1
- mlrun/frameworks/sklearn/utils.py +1 -1
- mlrun/frameworks/tf_keras/__init__.py +1 -1
- mlrun/frameworks/tf_keras/callbacks/__init__.py +1 -1
- mlrun/frameworks/tf_keras/callbacks/logging_callback.py +1 -1
- mlrun/frameworks/tf_keras/callbacks/mlrun_logging_callback.py +1 -1
- mlrun/frameworks/tf_keras/callbacks/tensorboard_logging_callback.py +1 -1
- mlrun/frameworks/tf_keras/mlrun_interface.py +1 -1
- mlrun/frameworks/tf_keras/model_handler.py +1 -1
- mlrun/frameworks/tf_keras/model_server.py +1 -1
- mlrun/frameworks/tf_keras/utils.py +1 -1
- mlrun/frameworks/xgboost/__init__.py +1 -1
- mlrun/frameworks/xgboost/mlrun_interface.py +1 -1
- mlrun/frameworks/xgboost/model_handler.py +1 -1
- mlrun/frameworks/xgboost/utils.py +1 -1
- mlrun/k8s_utils.py +14 -765
- mlrun/kfpops.py +14 -17
- mlrun/launcher/__init__.py +13 -0
- mlrun/launcher/base.py +406 -0
- mlrun/launcher/client.py +159 -0
- mlrun/launcher/factory.py +50 -0
- mlrun/launcher/local.py +276 -0
- mlrun/launcher/remote.py +178 -0
- mlrun/lists.py +10 -2
- mlrun/mlutils/__init__.py +1 -1
- mlrun/mlutils/data.py +1 -1
- mlrun/mlutils/models.py +1 -1
- mlrun/mlutils/plots.py +1 -1
- mlrun/model.py +252 -14
- mlrun/model_monitoring/__init__.py +41 -0
- mlrun/model_monitoring/features_drift_table.py +1 -1
- mlrun/model_monitoring/helpers.py +123 -38
- mlrun/model_monitoring/model_endpoint.py +144 -0
- mlrun/model_monitoring/model_monitoring_batch.py +310 -259
- mlrun/model_monitoring/stores/__init__.py +106 -0
- mlrun/model_monitoring/stores/kv_model_endpoint_store.py +448 -0
- mlrun/model_monitoring/stores/model_endpoint_store.py +147 -0
- mlrun/model_monitoring/stores/models/__init__.py +23 -0
- mlrun/model_monitoring/stores/models/base.py +18 -0
- mlrun/model_monitoring/stores/models/mysql.py +100 -0
- mlrun/model_monitoring/stores/models/sqlite.py +98 -0
- mlrun/model_monitoring/stores/sql_model_endpoint_store.py +370 -0
- mlrun/model_monitoring/stream_processing_fs.py +239 -271
- mlrun/package/__init__.py +163 -0
- mlrun/package/context_handler.py +325 -0
- mlrun/package/errors.py +47 -0
- mlrun/package/packager.py +298 -0
- mlrun/{runtimes/package → package/packagers}/__init__.py +3 -1
- mlrun/package/packagers/default_packager.py +422 -0
- mlrun/package/packagers/numpy_packagers.py +612 -0
- mlrun/package/packagers/pandas_packagers.py +968 -0
- mlrun/package/packagers/python_standard_library_packagers.py +616 -0
- mlrun/package/packagers_manager.py +786 -0
- mlrun/package/utils/__init__.py +53 -0
- mlrun/package/utils/_archiver.py +226 -0
- mlrun/package/utils/_formatter.py +211 -0
- mlrun/package/utils/_pickler.py +234 -0
- mlrun/package/utils/_supported_format.py +71 -0
- mlrun/package/utils/log_hint_utils.py +93 -0
- mlrun/package/utils/type_hint_utils.py +298 -0
- mlrun/platforms/__init__.py +1 -1
- mlrun/platforms/iguazio.py +34 -2
- mlrun/platforms/other.py +1 -1
- mlrun/projects/__init__.py +1 -1
- mlrun/projects/operations.py +14 -9
- mlrun/projects/pipelines.py +31 -13
- mlrun/projects/project.py +762 -238
- mlrun/render.py +49 -19
- mlrun/run.py +57 -326
- mlrun/runtimes/__init__.py +3 -9
- mlrun/runtimes/base.py +247 -784
- mlrun/runtimes/constants.py +1 -1
- mlrun/runtimes/daskjob.py +45 -41
- mlrun/runtimes/funcdoc.py +43 -7
- mlrun/runtimes/function.py +66 -656
- mlrun/runtimes/function_reference.py +1 -1
- mlrun/runtimes/generators.py +1 -1
- mlrun/runtimes/kubejob.py +99 -116
- mlrun/runtimes/local.py +59 -66
- mlrun/runtimes/mpijob/__init__.py +1 -1
- mlrun/runtimes/mpijob/abstract.py +13 -15
- mlrun/runtimes/mpijob/v1.py +3 -1
- mlrun/runtimes/mpijob/v1alpha1.py +1 -1
- mlrun/runtimes/nuclio.py +1 -1
- mlrun/runtimes/pod.py +51 -26
- mlrun/runtimes/remotesparkjob.py +3 -1
- mlrun/runtimes/serving.py +12 -4
- mlrun/runtimes/sparkjob/__init__.py +1 -2
- mlrun/runtimes/sparkjob/abstract.py +44 -31
- mlrun/runtimes/sparkjob/spark3job.py +11 -9
- mlrun/runtimes/utils.py +61 -42
- mlrun/secrets.py +16 -18
- mlrun/serving/__init__.py +3 -2
- mlrun/serving/merger.py +1 -1
- mlrun/serving/remote.py +1 -1
- mlrun/serving/routers.py +39 -42
- mlrun/serving/server.py +23 -13
- mlrun/serving/serving_wrapper.py +1 -1
- mlrun/serving/states.py +172 -39
- mlrun/serving/utils.py +1 -1
- mlrun/serving/v1_serving.py +1 -1
- mlrun/serving/v2_serving.py +29 -21
- mlrun/utils/__init__.py +1 -2
- mlrun/utils/async_http.py +8 -1
- mlrun/utils/azure_vault.py +1 -1
- mlrun/utils/clones.py +2 -2
- mlrun/utils/condition_evaluator.py +65 -0
- mlrun/utils/db.py +52 -0
- mlrun/utils/helpers.py +188 -13
- mlrun/utils/http.py +89 -54
- mlrun/utils/logger.py +48 -8
- mlrun/utils/model_monitoring.py +132 -100
- mlrun/utils/notifications/__init__.py +1 -1
- mlrun/utils/notifications/notification/__init__.py +8 -6
- mlrun/utils/notifications/notification/base.py +20 -14
- mlrun/utils/notifications/notification/console.py +7 -4
- mlrun/utils/notifications/notification/git.py +36 -19
- mlrun/utils/notifications/notification/ipython.py +10 -8
- mlrun/utils/notifications/notification/slack.py +18 -13
- mlrun/utils/notifications/notification_pusher.py +377 -56
- mlrun/utils/regex.py +6 -1
- mlrun/utils/singleton.py +1 -1
- mlrun/utils/v3io_clients.py +1 -1
- mlrun/utils/vault.py +270 -269
- mlrun/utils/version/__init__.py +1 -1
- mlrun/utils/version/version.json +2 -2
- mlrun/utils/version/version.py +1 -1
- {mlrun-1.3.3rc1.dist-info → mlrun-1.4.0.dist-info}/METADATA +16 -10
- mlrun-1.4.0.dist-info/RECORD +434 -0
- mlrun/api/api/endpoints/marketplace.py +0 -257
- mlrun/api/crud/marketplace.py +0 -221
- mlrun/api/crud/model_monitoring/model_endpoint_store.py +0 -847
- mlrun/api/db/filedb/db.py +0 -518
- mlrun/api/schemas/marketplace.py +0 -128
- mlrun/api/schemas/model_endpoints.py +0 -185
- mlrun/db/filedb.py +0 -891
- mlrun/feature_store/retrieval/online.py +0 -92
- mlrun/model_monitoring/constants.py +0 -67
- mlrun/runtimes/package/context_handler.py +0 -711
- mlrun/runtimes/sparkjob/spark2job.py +0 -59
- mlrun-1.3.3rc1.dist-info/RECORD +0 -381
- {mlrun-1.3.3rc1.dist-info → mlrun-1.4.0.dist-info}/LICENSE +0 -0
- {mlrun-1.3.3rc1.dist-info → mlrun-1.4.0.dist-info}/WHEEL +0 -0
- {mlrun-1.3.3rc1.dist-info → mlrun-1.4.0.dist-info}/entry_points.txt +0 -0
- {mlrun-1.3.3rc1.dist-info → mlrun-1.4.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
# Copyright 2023 Iguazio
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
#
|
|
15
|
+
import importlib
|
|
16
|
+
import os
|
|
17
|
+
import sys
|
|
18
|
+
import tempfile
|
|
19
|
+
import warnings
|
|
20
|
+
from types import ModuleType
|
|
21
|
+
from typing import Any, Dict, Tuple, Union
|
|
22
|
+
|
|
23
|
+
from mlrun.errors import MLRunInvalidArgumentError
|
|
24
|
+
from mlrun.utils import logger
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class Pickler:
|
|
28
|
+
"""
|
|
29
|
+
A static class to pickle objects with multiple modules while capturing the environment of the pickled object. The
|
|
30
|
+
pickler will raise warnings in case the object is un-pickled in a mismatching environment (different modules
|
|
31
|
+
and / or python versions)
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
@staticmethod
|
|
35
|
+
def pickle(
|
|
36
|
+
obj: Any, pickle_module_name: str, output_path: str = None
|
|
37
|
+
) -> Tuple[str, Dict[str, Union[str, None]]]:
|
|
38
|
+
"""
|
|
39
|
+
Pickle an object using the given module. The pickled object will be saved to file to the given output path.
|
|
40
|
+
|
|
41
|
+
:param obj: The object to pickle.
|
|
42
|
+
:param pickle_module_name: The pickle module to use. For example: "pickle", "joblib", "cloudpickle".
|
|
43
|
+
:param output_path: The output path to save the 'pkl' file to. If not provided, the pickle will be saved
|
|
44
|
+
to a temporary directory. The user is responsible to clean the temporary directory.
|
|
45
|
+
|
|
46
|
+
:return: A tuple of the path of the 'pkl' file and the instructions the pickler noted.
|
|
47
|
+
"""
|
|
48
|
+
# Get the pickle module:
|
|
49
|
+
pickle_module = importlib.import_module(pickle_module_name)
|
|
50
|
+
Pickler._validate_pickle_module(pickle_module=pickle_module)
|
|
51
|
+
pickle_module_version = Pickler._get_module_version(
|
|
52
|
+
module_name=pickle_module_name
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
# Get the object's module (module name can be extracted usually from the object's class):
|
|
56
|
+
object_module_name = (
|
|
57
|
+
obj.__module__.split(".")[0]
|
|
58
|
+
if hasattr(obj, "__module__")
|
|
59
|
+
else type(obj).__module__.split(".")[0]
|
|
60
|
+
)
|
|
61
|
+
object_module_version = Pickler._get_module_version(
|
|
62
|
+
module_name=object_module_name
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
# Get the python version:
|
|
66
|
+
python_version = Pickler._get_python_version()
|
|
67
|
+
|
|
68
|
+
# Construct the pickler labels dictionary (versions may not be available):
|
|
69
|
+
instructions = {
|
|
70
|
+
"object_module_name": object_module_name,
|
|
71
|
+
"pickle_module_name": pickle_module_name,
|
|
72
|
+
"python_version": python_version,
|
|
73
|
+
}
|
|
74
|
+
if object_module_version is not None:
|
|
75
|
+
instructions["object_module_version"] = object_module_version
|
|
76
|
+
if pickle_module_version is not None:
|
|
77
|
+
instructions["pickle_module_version"] = pickle_module_version
|
|
78
|
+
|
|
79
|
+
# Generate a temporary output path if not provided:
|
|
80
|
+
if output_path is None:
|
|
81
|
+
output_path = os.path.join(tempfile.mkdtemp(), "obj.pkl")
|
|
82
|
+
|
|
83
|
+
# Pickle the object to file:
|
|
84
|
+
with open(output_path, "wb") as pkl_file:
|
|
85
|
+
pickle_module.dump(obj, pkl_file)
|
|
86
|
+
|
|
87
|
+
return output_path, instructions
|
|
88
|
+
|
|
89
|
+
@staticmethod
|
|
90
|
+
def unpickle(
|
|
91
|
+
pickle_path: str,
|
|
92
|
+
pickle_module_name: str,
|
|
93
|
+
object_module_name: str = None,
|
|
94
|
+
python_version: str = None,
|
|
95
|
+
pickle_module_version: str = None,
|
|
96
|
+
object_module_version: str = None,
|
|
97
|
+
) -> Any:
|
|
98
|
+
"""
|
|
99
|
+
Unpickle an object using the given instructions. Warnings may be raised in case any of the versions are
|
|
100
|
+
mismatching (only if provided - not None).
|
|
101
|
+
|
|
102
|
+
:param pickle_path: Path to the 'pkl' file to un-pickle.
|
|
103
|
+
:param pickle_module_name: Module to use for unpickling the object.
|
|
104
|
+
:param object_module_name: The original object's module. Used to verify the current interpreter object module
|
|
105
|
+
version match the pickled object version before unpickling the object.
|
|
106
|
+
:param python_version: The python version in which the original object was pickled. Used to verify the
|
|
107
|
+
current interpreter python version match the pickled object version before
|
|
108
|
+
unpickling the object.
|
|
109
|
+
:param pickle_module_version: The pickle module version. Used to verify the current interpreter module version
|
|
110
|
+
match the one who pickled the object before unpickling it.
|
|
111
|
+
:param object_module_version: The original object's module version to match to the interpreter's module version.
|
|
112
|
+
|
|
113
|
+
:return: The un-pickled object.
|
|
114
|
+
"""
|
|
115
|
+
# Check the python version against the pickled object:
|
|
116
|
+
if python_version is not None:
|
|
117
|
+
current_python_version = Pickler._get_python_version()
|
|
118
|
+
if python_version != current_python_version:
|
|
119
|
+
logger.warn(
|
|
120
|
+
f"MLRun is trying to load an object that was pickled on python version "
|
|
121
|
+
f"'{python_version}' but the current python version is '{current_python_version}'. "
|
|
122
|
+
f"When using pickle, it is recommended to save and load an object on the same python version to "
|
|
123
|
+
f"reduce unexpected errors."
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
# Get the pickle module:
|
|
127
|
+
pickle_module = importlib.import_module(pickle_module_name)
|
|
128
|
+
Pickler._validate_pickle_module(pickle_module=pickle_module)
|
|
129
|
+
|
|
130
|
+
# Check the pickle module against the pickled object (only if the version is given):
|
|
131
|
+
if pickle_module_version is not None:
|
|
132
|
+
current_pickle_module_version = Pickler._get_module_version(
|
|
133
|
+
module_name=pickle_module_name
|
|
134
|
+
)
|
|
135
|
+
if pickle_module_version != current_pickle_module_version:
|
|
136
|
+
logger.warn(
|
|
137
|
+
f"MLRun is trying to load an object that was pickled using "
|
|
138
|
+
f"{pickle_module_name} version {pickle_module_version} but the current module version is "
|
|
139
|
+
f"'{current_pickle_module_version}'. "
|
|
140
|
+
f"When using pickle, it is recommended to save and load an "
|
|
141
|
+
f"object using the same pickling module version to reduce unexpected errors."
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
# Check the object module against the pickled object (only if the version is given):
|
|
145
|
+
if object_module_version is not None and object_module_name is not None:
|
|
146
|
+
current_object_module_version = Pickler._get_module_version(
|
|
147
|
+
module_name=object_module_name
|
|
148
|
+
)
|
|
149
|
+
if object_module_version != current_object_module_version:
|
|
150
|
+
logger.warn(
|
|
151
|
+
f"MLRun is trying to load an object from module {object_module_name} version "
|
|
152
|
+
f"{object_module_version} but the current module version is '{current_object_module_version}'. "
|
|
153
|
+
f"When using pickle, it is recommended to save and load an object using "
|
|
154
|
+
f"the same exact module version to reduce unexpected errors."
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
# Load the object from the pickle file:
|
|
158
|
+
with open(pickle_path, "rb") as pickle_file:
|
|
159
|
+
obj = pickle_module.load(pickle_file)
|
|
160
|
+
|
|
161
|
+
return obj
|
|
162
|
+
|
|
163
|
+
@staticmethod
|
|
164
|
+
def _validate_pickle_module(pickle_module: ModuleType):
|
|
165
|
+
"""
|
|
166
|
+
Validate the pickle module to use have a `dump` and `load` functions so the Pickler can use it.
|
|
167
|
+
|
|
168
|
+
:param pickle_module: The pickle module tot validate.
|
|
169
|
+
|
|
170
|
+
:raise MLRunInvalidArgumentError: If the pickle module is not valid.
|
|
171
|
+
"""
|
|
172
|
+
for function_name in ["dump", "load"]:
|
|
173
|
+
if not hasattr(pickle_module, function_name):
|
|
174
|
+
raise MLRunInvalidArgumentError(
|
|
175
|
+
f"A pickle module is expected to have a `{function_name}` function but the provided module "
|
|
176
|
+
f"{pickle_module.__name__} does not have it."
|
|
177
|
+
)
|
|
178
|
+
|
|
179
|
+
@staticmethod
|
|
180
|
+
def _get_module_version(module_name: str) -> Union[str, None]:
|
|
181
|
+
"""
|
|
182
|
+
Get a module's version. Most updated modules have versions but some don't. In case the version could not be
|
|
183
|
+
read, None is returned.
|
|
184
|
+
|
|
185
|
+
:param module_name: The module's name to get its version.
|
|
186
|
+
|
|
187
|
+
:return: The module's version if found and None otherwise.
|
|
188
|
+
"""
|
|
189
|
+
# First we'll try to get the module version from `importlib`:
|
|
190
|
+
try:
|
|
191
|
+
# Since Python 3.8, `version` is part of `importlib.metadata`. Before 3.8, we'll use the module
|
|
192
|
+
# `importlib_metadata` to get `version`.
|
|
193
|
+
if (
|
|
194
|
+
sys.version_info[1] > 7
|
|
195
|
+
): # TODO: Remove once Python 3.7 is not supported.
|
|
196
|
+
from importlib.metadata import version
|
|
197
|
+
else:
|
|
198
|
+
from importlib_metadata import version
|
|
199
|
+
|
|
200
|
+
return version(module_name)
|
|
201
|
+
except (ModuleNotFoundError, importlib.metadata.PackageNotFoundError):
|
|
202
|
+
# User won't necessarily have the `importlib_metadata` module, so we will ignore it by catching
|
|
203
|
+
# `ModuleNotFoundError`. `PackageNotFoundError` is ignored as well as this is raised when `version` could
|
|
204
|
+
# not find the package related to the module.
|
|
205
|
+
pass
|
|
206
|
+
|
|
207
|
+
# Secondly, if importlib could not get the version (most likely 'importlib_metadata' is not installed), we'll
|
|
208
|
+
# try to use `pkg_resources` to get the version (the version will be found only if the package name is equal to
|
|
209
|
+
# the module name. For example, if the module name is 'x' then the way we installed the package must be
|
|
210
|
+
# 'pip install x'):
|
|
211
|
+
import pkg_resources
|
|
212
|
+
|
|
213
|
+
with warnings.catch_warnings():
|
|
214
|
+
# If a module's package is not found, a `PkgResourcesDeprecationWarning` warning will be raised and then
|
|
215
|
+
# `DistributionNotFound` exception will be raised, so we ignore them both:
|
|
216
|
+
warnings.filterwarnings(
|
|
217
|
+
"ignore", category=pkg_resources.PkgResourcesDeprecationWarning
|
|
218
|
+
)
|
|
219
|
+
try:
|
|
220
|
+
return pkg_resources.get_distribution(module_name).version
|
|
221
|
+
except pkg_resources.DistributionNotFound:
|
|
222
|
+
pass
|
|
223
|
+
|
|
224
|
+
# The version could not be found.
|
|
225
|
+
return None
|
|
226
|
+
|
|
227
|
+
@staticmethod
|
|
228
|
+
def _get_python_version() -> str:
|
|
229
|
+
"""
|
|
230
|
+
Get the current running python's version.
|
|
231
|
+
|
|
232
|
+
:return: The python version string.
|
|
233
|
+
"""
|
|
234
|
+
return f"{sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}"
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# Copyright 2023 Iguazio
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
#
|
|
15
|
+
from abc import ABC
|
|
16
|
+
from typing import Dict, Generic, List, Type, TypeVar, Union
|
|
17
|
+
|
|
18
|
+
# A generic type for a supported format handler class type:
|
|
19
|
+
FileHandlerType = TypeVar("FileHandlerType")
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class SupportedFormat(ABC, Generic[FileHandlerType]):
|
|
23
|
+
"""
|
|
24
|
+
Library of supported formats by some builtin MLRun packagers.
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
# Add here the all the supported formats in ALL CAPS and their value as a string:
|
|
28
|
+
...
|
|
29
|
+
|
|
30
|
+
# The map to use in the method `get_format_handler`. A dictionary of string key to a class type to handle that
|
|
31
|
+
# format. New supported formats and handlers should be added to it:
|
|
32
|
+
_FORMAT_HANDLERS_MAP: Dict[str, Type[FileHandlerType]] = {}
|
|
33
|
+
|
|
34
|
+
@classmethod
|
|
35
|
+
def get_all_formats(cls) -> List[str]:
|
|
36
|
+
"""
|
|
37
|
+
Get all supported formats.
|
|
38
|
+
|
|
39
|
+
:return: A list of all the supported formats.
|
|
40
|
+
"""
|
|
41
|
+
return [
|
|
42
|
+
value
|
|
43
|
+
for key, value in cls.__dict__.items()
|
|
44
|
+
if isinstance(value, str) and not key.startswith("_")
|
|
45
|
+
]
|
|
46
|
+
|
|
47
|
+
@classmethod
|
|
48
|
+
def get_format_handler(cls, fmt: str) -> Type[FileHandlerType]:
|
|
49
|
+
"""
|
|
50
|
+
Get the format handler to the provided format (file extension):
|
|
51
|
+
|
|
52
|
+
:param fmt: The file extension to get the corresponding handler.
|
|
53
|
+
|
|
54
|
+
:return: The handler class.
|
|
55
|
+
"""
|
|
56
|
+
return cls._FORMAT_HANDLERS_MAP[fmt]
|
|
57
|
+
|
|
58
|
+
@classmethod
|
|
59
|
+
def match_format(cls, path: str) -> Union[str, None]:
|
|
60
|
+
"""
|
|
61
|
+
Try to match one of the available formats this class holds to a given path.
|
|
62
|
+
|
|
63
|
+
:param path: The path to match the format to.
|
|
64
|
+
|
|
65
|
+
:return: The matched format if found and None otherwise.
|
|
66
|
+
"""
|
|
67
|
+
formats = cls.get_all_formats()
|
|
68
|
+
for fmt in formats:
|
|
69
|
+
if path.endswith(f".{fmt}"):
|
|
70
|
+
return fmt
|
|
71
|
+
return None
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# Copyright 2023 Iguazio
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
#
|
|
15
|
+
import typing
|
|
16
|
+
|
|
17
|
+
from mlrun.errors import MLRunInvalidArgumentError
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class LogHintKey:
|
|
21
|
+
"""
|
|
22
|
+
Known keys for a log hint to have.
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
KEY = "key"
|
|
26
|
+
ARTIFACT_TYPE = "artifact_type"
|
|
27
|
+
EXTRA_DATA = "extra_data"
|
|
28
|
+
METRICS = "metrics"
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class LogHintUtils:
|
|
32
|
+
"""
|
|
33
|
+
Static class for utilities functions to process log hints.
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
@staticmethod
|
|
37
|
+
def parse_log_hint(
|
|
38
|
+
log_hint: typing.Union[typing.Dict[str, str], str, None]
|
|
39
|
+
) -> typing.Union[typing.Dict[str, str], None]:
|
|
40
|
+
"""
|
|
41
|
+
Parse a given log hint from string to a logging configuration dictionary. The string will be read as the
|
|
42
|
+
artifact key ('key' in the dictionary) and if the string have a single colon, the following structure is
|
|
43
|
+
assumed: "<artifact_key> : <artifact_type>".
|
|
44
|
+
|
|
45
|
+
If a logging configuration dictionary is received, it will be validated to have a key field.
|
|
46
|
+
|
|
47
|
+
None will be returned as None.
|
|
48
|
+
|
|
49
|
+
:param log_hint: The log hint to parse.
|
|
50
|
+
|
|
51
|
+
:return: The hinted logging configuration.
|
|
52
|
+
|
|
53
|
+
:raise MLRunInvalidArgumentError: In case the log hint is not following the string structure or the dictionary
|
|
54
|
+
is missing the key field.
|
|
55
|
+
"""
|
|
56
|
+
# Check for None value:
|
|
57
|
+
if log_hint is None:
|
|
58
|
+
return None
|
|
59
|
+
|
|
60
|
+
# If the log hint was provided as a string, construct a dictionary out of it:
|
|
61
|
+
if isinstance(log_hint, str):
|
|
62
|
+
# Check if only key is given:
|
|
63
|
+
if ":" not in log_hint:
|
|
64
|
+
log_hint = {LogHintKey.KEY: log_hint}
|
|
65
|
+
# Check for valid "<key> : <artifact type>" pattern:
|
|
66
|
+
else:
|
|
67
|
+
if log_hint.count(":") > 1:
|
|
68
|
+
raise MLRunInvalidArgumentError(
|
|
69
|
+
f"Incorrect log hint pattern. Log hints can have only a single ':' in them to specify the "
|
|
70
|
+
f"desired artifact type the returned value will be logged as: "
|
|
71
|
+
f"'<artifact_key> : <artifact_type>', but given: {log_hint}"
|
|
72
|
+
)
|
|
73
|
+
# Split into key and type:
|
|
74
|
+
key, artifact_type = log_hint.replace(" ", "").split(":")
|
|
75
|
+
if artifact_type == "":
|
|
76
|
+
raise MLRunInvalidArgumentError(
|
|
77
|
+
f"Incorrect log hint pattern. The ':' in a log hint should specify the desired artifact type "
|
|
78
|
+
f"the returned value will be logged as in the following pattern: "
|
|
79
|
+
f"'<artifact_key> : <artifact_type>', but no artifact type was given: {log_hint}"
|
|
80
|
+
)
|
|
81
|
+
log_hint = {
|
|
82
|
+
LogHintKey.KEY: key,
|
|
83
|
+
LogHintKey.ARTIFACT_TYPE: artifact_type,
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
# Validate the log hint dictionary has the mandatory key:
|
|
87
|
+
if LogHintKey.KEY not in log_hint:
|
|
88
|
+
raise MLRunInvalidArgumentError(
|
|
89
|
+
f"A log hint dictionary must include the 'key' - the artifact key (it's name). The following log hint "
|
|
90
|
+
f"is missing the key: {log_hint}."
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
return log_hint
|