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
mlrun/db/filedb.py
DELETED
|
@@ -1,891 +0,0 @@
|
|
|
1
|
-
# Copyright 2018 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 json
|
|
16
|
-
import pathlib
|
|
17
|
-
from datetime import datetime, timedelta, timezone
|
|
18
|
-
from os import listdir, makedirs, path, remove, scandir
|
|
19
|
-
from typing import List, Optional, Union
|
|
20
|
-
|
|
21
|
-
import yaml
|
|
22
|
-
from dateutil.parser import parse as parse_time
|
|
23
|
-
|
|
24
|
-
import mlrun.api.schemas
|
|
25
|
-
import mlrun.errors
|
|
26
|
-
|
|
27
|
-
from ..api import schemas
|
|
28
|
-
from ..api.schemas import ModelEndpoint
|
|
29
|
-
from ..config import config
|
|
30
|
-
from ..datastore import store_manager
|
|
31
|
-
from ..lists import ArtifactList, RunList
|
|
32
|
-
from ..utils import (
|
|
33
|
-
dict_to_json,
|
|
34
|
-
dict_to_yaml,
|
|
35
|
-
fill_function_hash,
|
|
36
|
-
generate_object_uri,
|
|
37
|
-
get_in,
|
|
38
|
-
logger,
|
|
39
|
-
match_labels,
|
|
40
|
-
match_times,
|
|
41
|
-
match_value,
|
|
42
|
-
match_value_options,
|
|
43
|
-
update_in,
|
|
44
|
-
)
|
|
45
|
-
from .base import RunDBError, RunDBInterface
|
|
46
|
-
|
|
47
|
-
run_logs = "runs"
|
|
48
|
-
artifacts_dir = "artifacts"
|
|
49
|
-
functions_dir = "functions"
|
|
50
|
-
schedules_dir = "schedules"
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
# TODO: remove fileDB, doesn't needs to be used anymore
|
|
54
|
-
class FileRunDB(RunDBInterface):
|
|
55
|
-
kind = "file"
|
|
56
|
-
|
|
57
|
-
def __init__(self, dirpath="", format=".yaml"):
|
|
58
|
-
self.format = format
|
|
59
|
-
self.dirpath = dirpath
|
|
60
|
-
self._datastore = None
|
|
61
|
-
self._subpath = None
|
|
62
|
-
self._secrets = None
|
|
63
|
-
makedirs(self.schedules_dir, exist_ok=True)
|
|
64
|
-
|
|
65
|
-
def connect(self, secrets=None):
|
|
66
|
-
self._secrets = secrets
|
|
67
|
-
return self
|
|
68
|
-
|
|
69
|
-
def _connect(self, secrets=None):
|
|
70
|
-
sm = store_manager.set(secrets or self._secrets)
|
|
71
|
-
self._datastore, self._subpath = sm.get_or_create_store(self.dirpath)
|
|
72
|
-
return self
|
|
73
|
-
|
|
74
|
-
@property
|
|
75
|
-
def datastore(self):
|
|
76
|
-
if not self._datastore:
|
|
77
|
-
self._connect()
|
|
78
|
-
return self._datastore
|
|
79
|
-
|
|
80
|
-
def store_log(self, uid, project="", body=None, append=False):
|
|
81
|
-
filepath = self._filepath(run_logs, project, uid, "") + ".log"
|
|
82
|
-
makedirs(path.dirname(filepath), exist_ok=True)
|
|
83
|
-
mode = "ab" if append else "wb"
|
|
84
|
-
with open(filepath, mode) as fp:
|
|
85
|
-
fp.write(body)
|
|
86
|
-
fp.close()
|
|
87
|
-
|
|
88
|
-
def get_log(self, uid, project="", offset=0, size=0):
|
|
89
|
-
filepath = self._filepath(run_logs, project, uid, "") + ".log"
|
|
90
|
-
if pathlib.Path(filepath).is_file():
|
|
91
|
-
with open(filepath, "rb") as fp:
|
|
92
|
-
if offset:
|
|
93
|
-
fp.seek(offset)
|
|
94
|
-
if not size:
|
|
95
|
-
size = 2**18
|
|
96
|
-
return "", fp.read(size)
|
|
97
|
-
return "", None
|
|
98
|
-
|
|
99
|
-
def _run_path(self, uid, iter):
|
|
100
|
-
if iter:
|
|
101
|
-
return f"{uid}-{iter}"
|
|
102
|
-
return uid
|
|
103
|
-
|
|
104
|
-
def store_run(self, struct, uid, project="", iter=0):
|
|
105
|
-
data = self._dumps(struct)
|
|
106
|
-
filepath = (
|
|
107
|
-
self._filepath(run_logs, project, self._run_path(uid, iter), "")
|
|
108
|
-
+ self.format
|
|
109
|
-
)
|
|
110
|
-
self.datastore.put(filepath, data)
|
|
111
|
-
|
|
112
|
-
def update_run(self, updates: dict, uid, project="", iter=0):
|
|
113
|
-
run = self.read_run(uid, project, iter=iter)
|
|
114
|
-
if run and updates:
|
|
115
|
-
for key, val in updates.items():
|
|
116
|
-
update_in(run, key, val)
|
|
117
|
-
self.store_run(run, uid, project, iter=iter)
|
|
118
|
-
|
|
119
|
-
def abort_run(self, uid, project="", iter=0):
|
|
120
|
-
raise NotImplementedError()
|
|
121
|
-
|
|
122
|
-
def read_run(self, uid, project="", iter=0):
|
|
123
|
-
filepath = (
|
|
124
|
-
self._filepath(run_logs, project, self._run_path(uid, iter), "")
|
|
125
|
-
+ self.format
|
|
126
|
-
)
|
|
127
|
-
if not pathlib.Path(filepath).is_file():
|
|
128
|
-
raise mlrun.errors.MLRunNotFoundError(uid)
|
|
129
|
-
data = self.datastore.get(filepath)
|
|
130
|
-
return self._loads(data)
|
|
131
|
-
|
|
132
|
-
def list_runs(
|
|
133
|
-
self,
|
|
134
|
-
name="",
|
|
135
|
-
uid: Optional[Union[str, List[str]]] = None,
|
|
136
|
-
project="",
|
|
137
|
-
labels=None,
|
|
138
|
-
state="",
|
|
139
|
-
sort=True,
|
|
140
|
-
last=1000,
|
|
141
|
-
iter=False,
|
|
142
|
-
start_time_from: datetime = None,
|
|
143
|
-
start_time_to: datetime = None,
|
|
144
|
-
last_update_time_from: datetime = None,
|
|
145
|
-
last_update_time_to: datetime = None,
|
|
146
|
-
partition_by: Union[schemas.RunPartitionByField, str] = None,
|
|
147
|
-
rows_per_partition: int = 1,
|
|
148
|
-
partition_sort_by: Union[schemas.SortField, str] = None,
|
|
149
|
-
partition_order: Union[schemas.OrderType, str] = schemas.OrderType.desc,
|
|
150
|
-
max_partitions: int = 0,
|
|
151
|
-
):
|
|
152
|
-
if partition_by is not None:
|
|
153
|
-
raise mlrun.errors.MLRunInvalidArgumentError(
|
|
154
|
-
"Runs partitioning not supported"
|
|
155
|
-
)
|
|
156
|
-
if uid and isinstance(uid, list):
|
|
157
|
-
raise mlrun.errors.MLRunInvalidArgumentError(
|
|
158
|
-
"Runs list with multiple uids not supported"
|
|
159
|
-
)
|
|
160
|
-
|
|
161
|
-
labels = [] if labels is None else labels
|
|
162
|
-
filepath = self._filepath(run_logs, project)
|
|
163
|
-
results = RunList()
|
|
164
|
-
if isinstance(labels, str):
|
|
165
|
-
labels = labels.split(",")
|
|
166
|
-
for run, _ in self._load_list(filepath, "*"):
|
|
167
|
-
if (
|
|
168
|
-
match_value(name, run, "metadata.name")
|
|
169
|
-
and match_labels(get_in(run, "metadata.labels", {}), labels)
|
|
170
|
-
and match_value_options(state, run, "status.state")
|
|
171
|
-
and match_value(uid, run, "metadata.uid")
|
|
172
|
-
and match_times(
|
|
173
|
-
start_time_from,
|
|
174
|
-
start_time_to,
|
|
175
|
-
run,
|
|
176
|
-
"status.start_time",
|
|
177
|
-
)
|
|
178
|
-
and match_times(
|
|
179
|
-
last_update_time_from,
|
|
180
|
-
last_update_time_to,
|
|
181
|
-
run,
|
|
182
|
-
"status.last_update",
|
|
183
|
-
)
|
|
184
|
-
and (iter or get_in(run, "metadata.iteration", 0) == 0)
|
|
185
|
-
):
|
|
186
|
-
results.append(run)
|
|
187
|
-
|
|
188
|
-
if sort or last:
|
|
189
|
-
results.sort(
|
|
190
|
-
key=lambda i: get_in(i, ["status", "start_time"], ""), reverse=True
|
|
191
|
-
)
|
|
192
|
-
if last and len(results) > last:
|
|
193
|
-
return RunList(results[:last])
|
|
194
|
-
return results
|
|
195
|
-
|
|
196
|
-
def del_run(self, uid, project="", iter=0):
|
|
197
|
-
filepath = (
|
|
198
|
-
self._filepath(run_logs, project, self._run_path(uid, iter), "")
|
|
199
|
-
+ self.format
|
|
200
|
-
)
|
|
201
|
-
self._safe_del(filepath)
|
|
202
|
-
|
|
203
|
-
def del_runs(self, name="", project="", labels=None, state="", days_ago=0):
|
|
204
|
-
|
|
205
|
-
labels = [] if labels is None else labels
|
|
206
|
-
if not any([name, state, days_ago, labels]):
|
|
207
|
-
raise RunDBError(
|
|
208
|
-
"filter is too wide, select name and/or state and/or days_ago"
|
|
209
|
-
)
|
|
210
|
-
|
|
211
|
-
filepath = self._filepath(run_logs, project)
|
|
212
|
-
if isinstance(labels, str):
|
|
213
|
-
labels = labels.split(",")
|
|
214
|
-
|
|
215
|
-
if days_ago:
|
|
216
|
-
days_ago = datetime.now() - timedelta(days=days_ago)
|
|
217
|
-
|
|
218
|
-
def date_before(run):
|
|
219
|
-
d = get_in(run, "status.start_time", "")
|
|
220
|
-
if not d:
|
|
221
|
-
return False
|
|
222
|
-
return parse_time(d) < days_ago
|
|
223
|
-
|
|
224
|
-
for run, p in self._load_list(filepath, "*"):
|
|
225
|
-
if (
|
|
226
|
-
match_value(name, run, "metadata.name")
|
|
227
|
-
and match_labels(get_in(run, "metadata.labels", {}), labels)
|
|
228
|
-
and match_value(state, run, "status.state")
|
|
229
|
-
and (not days_ago or date_before(run))
|
|
230
|
-
):
|
|
231
|
-
self._safe_del(p)
|
|
232
|
-
|
|
233
|
-
def store_artifact(self, key, artifact, uid, iter=None, tag="", project=""):
|
|
234
|
-
if "updated" not in artifact:
|
|
235
|
-
artifact["updated"] = datetime.now(timezone.utc).isoformat()
|
|
236
|
-
data = self._dumps(artifact)
|
|
237
|
-
if iter:
|
|
238
|
-
key = f"{iter}-{key}"
|
|
239
|
-
filepath = self._filepath(artifacts_dir, project, key, uid) + self.format
|
|
240
|
-
self.datastore.put(filepath, data)
|
|
241
|
-
filepath = (
|
|
242
|
-
self._filepath(artifacts_dir, project, key, tag or "latest") + self.format
|
|
243
|
-
)
|
|
244
|
-
self.datastore.put(filepath, data)
|
|
245
|
-
|
|
246
|
-
def read_artifact(self, key, tag="", iter=None, project=""):
|
|
247
|
-
tag = tag or "latest"
|
|
248
|
-
if iter:
|
|
249
|
-
key = f"{iter}-{key}"
|
|
250
|
-
filepath = self._filepath(artifacts_dir, project, key, tag) + self.format
|
|
251
|
-
|
|
252
|
-
if not pathlib.Path(filepath).is_file():
|
|
253
|
-
raise RunDBError(key)
|
|
254
|
-
data = self.datastore.get(filepath)
|
|
255
|
-
return self._loads(data)
|
|
256
|
-
|
|
257
|
-
def list_artifacts(
|
|
258
|
-
self,
|
|
259
|
-
name="",
|
|
260
|
-
project="",
|
|
261
|
-
tag="",
|
|
262
|
-
labels=None,
|
|
263
|
-
since=None,
|
|
264
|
-
until=None,
|
|
265
|
-
iter: int = None,
|
|
266
|
-
best_iteration: bool = False,
|
|
267
|
-
kind: str = None,
|
|
268
|
-
category: Union[str, schemas.ArtifactCategories] = None,
|
|
269
|
-
):
|
|
270
|
-
if iter or kind or category:
|
|
271
|
-
raise NotImplementedError(
|
|
272
|
-
"iter/kind/category parameters are not supported for filedb implementation"
|
|
273
|
-
)
|
|
274
|
-
|
|
275
|
-
labels = [] if labels is None else labels
|
|
276
|
-
tag = tag or "latest"
|
|
277
|
-
name = name or ""
|
|
278
|
-
logger.info(f"reading artifacts in {project} name/mask: {name} tag: {tag} ...")
|
|
279
|
-
filepath = self._filepath(artifacts_dir, project, tag=tag)
|
|
280
|
-
results = ArtifactList()
|
|
281
|
-
results.tag = tag
|
|
282
|
-
if isinstance(labels, str):
|
|
283
|
-
labels = labels.split(",")
|
|
284
|
-
if tag == "*":
|
|
285
|
-
mask = "**/*" + name
|
|
286
|
-
if name:
|
|
287
|
-
mask += "*"
|
|
288
|
-
else:
|
|
289
|
-
mask = "**/*"
|
|
290
|
-
|
|
291
|
-
time_pred = make_time_pred(since, until)
|
|
292
|
-
for artifact, p in self._load_list(filepath, mask):
|
|
293
|
-
if (name == "" or name in get_in(artifact, "key", "")) and match_labels(
|
|
294
|
-
get_in(artifact, "labels", {}), labels
|
|
295
|
-
):
|
|
296
|
-
if not time_pred(artifact):
|
|
297
|
-
continue
|
|
298
|
-
if "artifacts/latest" in p:
|
|
299
|
-
artifact["tree"] = "latest"
|
|
300
|
-
results.append(artifact)
|
|
301
|
-
|
|
302
|
-
return results
|
|
303
|
-
|
|
304
|
-
def del_artifact(self, key, tag="", project=""):
|
|
305
|
-
tag = tag or "latest"
|
|
306
|
-
filepath = self._filepath(artifacts_dir, project, key, tag) + self.format
|
|
307
|
-
self._safe_del(filepath)
|
|
308
|
-
|
|
309
|
-
def del_artifacts(self, name="", project="", tag="", labels=None):
|
|
310
|
-
labels = [] if labels is None else labels
|
|
311
|
-
tag = tag or "latest"
|
|
312
|
-
filepath = self._filepath(artifacts_dir, project, tag=tag)
|
|
313
|
-
|
|
314
|
-
if isinstance(labels, str):
|
|
315
|
-
labels = labels.split(",")
|
|
316
|
-
if tag == "*":
|
|
317
|
-
mask = "**/*" + name
|
|
318
|
-
if name:
|
|
319
|
-
mask += "*"
|
|
320
|
-
else:
|
|
321
|
-
mask = "**/*"
|
|
322
|
-
|
|
323
|
-
for artifact, p in self._load_list(filepath, mask):
|
|
324
|
-
if (name == "" or name == get_in(artifact, "key", "")) and match_labels(
|
|
325
|
-
get_in(artifact, "labels", {}), labels
|
|
326
|
-
):
|
|
327
|
-
|
|
328
|
-
self._safe_del(p)
|
|
329
|
-
|
|
330
|
-
def store_function(self, function, name, project="", tag="", versioned=False):
|
|
331
|
-
tag = tag or get_in(function, "metadata.tag") or "latest"
|
|
332
|
-
hash_key = fill_function_hash(function, tag)
|
|
333
|
-
update_in(function, "metadata.updated", datetime.now(timezone.utc))
|
|
334
|
-
update_in(function, "metadata.tag", "")
|
|
335
|
-
data = self._dumps(function)
|
|
336
|
-
filepath = (
|
|
337
|
-
path.join(
|
|
338
|
-
self.dirpath,
|
|
339
|
-
functions_dir,
|
|
340
|
-
project or config.default_project,
|
|
341
|
-
name,
|
|
342
|
-
tag,
|
|
343
|
-
)
|
|
344
|
-
+ self.format
|
|
345
|
-
)
|
|
346
|
-
self.datastore.put(filepath, data)
|
|
347
|
-
if versioned:
|
|
348
|
-
|
|
349
|
-
# the "hash_key" version should not include the status
|
|
350
|
-
function["status"] = None
|
|
351
|
-
|
|
352
|
-
# versioned means we want this function to be queryable by its hash key so save another file that the
|
|
353
|
-
# hash key is the file name
|
|
354
|
-
filepath = (
|
|
355
|
-
path.join(
|
|
356
|
-
self.dirpath,
|
|
357
|
-
functions_dir,
|
|
358
|
-
project or config.default_project,
|
|
359
|
-
name,
|
|
360
|
-
hash_key,
|
|
361
|
-
)
|
|
362
|
-
+ self.format
|
|
363
|
-
)
|
|
364
|
-
data = self._dumps(function)
|
|
365
|
-
self.datastore.put(filepath, data)
|
|
366
|
-
return hash_key
|
|
367
|
-
|
|
368
|
-
def get_function(self, name, project="", tag="", hash_key=""):
|
|
369
|
-
tag = tag or "latest"
|
|
370
|
-
file_name = hash_key or tag
|
|
371
|
-
filepath = (
|
|
372
|
-
path.join(
|
|
373
|
-
self.dirpath,
|
|
374
|
-
functions_dir,
|
|
375
|
-
project or config.default_project,
|
|
376
|
-
name,
|
|
377
|
-
file_name,
|
|
378
|
-
)
|
|
379
|
-
+ self.format
|
|
380
|
-
)
|
|
381
|
-
if not pathlib.Path(filepath).is_file():
|
|
382
|
-
function_uri = generate_object_uri(project, name, tag, hash_key)
|
|
383
|
-
raise mlrun.errors.MLRunNotFoundError(f"Function not found {function_uri}")
|
|
384
|
-
data = self.datastore.get(filepath)
|
|
385
|
-
parsed_data = self._loads(data)
|
|
386
|
-
|
|
387
|
-
# tag should be filled only when queried by tag
|
|
388
|
-
parsed_data["metadata"]["tag"] = "" if hash_key else tag
|
|
389
|
-
return parsed_data
|
|
390
|
-
|
|
391
|
-
def delete_function(self, name: str, project: str = ""):
|
|
392
|
-
raise NotImplementedError()
|
|
393
|
-
|
|
394
|
-
def list_functions(self, name=None, project="", tag="", labels=None):
|
|
395
|
-
labels = labels or []
|
|
396
|
-
logger.info(f"reading functions in {project} name/mask: {name} tag: {tag} ...")
|
|
397
|
-
filepath = path.join(
|
|
398
|
-
self.dirpath,
|
|
399
|
-
functions_dir,
|
|
400
|
-
project or config.default_project,
|
|
401
|
-
)
|
|
402
|
-
filepath += "/"
|
|
403
|
-
|
|
404
|
-
# function name -> tag name -> function dict
|
|
405
|
-
functions_with_tag_filename = {}
|
|
406
|
-
# function name -> hash key -> function dict
|
|
407
|
-
functions_with_hash_key_filename = {}
|
|
408
|
-
# function name -> hash keys set
|
|
409
|
-
function_with_tag_hash_keys = {}
|
|
410
|
-
if isinstance(labels, str):
|
|
411
|
-
labels = labels.split(",")
|
|
412
|
-
mask = "**/*"
|
|
413
|
-
if name:
|
|
414
|
-
filepath = f"{filepath}{name}/"
|
|
415
|
-
mask = "*"
|
|
416
|
-
for func, fullname in self._load_list(filepath, mask):
|
|
417
|
-
if match_labels(get_in(func, "metadata.labels", {}), labels):
|
|
418
|
-
file_name, _ = path.splitext(path.basename(fullname))
|
|
419
|
-
function_name = path.basename(path.dirname(fullname))
|
|
420
|
-
target_dict = functions_with_tag_filename
|
|
421
|
-
|
|
422
|
-
tag_name = file_name
|
|
423
|
-
# Heuristic - if tag length is bigger than 20 it's probably a hash key
|
|
424
|
-
if len(tag_name) > 20: # hash vs tags
|
|
425
|
-
tag_name = ""
|
|
426
|
-
target_dict = functions_with_hash_key_filename
|
|
427
|
-
else:
|
|
428
|
-
function_with_tag_hash_keys.setdefault(function_name, set()).add(
|
|
429
|
-
func["metadata"]["hash"]
|
|
430
|
-
)
|
|
431
|
-
update_in(func, "metadata.tag", tag_name)
|
|
432
|
-
target_dict.setdefault(function_name, {})[file_name] = func
|
|
433
|
-
|
|
434
|
-
# clean duplicated function e.g. function that was saved both in a hash key filename and tag filename
|
|
435
|
-
for (
|
|
436
|
-
function_name,
|
|
437
|
-
hash_keys_to_function_dict_map,
|
|
438
|
-
) in functions_with_hash_key_filename.items():
|
|
439
|
-
function_hash_keys_to_remove = []
|
|
440
|
-
for (
|
|
441
|
-
function_hash_key,
|
|
442
|
-
function_dict,
|
|
443
|
-
) in hash_keys_to_function_dict_map.items():
|
|
444
|
-
if function_hash_key in function_with_tag_hash_keys.get(
|
|
445
|
-
function_name, set()
|
|
446
|
-
):
|
|
447
|
-
function_hash_keys_to_remove.append(function_hash_key)
|
|
448
|
-
|
|
449
|
-
for function_hash_key in function_hash_keys_to_remove:
|
|
450
|
-
del hash_keys_to_function_dict_map[function_hash_key]
|
|
451
|
-
|
|
452
|
-
results = []
|
|
453
|
-
for functions_map in [
|
|
454
|
-
functions_with_hash_key_filename,
|
|
455
|
-
functions_with_tag_filename,
|
|
456
|
-
]:
|
|
457
|
-
for function_name, filename_to_function_map in functions_map.items():
|
|
458
|
-
results.extend(filename_to_function_map.values())
|
|
459
|
-
|
|
460
|
-
return results
|
|
461
|
-
|
|
462
|
-
def _filepath(self, table, project, key="", tag=""):
|
|
463
|
-
if tag == "*":
|
|
464
|
-
tag = ""
|
|
465
|
-
if tag:
|
|
466
|
-
key = "/" + key
|
|
467
|
-
project = project or config.default_project
|
|
468
|
-
return path.join(self.dirpath, table, project, tag + key)
|
|
469
|
-
|
|
470
|
-
def list_projects(
|
|
471
|
-
self,
|
|
472
|
-
owner: str = None,
|
|
473
|
-
format_: mlrun.api.schemas.ProjectsFormat = mlrun.api.schemas.ProjectsFormat.full,
|
|
474
|
-
labels: List[str] = None,
|
|
475
|
-
state: mlrun.api.schemas.ProjectState = None,
|
|
476
|
-
names: Optional[List[str]] = None,
|
|
477
|
-
) -> mlrun.api.schemas.ProjectsOutput:
|
|
478
|
-
if (
|
|
479
|
-
owner
|
|
480
|
-
or format_ == mlrun.api.schemas.ProjectsFormat.full
|
|
481
|
-
or labels
|
|
482
|
-
or state
|
|
483
|
-
or names
|
|
484
|
-
):
|
|
485
|
-
raise NotImplementedError()
|
|
486
|
-
run_dir = path.join(self.dirpath, run_logs)
|
|
487
|
-
if not path.isdir(run_dir):
|
|
488
|
-
return mlrun.api.schemas.ProjectsOutput(projects=[])
|
|
489
|
-
project_names = [
|
|
490
|
-
d for d in listdir(run_dir) if path.isdir(path.join(run_dir, d))
|
|
491
|
-
]
|
|
492
|
-
return mlrun.api.schemas.ProjectsOutput(projects=project_names)
|
|
493
|
-
|
|
494
|
-
def tag_objects(
|
|
495
|
-
self,
|
|
496
|
-
project: str,
|
|
497
|
-
tag_name: str,
|
|
498
|
-
tag_objects: schemas.TagObjects,
|
|
499
|
-
replace: bool = False,
|
|
500
|
-
):
|
|
501
|
-
raise NotImplementedError()
|
|
502
|
-
|
|
503
|
-
def delete_objects_tag(
|
|
504
|
-
self, project: str, tag_name: str, tag_objects: schemas.TagObjects
|
|
505
|
-
):
|
|
506
|
-
raise NotImplementedError()
|
|
507
|
-
|
|
508
|
-
def tag_artifacts(
|
|
509
|
-
self,
|
|
510
|
-
artifacts,
|
|
511
|
-
project: str,
|
|
512
|
-
tag_name: str,
|
|
513
|
-
replace: bool = False,
|
|
514
|
-
):
|
|
515
|
-
raise NotImplementedError()
|
|
516
|
-
|
|
517
|
-
def delete_artifacts_tags(
|
|
518
|
-
self,
|
|
519
|
-
artifacts,
|
|
520
|
-
project: str,
|
|
521
|
-
tag_name: str,
|
|
522
|
-
):
|
|
523
|
-
raise NotImplementedError()
|
|
524
|
-
|
|
525
|
-
def get_project(self, name: str) -> mlrun.api.schemas.Project:
|
|
526
|
-
# returns None if project not found, mainly for tests, until we remove fileDB
|
|
527
|
-
return None
|
|
528
|
-
|
|
529
|
-
def delete_project(
|
|
530
|
-
self,
|
|
531
|
-
name: str,
|
|
532
|
-
deletion_strategy: mlrun.api.schemas.DeletionStrategy = mlrun.api.schemas.DeletionStrategy.default(),
|
|
533
|
-
):
|
|
534
|
-
raise NotImplementedError()
|
|
535
|
-
|
|
536
|
-
def store_project(
|
|
537
|
-
self,
|
|
538
|
-
name: str,
|
|
539
|
-
project: mlrun.api.schemas.Project,
|
|
540
|
-
) -> mlrun.api.schemas.Project:
|
|
541
|
-
raise NotImplementedError()
|
|
542
|
-
|
|
543
|
-
def patch_project(
|
|
544
|
-
self,
|
|
545
|
-
name: str,
|
|
546
|
-
project: dict,
|
|
547
|
-
patch_mode: mlrun.api.schemas.PatchMode = mlrun.api.schemas.PatchMode.replace,
|
|
548
|
-
) -> mlrun.api.schemas.Project:
|
|
549
|
-
raise NotImplementedError()
|
|
550
|
-
|
|
551
|
-
def create_project(
|
|
552
|
-
self,
|
|
553
|
-
project: mlrun.api.schemas.Project,
|
|
554
|
-
) -> mlrun.api.schemas.Project:
|
|
555
|
-
raise NotImplementedError()
|
|
556
|
-
|
|
557
|
-
@property
|
|
558
|
-
def schedules_dir(self):
|
|
559
|
-
return path.join(self.dirpath, schedules_dir)
|
|
560
|
-
|
|
561
|
-
def store_schedule(self, data):
|
|
562
|
-
sched_id = 1 + sum(1 for _ in scandir(self.schedules_dir))
|
|
563
|
-
fname = path.join(self.schedules_dir, f"{sched_id}{self.format}")
|
|
564
|
-
with open(fname, "w") as out:
|
|
565
|
-
out.write(self._dumps(data))
|
|
566
|
-
|
|
567
|
-
def list_schedules(self):
|
|
568
|
-
pattern = f"*{self.format}"
|
|
569
|
-
for p in pathlib.Path(self.schedules_dir).glob(pattern):
|
|
570
|
-
with p.open() as fp:
|
|
571
|
-
yield self._loads(fp.read())
|
|
572
|
-
|
|
573
|
-
return []
|
|
574
|
-
|
|
575
|
-
_encodings = {
|
|
576
|
-
".yaml": ("to_yaml", dict_to_yaml),
|
|
577
|
-
".json": ("to_json", dict_to_json),
|
|
578
|
-
}
|
|
579
|
-
|
|
580
|
-
def _dumps(self, obj):
|
|
581
|
-
meth_name, enc_fn = self._encodings.get(self.format, (None, None))
|
|
582
|
-
if meth_name is None:
|
|
583
|
-
raise ValueError(f"unsupported format - {self.format}")
|
|
584
|
-
|
|
585
|
-
meth = getattr(obj, meth_name, None)
|
|
586
|
-
if meth:
|
|
587
|
-
return meth()
|
|
588
|
-
|
|
589
|
-
return enc_fn(obj)
|
|
590
|
-
|
|
591
|
-
def _loads(self, data):
|
|
592
|
-
if self.format == ".yaml":
|
|
593
|
-
return yaml.load(data, Loader=yaml.FullLoader)
|
|
594
|
-
else:
|
|
595
|
-
return json.loads(data)
|
|
596
|
-
|
|
597
|
-
def _load_list(self, dirpath, mask):
|
|
598
|
-
for p in pathlib.Path(dirpath).glob(mask + self.format):
|
|
599
|
-
if p.is_file():
|
|
600
|
-
if ".ipynb_checkpoints" in p.parts:
|
|
601
|
-
continue
|
|
602
|
-
data = self._loads(p.read_text())
|
|
603
|
-
if data:
|
|
604
|
-
yield data, str(p)
|
|
605
|
-
|
|
606
|
-
def _safe_del(self, filepath):
|
|
607
|
-
if path.isfile(filepath):
|
|
608
|
-
remove(filepath)
|
|
609
|
-
else:
|
|
610
|
-
raise RunDBError(f"run file is not found or valid ({filepath})")
|
|
611
|
-
|
|
612
|
-
def create_feature_set(self, feature_set, project="", versioned=True):
|
|
613
|
-
raise NotImplementedError()
|
|
614
|
-
|
|
615
|
-
def get_feature_set(
|
|
616
|
-
self, name: str, project: str = "", tag: str = None, uid: str = None
|
|
617
|
-
):
|
|
618
|
-
raise NotImplementedError()
|
|
619
|
-
|
|
620
|
-
def list_features(
|
|
621
|
-
self,
|
|
622
|
-
project: str,
|
|
623
|
-
name: str = None,
|
|
624
|
-
tag: str = None,
|
|
625
|
-
entities: List[str] = None,
|
|
626
|
-
labels: List[str] = None,
|
|
627
|
-
):
|
|
628
|
-
raise NotImplementedError()
|
|
629
|
-
|
|
630
|
-
def list_entities(
|
|
631
|
-
self,
|
|
632
|
-
project: str,
|
|
633
|
-
name: str = None,
|
|
634
|
-
tag: str = None,
|
|
635
|
-
labels: List[str] = None,
|
|
636
|
-
):
|
|
637
|
-
raise NotImplementedError()
|
|
638
|
-
|
|
639
|
-
def list_feature_sets(
|
|
640
|
-
self,
|
|
641
|
-
project: str = "",
|
|
642
|
-
name: str = None,
|
|
643
|
-
tag: str = None,
|
|
644
|
-
state: str = None,
|
|
645
|
-
entities: List[str] = None,
|
|
646
|
-
features: List[str] = None,
|
|
647
|
-
labels: List[str] = None,
|
|
648
|
-
partition_by: str = None,
|
|
649
|
-
rows_per_partition: int = 1,
|
|
650
|
-
partition_sort_by: str = None,
|
|
651
|
-
partition_order: str = "desc",
|
|
652
|
-
):
|
|
653
|
-
raise NotImplementedError()
|
|
654
|
-
|
|
655
|
-
def store_feature_set(
|
|
656
|
-
self, feature_set, name=None, project="", tag=None, uid=None, versioned=True
|
|
657
|
-
):
|
|
658
|
-
raise NotImplementedError()
|
|
659
|
-
|
|
660
|
-
def patch_feature_set(
|
|
661
|
-
self,
|
|
662
|
-
name,
|
|
663
|
-
feature_set,
|
|
664
|
-
project="",
|
|
665
|
-
tag=None,
|
|
666
|
-
uid=None,
|
|
667
|
-
patch_mode="replace",
|
|
668
|
-
):
|
|
669
|
-
raise NotImplementedError()
|
|
670
|
-
|
|
671
|
-
def delete_feature_set(self, name, project="", tag=None, uid=None):
|
|
672
|
-
raise NotImplementedError()
|
|
673
|
-
|
|
674
|
-
def create_feature_vector(self, feature_vector, project="", versioned=True) -> dict:
|
|
675
|
-
raise NotImplementedError()
|
|
676
|
-
|
|
677
|
-
def get_feature_vector(
|
|
678
|
-
self, name: str, project: str = "", tag: str = None, uid: str = None
|
|
679
|
-
) -> dict:
|
|
680
|
-
raise NotImplementedError()
|
|
681
|
-
|
|
682
|
-
def list_feature_vectors(
|
|
683
|
-
self,
|
|
684
|
-
project: str = "",
|
|
685
|
-
name: str = None,
|
|
686
|
-
tag: str = None,
|
|
687
|
-
state: str = None,
|
|
688
|
-
labels: List[str] = None,
|
|
689
|
-
partition_by: str = None,
|
|
690
|
-
rows_per_partition: int = 1,
|
|
691
|
-
partition_sort_by: str = None,
|
|
692
|
-
partition_order: str = "desc",
|
|
693
|
-
) -> List[dict]:
|
|
694
|
-
raise NotImplementedError()
|
|
695
|
-
|
|
696
|
-
def store_feature_vector(
|
|
697
|
-
self,
|
|
698
|
-
feature_vector,
|
|
699
|
-
name=None,
|
|
700
|
-
project="",
|
|
701
|
-
tag=None,
|
|
702
|
-
uid=None,
|
|
703
|
-
versioned=True,
|
|
704
|
-
):
|
|
705
|
-
raise NotImplementedError()
|
|
706
|
-
|
|
707
|
-
def patch_feature_vector(
|
|
708
|
-
self,
|
|
709
|
-
name,
|
|
710
|
-
feature_vector_update: dict,
|
|
711
|
-
project="",
|
|
712
|
-
tag=None,
|
|
713
|
-
uid=None,
|
|
714
|
-
patch_mode="replace",
|
|
715
|
-
):
|
|
716
|
-
raise NotImplementedError()
|
|
717
|
-
|
|
718
|
-
def delete_feature_vector(self, name, project="", tag=None, uid=None):
|
|
719
|
-
raise NotImplementedError()
|
|
720
|
-
|
|
721
|
-
def list_pipelines(
|
|
722
|
-
self,
|
|
723
|
-
project: str,
|
|
724
|
-
namespace: str = None,
|
|
725
|
-
sort_by: str = "",
|
|
726
|
-
page_token: str = "",
|
|
727
|
-
filter_: str = "",
|
|
728
|
-
format_: Union[
|
|
729
|
-
str, mlrun.api.schemas.PipelinesFormat
|
|
730
|
-
] = mlrun.api.schemas.PipelinesFormat.metadata_only,
|
|
731
|
-
page_size: int = None,
|
|
732
|
-
) -> mlrun.api.schemas.PipelinesOutput:
|
|
733
|
-
raise NotImplementedError()
|
|
734
|
-
|
|
735
|
-
def create_project_secrets(
|
|
736
|
-
self,
|
|
737
|
-
project: str,
|
|
738
|
-
provider: str = mlrun.api.schemas.SecretProviderName.kubernetes.value,
|
|
739
|
-
secrets: dict = None,
|
|
740
|
-
):
|
|
741
|
-
raise NotImplementedError()
|
|
742
|
-
|
|
743
|
-
def list_project_secrets(
|
|
744
|
-
self,
|
|
745
|
-
project: str,
|
|
746
|
-
token: str,
|
|
747
|
-
provider: str = mlrun.api.schemas.SecretProviderName.kubernetes.value,
|
|
748
|
-
secrets: List[str] = None,
|
|
749
|
-
) -> mlrun.api.schemas.SecretsData:
|
|
750
|
-
raise NotImplementedError()
|
|
751
|
-
|
|
752
|
-
def list_project_secret_keys(
|
|
753
|
-
self,
|
|
754
|
-
project: str,
|
|
755
|
-
provider: str = mlrun.api.schemas.SecretProviderName.kubernetes,
|
|
756
|
-
token: str = None,
|
|
757
|
-
) -> mlrun.api.schemas.SecretKeysData:
|
|
758
|
-
raise NotImplementedError()
|
|
759
|
-
|
|
760
|
-
def delete_project_secrets(
|
|
761
|
-
self,
|
|
762
|
-
project: str,
|
|
763
|
-
provider: str = mlrun.api.schemas.SecretProviderName.kubernetes.value,
|
|
764
|
-
secrets: List[str] = None,
|
|
765
|
-
):
|
|
766
|
-
raise NotImplementedError()
|
|
767
|
-
|
|
768
|
-
def create_user_secrets(
|
|
769
|
-
self,
|
|
770
|
-
user: str,
|
|
771
|
-
provider: str = mlrun.api.schemas.secret.SecretProviderName.vault.value,
|
|
772
|
-
secrets: dict = None,
|
|
773
|
-
):
|
|
774
|
-
raise NotImplementedError()
|
|
775
|
-
|
|
776
|
-
def list_artifact_tags(self, project=None, category=None):
|
|
777
|
-
raise NotImplementedError()
|
|
778
|
-
|
|
779
|
-
def create_model_endpoint(
|
|
780
|
-
self,
|
|
781
|
-
project: str,
|
|
782
|
-
endpoint_id: str,
|
|
783
|
-
model_endpoint: ModelEndpoint,
|
|
784
|
-
):
|
|
785
|
-
raise NotImplementedError()
|
|
786
|
-
|
|
787
|
-
def delete_model_endpoint(
|
|
788
|
-
self,
|
|
789
|
-
project: str,
|
|
790
|
-
endpoint_id: str,
|
|
791
|
-
):
|
|
792
|
-
raise NotImplementedError()
|
|
793
|
-
|
|
794
|
-
def list_model_endpoints(
|
|
795
|
-
self,
|
|
796
|
-
project: str,
|
|
797
|
-
model: Optional[str] = None,
|
|
798
|
-
function: Optional[str] = None,
|
|
799
|
-
labels: List[str] = None,
|
|
800
|
-
start: str = "now-1h",
|
|
801
|
-
end: str = "now",
|
|
802
|
-
metrics: Optional[List[str]] = None,
|
|
803
|
-
):
|
|
804
|
-
raise NotImplementedError()
|
|
805
|
-
|
|
806
|
-
def get_model_endpoint(
|
|
807
|
-
self,
|
|
808
|
-
project: str,
|
|
809
|
-
endpoint_id: str,
|
|
810
|
-
start: Optional[str] = None,
|
|
811
|
-
end: Optional[str] = None,
|
|
812
|
-
metrics: Optional[List[str]] = None,
|
|
813
|
-
features: bool = False,
|
|
814
|
-
):
|
|
815
|
-
raise NotImplementedError()
|
|
816
|
-
|
|
817
|
-
def patch_model_endpoint(
|
|
818
|
-
self,
|
|
819
|
-
project: str,
|
|
820
|
-
endpoint_id: str,
|
|
821
|
-
attributes: dict,
|
|
822
|
-
):
|
|
823
|
-
raise NotImplementedError()
|
|
824
|
-
|
|
825
|
-
def create_marketplace_source(
|
|
826
|
-
self, source: Union[dict, schemas.IndexedMarketplaceSource]
|
|
827
|
-
):
|
|
828
|
-
raise NotImplementedError()
|
|
829
|
-
|
|
830
|
-
def store_marketplace_source(
|
|
831
|
-
self, source_name: str, source: Union[dict, schemas.IndexedMarketplaceSource]
|
|
832
|
-
):
|
|
833
|
-
raise NotImplementedError()
|
|
834
|
-
|
|
835
|
-
def list_marketplace_sources(self):
|
|
836
|
-
raise NotImplementedError()
|
|
837
|
-
|
|
838
|
-
def get_marketplace_source(self, source_name: str):
|
|
839
|
-
raise NotImplementedError()
|
|
840
|
-
|
|
841
|
-
def delete_marketplace_source(self, source_name: str):
|
|
842
|
-
raise NotImplementedError()
|
|
843
|
-
|
|
844
|
-
def get_marketplace_catalog(
|
|
845
|
-
self,
|
|
846
|
-
source_name: str,
|
|
847
|
-
channel: str = None,
|
|
848
|
-
version: str = None,
|
|
849
|
-
tag: str = None,
|
|
850
|
-
force_refresh: bool = False,
|
|
851
|
-
):
|
|
852
|
-
raise NotImplementedError()
|
|
853
|
-
|
|
854
|
-
def get_marketplace_item(
|
|
855
|
-
self,
|
|
856
|
-
source_name: str,
|
|
857
|
-
item_name: str,
|
|
858
|
-
channel: str = "development",
|
|
859
|
-
version: str = None,
|
|
860
|
-
tag: str = "latest",
|
|
861
|
-
force_refresh: bool = False,
|
|
862
|
-
):
|
|
863
|
-
raise NotImplementedError()
|
|
864
|
-
|
|
865
|
-
def verify_authorization(
|
|
866
|
-
self,
|
|
867
|
-
authorization_verification_input: mlrun.api.schemas.AuthorizationVerificationInput,
|
|
868
|
-
):
|
|
869
|
-
raise NotImplementedError()
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
def make_time_pred(since, until):
|
|
873
|
-
if not (since or until):
|
|
874
|
-
return lambda artifact: True
|
|
875
|
-
|
|
876
|
-
since = since or datetime.min
|
|
877
|
-
until = until or datetime.max
|
|
878
|
-
|
|
879
|
-
if since.tzinfo is None:
|
|
880
|
-
since = since.replace(tzinfo=timezone.utc)
|
|
881
|
-
if until.tzinfo is None:
|
|
882
|
-
until = until.replace(tzinfo=timezone.utc)
|
|
883
|
-
|
|
884
|
-
def pred(artifact):
|
|
885
|
-
val = artifact.get("updated")
|
|
886
|
-
if not val:
|
|
887
|
-
return True
|
|
888
|
-
t = parse_time(val).replace(tzinfo=timezone.utc)
|
|
889
|
-
return since <= t <= until
|
|
890
|
-
|
|
891
|
-
return pred
|