mlrun 1.3.3__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.3.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.3.dist-info/RECORD +0 -381
- {mlrun-1.3.3.dist-info → mlrun-1.4.0.dist-info}/LICENSE +0 -0
- {mlrun-1.3.3.dist-info → mlrun-1.4.0.dist-info}/WHEEL +0 -0
- {mlrun-1.3.3.dist-info → mlrun-1.4.0.dist-info}/entry_points.txt +0 -0
- {mlrun-1.3.3.dist-info → mlrun-1.4.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,298 @@
|
|
|
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 builtins
|
|
16
|
+
import importlib
|
|
17
|
+
import itertools
|
|
18
|
+
import re
|
|
19
|
+
import sys
|
|
20
|
+
import typing
|
|
21
|
+
|
|
22
|
+
from mlrun.errors import MLRunInvalidArgumentError
|
|
23
|
+
from mlrun.utils import logger
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class TypeHintUtils:
|
|
27
|
+
"""
|
|
28
|
+
Static class for utilities functions to process type hints.
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
@staticmethod
|
|
32
|
+
def is_typing_type(type_hint: type) -> bool:
|
|
33
|
+
"""
|
|
34
|
+
Check whether a given type is a type hint from one of the modules `typing` and `types`. The function will return
|
|
35
|
+
True for generic type aliases also, meaning Python 3.9's new hinting feature that includes hinting like
|
|
36
|
+
`list[int]` instead of `typing.List[int]`.
|
|
37
|
+
|
|
38
|
+
:param type_hint: The type to check.
|
|
39
|
+
|
|
40
|
+
:return: True if the type hint from `typing` / `types` and False otherwise.
|
|
41
|
+
"""
|
|
42
|
+
# A type hint should be one of the based typing classes, meaning it will have "typing" as its module. Some
|
|
43
|
+
# typing classes are considered a type (like `TypeVar`) so we check their type as well. The only case "types"
|
|
44
|
+
# will be a module is for generic aliases like `list[int]`.
|
|
45
|
+
return (type_hint.__module__ == "typing") or (
|
|
46
|
+
type(type_hint).__module__ in ["typing", "types"]
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
@staticmethod
|
|
50
|
+
def parse_type_hint(type_hint: typing.Union[type, str]) -> type:
|
|
51
|
+
"""
|
|
52
|
+
Parse a given type hint from string to its actual hinted type class object. The string must be one of the
|
|
53
|
+
following:
|
|
54
|
+
|
|
55
|
+
* Python builtin type - for example: `tuple`, `list`, `set`, `dict` and `bytearray`.
|
|
56
|
+
* Full module import path. An alias (if `import pandas as pd is used`, the type hint cannot be `pd.DataFrame`)
|
|
57
|
+
is not allowed.
|
|
58
|
+
|
|
59
|
+
The type class on its own (like `DataFrame`) cannot be used as the scope of this function is not the same as the
|
|
60
|
+
handler itself, hence modules and objects that were imported in the handler's scope are not available. This is
|
|
61
|
+
the same reason import aliases cannot be used as well.
|
|
62
|
+
|
|
63
|
+
If the provided type hint is not a string, it will simply be returned as is.
|
|
64
|
+
|
|
65
|
+
:param type_hint: The type hint to parse.
|
|
66
|
+
|
|
67
|
+
:return: The hinted type.
|
|
68
|
+
|
|
69
|
+
:raise MLRunInvalidArgumentError: In case the type hint is not following the 2 options mentioned above.
|
|
70
|
+
"""
|
|
71
|
+
if not isinstance(type_hint, str):
|
|
72
|
+
return type_hint
|
|
73
|
+
|
|
74
|
+
# Validate the type hint is a valid module path:
|
|
75
|
+
if not bool(
|
|
76
|
+
re.fullmatch(
|
|
77
|
+
r"([a-zA-Z_][a-zA-Z0-9_]*\.)*[a-zA-Z_][a-zA-Z0-9_]*", type_hint
|
|
78
|
+
)
|
|
79
|
+
):
|
|
80
|
+
raise MLRunInvalidArgumentError(
|
|
81
|
+
f"Invalid type hint. An input type hint must be a valid python class name or its module import path. "
|
|
82
|
+
f"For example: 'list', 'pandas.DataFrame', 'numpy.ndarray', 'sklearn.linear_model.LinearRegression'. "
|
|
83
|
+
f"Type hint given: '{type_hint}'."
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
# Look for a builtin type (rest of the builtin types like `int`, `str`, `float` should be treated as results,
|
|
87
|
+
# hence not given as an input to an MLRun function, but as a parameter):
|
|
88
|
+
builtin_types = {
|
|
89
|
+
builtin_name: builtin_type
|
|
90
|
+
for builtin_name, builtin_type in builtins.__dict__.items()
|
|
91
|
+
if isinstance(builtin_type, type)
|
|
92
|
+
}
|
|
93
|
+
if type_hint in builtin_types:
|
|
94
|
+
return builtin_types[type_hint]
|
|
95
|
+
|
|
96
|
+
# If it's not a builtin, its should have a full module path, meaning at least one '.' to separate the module and
|
|
97
|
+
# the class. If it doesn't, we will try to get the class from the main module:
|
|
98
|
+
if "." not in type_hint:
|
|
99
|
+
logger.warn(
|
|
100
|
+
f"The type hint string given '{type_hint}' is not a `builtins` python type. MLRun will try to look for "
|
|
101
|
+
f"it in the `__main__` module instead."
|
|
102
|
+
)
|
|
103
|
+
try:
|
|
104
|
+
return TypeHintUtils.parse_type_hint(type_hint=f"__main__.{type_hint}")
|
|
105
|
+
except MLRunInvalidArgumentError:
|
|
106
|
+
raise MLRunInvalidArgumentError(
|
|
107
|
+
f"MLRun tried to get the type hint '{type_hint}' but it can't as it is not a valid builtin Python "
|
|
108
|
+
f"type (one of `list`, `dict`, `str`, `int`, etc.) nor a locally declared type (from the "
|
|
109
|
+
f"`__main__` module). Pay attention using only the type as string is not allowed as the handler's "
|
|
110
|
+
f"scope is different than MLRun's. To properly give a type hint as string, please specify the full "
|
|
111
|
+
f"module path without aliases. For example: do not use `DataFrame` or `pd.DataFrame`, use "
|
|
112
|
+
f"`pandas.DataFrame`."
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
# Import the module to receive the hinted type:
|
|
116
|
+
try:
|
|
117
|
+
# Get the module path and the type class (If we'll wish to support inner classes, the `rsplit` won't work):
|
|
118
|
+
module_path, type_hint = type_hint.rsplit(".", 1)
|
|
119
|
+
# Replace alias if needed (alias assumed to be imported already, hence we look in globals):
|
|
120
|
+
# For example:
|
|
121
|
+
# If in handler scope there was `import A.B.C as abc` and user gave a type hint "abc.Something" then:
|
|
122
|
+
# `module_path[0]` will be equal to "abc". Then, because it is an alias, it will appear in the globals, so
|
|
123
|
+
# we'll replace the alias with the full module name in order to import the module.
|
|
124
|
+
module_path = module_path.split(".")
|
|
125
|
+
if module_path[0] in globals():
|
|
126
|
+
module_path[0] = globals()[module_path[0]].__name__
|
|
127
|
+
module_path = ".".join(module_path)
|
|
128
|
+
# Import the module:
|
|
129
|
+
module = importlib.import_module(module_path)
|
|
130
|
+
# Get the class type from the module:
|
|
131
|
+
type_hint = getattr(module, type_hint)
|
|
132
|
+
except ModuleNotFoundError as module_not_found_error:
|
|
133
|
+
# May be raised from `importlib.import_module` in case the module does not exist.
|
|
134
|
+
raise MLRunInvalidArgumentError(
|
|
135
|
+
f"MLRun tried to get the type hint '{type_hint}' but the module '{module_path}' cannot be imported. "
|
|
136
|
+
f"Keep in mind that using alias in the module path (meaning: import module as alias) is not allowed. "
|
|
137
|
+
f"If the module path is correct, please make sure the module package is installed in the python "
|
|
138
|
+
f"interpreter."
|
|
139
|
+
) from module_not_found_error
|
|
140
|
+
except AttributeError as attribute_error:
|
|
141
|
+
# May be raised from `getattr(module, type_hint)` in case the class type cannot be imported directly from
|
|
142
|
+
# the imported module.
|
|
143
|
+
raise MLRunInvalidArgumentError(
|
|
144
|
+
f"MLRun tried to get the type hint '{type_hint}' from the module '{module.__name__}' but it seems it "
|
|
145
|
+
f"doesn't exist. Make sure the class can be imported from the module with the exact module path you "
|
|
146
|
+
f"passed. Notice inner classes (a class inside of a class) are not supported."
|
|
147
|
+
) from attribute_error
|
|
148
|
+
|
|
149
|
+
return type_hint
|
|
150
|
+
|
|
151
|
+
@staticmethod
|
|
152
|
+
def is_matching(
|
|
153
|
+
object_type: type,
|
|
154
|
+
type_hint: typing.Union[type, typing.Set[type]],
|
|
155
|
+
include_subclasses: bool = True,
|
|
156
|
+
reduce_type_hint: bool = True,
|
|
157
|
+
) -> bool:
|
|
158
|
+
"""
|
|
159
|
+
Check if the given object type match the given hint.
|
|
160
|
+
|
|
161
|
+
:param object_type: The object type to match with the type hint.
|
|
162
|
+
:param type_hint: The hint to match with. Can be given as a set resulted from a reduced hint.
|
|
163
|
+
:param include_subclasses: Whether to mark a subclass as valid match. Default to True.
|
|
164
|
+
:param reduce_type_hint: Whether to reduce the type hint to match with its reduced hints.
|
|
165
|
+
|
|
166
|
+
:return: True if the object type match the type hint and False otherwise.
|
|
167
|
+
"""
|
|
168
|
+
# Wrap in a set if provided a single type hint:
|
|
169
|
+
type_hint = {type_hint} if not isinstance(type_hint, set) else type_hint
|
|
170
|
+
|
|
171
|
+
# Try to match the object type to one of the hints:
|
|
172
|
+
while len(type_hint) > 0:
|
|
173
|
+
for hint in type_hint:
|
|
174
|
+
# Subclass check can be made only on actual object types (not typing module types):
|
|
175
|
+
if (
|
|
176
|
+
not TypeHintUtils.is_typing_type(type_hint=object_type)
|
|
177
|
+
and not TypeHintUtils.is_typing_type(type_hint=hint)
|
|
178
|
+
and include_subclasses
|
|
179
|
+
and issubclass(object_type, hint)
|
|
180
|
+
):
|
|
181
|
+
return True
|
|
182
|
+
if object_type == hint:
|
|
183
|
+
return True
|
|
184
|
+
# See if needed to reduce, if not end on first iteration:
|
|
185
|
+
if not reduce_type_hint:
|
|
186
|
+
break
|
|
187
|
+
type_hint = TypeHintUtils.reduce_type_hint(type_hint=type_hint)
|
|
188
|
+
return False
|
|
189
|
+
|
|
190
|
+
@staticmethod
|
|
191
|
+
def reduce_type_hint(
|
|
192
|
+
type_hint: typing.Union[type, typing.Set[type]],
|
|
193
|
+
) -> typing.Set[type]:
|
|
194
|
+
"""
|
|
195
|
+
Reduce a type hint (or a set of type hints) using the `_reduce_type_hint` function.
|
|
196
|
+
|
|
197
|
+
:param type_hint: The type hint to reduce.
|
|
198
|
+
|
|
199
|
+
:return: The reduced type hints set or an empty set if the type hint could not be reduced.
|
|
200
|
+
"""
|
|
201
|
+
# Wrap in a set if provided a single type hint:
|
|
202
|
+
type_hints = {type_hint} if not isinstance(type_hint, set) else type_hint
|
|
203
|
+
|
|
204
|
+
# Iterate over the type hints and reduce each one:
|
|
205
|
+
return set(
|
|
206
|
+
itertools.chain(
|
|
207
|
+
*[
|
|
208
|
+
TypeHintUtils._reduce_type_hint(type_hint=type_hint)
|
|
209
|
+
for type_hint in type_hints
|
|
210
|
+
]
|
|
211
|
+
)
|
|
212
|
+
)
|
|
213
|
+
|
|
214
|
+
@staticmethod
|
|
215
|
+
def _reduce_type_hint(type_hint: type) -> typing.List[type]:
|
|
216
|
+
"""
|
|
217
|
+
Reduce a type hint. If the type hint is a `typing` module, it will be reduced to its original hinted types. For
|
|
218
|
+
example: `typing.Union[int, float, typing.List[int]]` will return `[int, float, List[int]]` and
|
|
219
|
+
`typing.List[int]` will return `[list]`. Regular type hints - Python object types cannot be reduced as they are
|
|
220
|
+
already a core type.
|
|
221
|
+
|
|
222
|
+
If a type hint cannot be reduced, an empty list will be returned.
|
|
223
|
+
|
|
224
|
+
:param type_hint: The type hint to reduce.
|
|
225
|
+
|
|
226
|
+
:return: The reduced type hint as list of hinted types or an empty list if the type hint could not be reduced.
|
|
227
|
+
"""
|
|
228
|
+
# TODO: Remove when we'll no longer support Python 3.7:
|
|
229
|
+
if sys.version_info[1] < 8:
|
|
230
|
+
return []
|
|
231
|
+
|
|
232
|
+
# If it's not a typing type (meaning it's an actual object type) then we can't reduce it further:
|
|
233
|
+
if not TypeHintUtils.is_typing_type(type_hint=type_hint):
|
|
234
|
+
return []
|
|
235
|
+
|
|
236
|
+
# If it's a type var, take its constraints (e.g. A = TypeVar("A", int, str) meaning an object of type A should
|
|
237
|
+
# be an integer or a string). If it doesn't have constraints, return an empty list:
|
|
238
|
+
if isinstance(type_hint, typing.TypeVar):
|
|
239
|
+
if len(type_hint.__constraints__) == 0:
|
|
240
|
+
return []
|
|
241
|
+
return list(type_hint.__constraints__)
|
|
242
|
+
|
|
243
|
+
# If it's a forward reference, we will try to import the reference:
|
|
244
|
+
if isinstance(type_hint, typing.ForwardRef):
|
|
245
|
+
try:
|
|
246
|
+
# ForwardRef is initialized with the string type it represents and optionally a module path, so we
|
|
247
|
+
# construct a full module path and try to parse it:
|
|
248
|
+
arg = type_hint.__forward_arg__
|
|
249
|
+
if type_hint.__forward_module__:
|
|
250
|
+
arg = f"{type_hint.__forward_module__}.{arg}"
|
|
251
|
+
return [TypeHintUtils.parse_type_hint(type_hint=arg)]
|
|
252
|
+
except MLRunInvalidArgumentError: # May be raised from `TypeHintUtils.parse_type_hint`
|
|
253
|
+
logger.warn(
|
|
254
|
+
f"Could not reduce the type hint '{type_hint}' as it is a forward reference to a class without "
|
|
255
|
+
f"it's full module path. To enable importing forward references, please provide the full module "
|
|
256
|
+
f"path to them. For example: use `ForwardRef('pandas.DataFrame')` instead of "
|
|
257
|
+
f"`ForwardRef('DataFrame')`."
|
|
258
|
+
)
|
|
259
|
+
return []
|
|
260
|
+
|
|
261
|
+
# Get the origin of the typing type. An origin is the subscripted typing type (origin of Union[str, int] is
|
|
262
|
+
# Union). The origin can be one of Callable, Tuple, Union, Literal, Final, ClassVar, Annotated or the actual
|
|
263
|
+
# type alias (e.g. origin of List[int] is list):
|
|
264
|
+
origin = typing.get_origin(type_hint)
|
|
265
|
+
|
|
266
|
+
# If the typing type has no origin (e.g. None is returned), we cannot reduce it, so we return an empty list:
|
|
267
|
+
if origin is None:
|
|
268
|
+
return []
|
|
269
|
+
|
|
270
|
+
# If the origin is a type of one of `builtins`, `contextlib` or `collections` (for example: List's origin is
|
|
271
|
+
# list) then we can be sure there is nothing to reduce as it's a regular type:
|
|
272
|
+
if not TypeHintUtils.is_typing_type(type_hint=origin):
|
|
273
|
+
return [origin]
|
|
274
|
+
|
|
275
|
+
# Get the type's subscriptions - arguments, in order to reduce it to them (we know for sure there are arguments,
|
|
276
|
+
# otherwise origin would have been None):
|
|
277
|
+
args = typing.get_args(type_hint)
|
|
278
|
+
|
|
279
|
+
# Return the reduced type as its arguments according to the origin:
|
|
280
|
+
if origin is typing.Callable:
|
|
281
|
+
# A callable cannot be reduced to its arguments, so we'll return the origin - Callable:
|
|
282
|
+
return [typing.Callable]
|
|
283
|
+
if origin is typing.Literal:
|
|
284
|
+
# Literal arguments are not types, but values. So we'll take the types of the values as the reduced type:
|
|
285
|
+
return [type(arg) for arg in args]
|
|
286
|
+
if origin is typing.Union:
|
|
287
|
+
# A union is reduced to its arguments:
|
|
288
|
+
return list(args)
|
|
289
|
+
if origin is typing.Annotated:
|
|
290
|
+
# Annotated is used to describe (add metadata to) a type, so we take the first argument (the type the
|
|
291
|
+
# metadata is being added to):
|
|
292
|
+
return [args[0]]
|
|
293
|
+
if origin is typing.Final or origin is typing.ClassVar:
|
|
294
|
+
# Both Final and ClassVar takes only one argument - the type:
|
|
295
|
+
return [args[0]]
|
|
296
|
+
|
|
297
|
+
# For Generic types we return an empty list:
|
|
298
|
+
return []
|
mlrun/platforms/__init__.py
CHANGED
mlrun/platforms/iguazio.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright
|
|
1
|
+
# Copyright 2023 Iguazio
|
|
2
2
|
#
|
|
3
3
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
4
|
# you may not use this file except in compliance with the License.
|
|
@@ -326,7 +326,6 @@ def v3io_to_vol(name, remote="~/", access_key="", user="", secret=None):
|
|
|
326
326
|
if secret:
|
|
327
327
|
secret = {"name": secret}
|
|
328
328
|
|
|
329
|
-
# vol = client.V1Volume(name=name, flex_volume=client.V1FlexVolumeSource('v3io/fuse', options=opts))
|
|
330
329
|
vol = {
|
|
331
330
|
"flexVolume": client.V1FlexVolumeSource(
|
|
332
331
|
"v3io/fuse", options=opts, secret_ref=secret
|
|
@@ -403,6 +402,37 @@ class OutputStream:
|
|
|
403
402
|
)
|
|
404
403
|
|
|
405
404
|
|
|
405
|
+
class HTTPOutputStream:
|
|
406
|
+
"""HTTP output source that usually used for CE mode and debugging process"""
|
|
407
|
+
|
|
408
|
+
def __init__(self, stream_path: str):
|
|
409
|
+
self._stream_path = stream_path
|
|
410
|
+
|
|
411
|
+
def push(self, data):
|
|
412
|
+
def dump_record(rec):
|
|
413
|
+
if isinstance(rec, bytes):
|
|
414
|
+
return rec
|
|
415
|
+
|
|
416
|
+
if not isinstance(rec, str):
|
|
417
|
+
rec = dict_to_json(rec)
|
|
418
|
+
|
|
419
|
+
return rec.encode("UTF-8")
|
|
420
|
+
|
|
421
|
+
if not isinstance(data, list):
|
|
422
|
+
data = [data]
|
|
423
|
+
|
|
424
|
+
for record in data:
|
|
425
|
+
|
|
426
|
+
# Convert the new record to the required format
|
|
427
|
+
serialized_record = dump_record(record)
|
|
428
|
+
response = requests.post(self._stream_path, data=serialized_record)
|
|
429
|
+
if not response:
|
|
430
|
+
raise mlrun.errors.MLRunInvalidArgumentError(
|
|
431
|
+
f"API call failed push a new record through {self._stream_path}"
|
|
432
|
+
f"status {response.status_code}: {response.reason}"
|
|
433
|
+
)
|
|
434
|
+
|
|
435
|
+
|
|
406
436
|
class KafkaOutputStream:
|
|
407
437
|
def __init__(
|
|
408
438
|
self,
|
|
@@ -650,6 +680,8 @@ def parse_path(url, suffix="/"):
|
|
|
650
680
|
)
|
|
651
681
|
endpoint = f"{prefix}://{parsed_url.netloc}"
|
|
652
682
|
else:
|
|
683
|
+
# no netloc is mainly when using v3io (v3io:///) and expecting the url to be resolved automatically from env or
|
|
684
|
+
# config
|
|
653
685
|
endpoint = None
|
|
654
686
|
return endpoint, parsed_url.path.strip("/") + suffix
|
|
655
687
|
|
mlrun/platforms/other.py
CHANGED
mlrun/projects/__init__.py
CHANGED
mlrun/projects/operations.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright
|
|
1
|
+
# Copyright 2023 Iguazio
|
|
2
2
|
#
|
|
3
3
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
4
|
# you may not use this file except in compliance with the License.
|
|
@@ -70,8 +70,9 @@ def run_function(
|
|
|
70
70
|
selector: str = None,
|
|
71
71
|
project_object=None,
|
|
72
72
|
auto_build: bool = None,
|
|
73
|
-
schedule: Union[str, mlrun.
|
|
73
|
+
schedule: Union[str, mlrun.common.schemas.ScheduleCronTrigger] = None,
|
|
74
74
|
artifact_path: str = None,
|
|
75
|
+
notifications: List[mlrun.model.Notification] = None,
|
|
75
76
|
returns: Optional[List[Union[str, Dict[str, str]]]] = None,
|
|
76
77
|
) -> Union[mlrun.model.RunObject, kfp.dsl.ContainerOp]:
|
|
77
78
|
"""Run a local or remote task as part of a local/kubeflow pipeline
|
|
@@ -91,16 +92,16 @@ def run_function(
|
|
|
91
92
|
LABELS = "is_error"
|
|
92
93
|
MODEL_CLASS = "sklearn.ensemble.RandomForestClassifier"
|
|
93
94
|
DATA_PATH = "s3://bigdata/data.parquet"
|
|
94
|
-
function = mlrun.import_function("hub://
|
|
95
|
+
function = mlrun.import_function("hub://auto-trainer")
|
|
95
96
|
run1 = run_function(function, params={"label_columns": LABELS, "model_class": MODEL_CLASS},
|
|
96
97
|
inputs={"dataset": DATA_PATH})
|
|
97
98
|
|
|
98
99
|
example (use with project)::
|
|
99
100
|
|
|
100
|
-
# create a project with two functions (local and from
|
|
101
|
+
# create a project with two functions (local and from hub)
|
|
101
102
|
project = mlrun.new_project(project_name, "./proj)
|
|
102
103
|
project.set_function("mycode.py", "myfunc", image="mlrun/mlrun")
|
|
103
|
-
project.set_function("hub://
|
|
104
|
+
project.set_function("hub://auto-trainer", "train")
|
|
104
105
|
|
|
105
106
|
# run functions (refer to them by name)
|
|
106
107
|
run1 = run_function("myfunc", params={"x": 7})
|
|
@@ -111,7 +112,7 @@ def run_function(
|
|
|
111
112
|
|
|
112
113
|
@dsl.pipeline(name="test pipeline", description="test")
|
|
113
114
|
def my_pipe(url=""):
|
|
114
|
-
run1 = run_function("loaddata", params={"url": url})
|
|
115
|
+
run1 = run_function("loaddata", params={"url": url}, outputs=["data"])
|
|
115
116
|
run2 = run_function("train", params={"label_columns": LABELS, "model_class": MODEL_CLASS},
|
|
116
117
|
inputs={"dataset": run1.outputs["data"]})
|
|
117
118
|
|
|
@@ -137,12 +138,13 @@ def run_function(
|
|
|
137
138
|
:param verbose: add verbose prints/logs
|
|
138
139
|
:param project_object: override the project object to use, will default to the project set in the runtime context.
|
|
139
140
|
:param auto_build: when set to True and the function require build it will be built on the first
|
|
140
|
-
function run, use only if you
|
|
141
|
+
function run, use only if you do not plan on changing the build config between runs
|
|
141
142
|
:param schedule: ScheduleCronTrigger class instance or a standard crontab expression string
|
|
142
143
|
(which will be converted to the class using its `from_crontab` constructor),
|
|
143
144
|
see this link for help:
|
|
144
145
|
https://apscheduler.readthedocs.io/en/3.x/modules/triggers/cron.html#module-apscheduler.triggers.cron
|
|
145
146
|
:param artifact_path: path to store artifacts, when running in a workflow this will be set automatically
|
|
147
|
+
:param notifications: list of notifications to push when the run is completed
|
|
146
148
|
:param returns: List of log hints - configurations for how to log the returning values from the handler's
|
|
147
149
|
run (as artifacts or results). The list's length must be equal to the amount of returning
|
|
148
150
|
objects. A log hint may be given as:
|
|
@@ -198,6 +200,7 @@ def run_function(
|
|
|
198
200
|
or (project.artifact_path if project else None),
|
|
199
201
|
auto_build=auto_build,
|
|
200
202
|
schedule=schedule,
|
|
203
|
+
notifications=notifications,
|
|
201
204
|
)
|
|
202
205
|
if run_result:
|
|
203
206
|
run_result._notified = False
|
|
@@ -233,6 +236,7 @@ def build_function(
|
|
|
233
236
|
commands: list = None,
|
|
234
237
|
secret_name=None,
|
|
235
238
|
requirements: Union[str, List[str]] = None,
|
|
239
|
+
requirements_file: str = None,
|
|
236
240
|
mlrun_version_specifier=None,
|
|
237
241
|
builder_env: dict = None,
|
|
238
242
|
project_object=None,
|
|
@@ -247,7 +251,8 @@ def build_function(
|
|
|
247
251
|
:param base_image: base image name/path (commands and source code will be added to it)
|
|
248
252
|
:param commands: list of docker build (RUN) commands e.g. ['pip install pandas']
|
|
249
253
|
:param secret_name: k8s secret for accessing the docker registry
|
|
250
|
-
:param requirements: list of python packages
|
|
254
|
+
:param requirements: list of python packages, defaults to None
|
|
255
|
+
:param requirements_file: pip requirements file path, defaults to None
|
|
251
256
|
:param mlrun_version_specifier: which mlrun package version to include (if not current)
|
|
252
257
|
:param builder_env: Kaniko builder pod env vars dict (for config/credentials)
|
|
253
258
|
e.g. builder_env={"GIT_TOKEN": token}, does not work yet in KFP
|
|
@@ -266,7 +271,7 @@ def build_function(
|
|
|
266
271
|
if overwrite_build_params:
|
|
267
272
|
function.spec.build.commands = None
|
|
268
273
|
if requirements:
|
|
269
|
-
function.with_requirements(requirements)
|
|
274
|
+
function.with_requirements(requirements, requirements_file)
|
|
270
275
|
if commands:
|
|
271
276
|
function.with_commands(commands)
|
|
272
277
|
return function.deploy_step(
|
mlrun/projects/pipelines.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright
|
|
1
|
+
# Copyright 2023 Iguazio
|
|
2
2
|
#
|
|
3
3
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
4
|
# you may not use this file except in compliance with the License.
|
|
@@ -27,7 +27,7 @@ from kfp import dsl
|
|
|
27
27
|
from kfp.compiler import compiler
|
|
28
28
|
|
|
29
29
|
import mlrun
|
|
30
|
-
import mlrun.
|
|
30
|
+
import mlrun.common.schemas
|
|
31
31
|
import mlrun.utils.notifications
|
|
32
32
|
from mlrun.errors import err_to_str
|
|
33
33
|
from mlrun.utils import (
|
|
@@ -79,7 +79,7 @@ class WorkflowSpec(mlrun.model.ModelObj):
|
|
|
79
79
|
# TODO: deprecated, remove in 1.5.0
|
|
80
80
|
ttl=None,
|
|
81
81
|
args_schema: dict = None,
|
|
82
|
-
schedule: typing.Union[str, mlrun.
|
|
82
|
+
schedule: typing.Union[str, mlrun.common.schemas.ScheduleCronTrigger] = None,
|
|
83
83
|
cleanup_ttl: int = None,
|
|
84
84
|
):
|
|
85
85
|
if ttl:
|
|
@@ -116,7 +116,13 @@ class WorkflowSpec(mlrun.model.ModelObj):
|
|
|
116
116
|
self._tmp_path = workflow_path = workflow_fh.name
|
|
117
117
|
else:
|
|
118
118
|
workflow_path = self.path or ""
|
|
119
|
-
if
|
|
119
|
+
if (
|
|
120
|
+
context
|
|
121
|
+
and not workflow_path.startswith("/")
|
|
122
|
+
# since the user may provide a path the includes the context,
|
|
123
|
+
# we need to make sure we don't add it twice
|
|
124
|
+
and not workflow_path.startswith(context)
|
|
125
|
+
):
|
|
120
126
|
workflow_path = os.path.join(context, workflow_path)
|
|
121
127
|
return workflow_path
|
|
122
128
|
|
|
@@ -279,7 +285,7 @@ def _enrich_kfp_pod_security_context(kfp_pod_template, function):
|
|
|
279
285
|
if (
|
|
280
286
|
mlrun.runtimes.RuntimeKinds.is_local_runtime(function.kind)
|
|
281
287
|
or mlrun.mlconf.function.spec.security_context.enrichment_mode
|
|
282
|
-
== mlrun.
|
|
288
|
+
== mlrun.common.schemas.SecurityContextEnrichmentModes.disabled.value
|
|
283
289
|
):
|
|
284
290
|
return
|
|
285
291
|
|
|
@@ -405,7 +411,7 @@ def enrich_function_object(
|
|
|
405
411
|
f.spec.build.source = project.spec.source
|
|
406
412
|
f.spec.build.load_source_on_run = project.spec.load_source_on_run
|
|
407
413
|
f.spec.workdir = project.spec.workdir or project.spec.subpath
|
|
408
|
-
f.
|
|
414
|
+
f.prepare_image_for_deploy()
|
|
409
415
|
|
|
410
416
|
if project.spec.default_requirements:
|
|
411
417
|
f.with_requirements(project.spec.default_requirements)
|
|
@@ -705,7 +711,7 @@ class _LocalRunner(_PipelineRunner):
|
|
|
705
711
|
trace = traceback.format_exc()
|
|
706
712
|
logger.error(trace)
|
|
707
713
|
project.notifiers.push(
|
|
708
|
-
f"Workflow {workflow_id} run failed!, error: {e}\n{trace}", "error"
|
|
714
|
+
f":x: Workflow {workflow_id} run failed!, error: {e}\n{trace}", "error"
|
|
709
715
|
)
|
|
710
716
|
state = mlrun.run.RunStatuses.failed
|
|
711
717
|
mlrun.run.wait_for_runs_completion(pipeline_context.runs_map.values())
|
|
@@ -755,6 +761,7 @@ class _RemoteRunner(_PipelineRunner):
|
|
|
755
761
|
artifact_path: str,
|
|
756
762
|
workflow_handler: str,
|
|
757
763
|
namespace: str,
|
|
764
|
+
subpath: str,
|
|
758
765
|
) -> typing.Tuple[mlrun.runtimes.RemoteRuntime, "mlrun.RunObject"]:
|
|
759
766
|
"""
|
|
760
767
|
Helper function for creating the runspec of the load and run function.
|
|
@@ -767,6 +774,7 @@ class _RemoteRunner(_PipelineRunner):
|
|
|
767
774
|
:param artifact_path: path to store artifacts
|
|
768
775
|
:param workflow_handler: workflow function handler (for running workflow function directly)
|
|
769
776
|
:param namespace: kubernetes namespace if other than default
|
|
777
|
+
:param subpath: project subpath (within the archive)
|
|
770
778
|
:return:
|
|
771
779
|
"""
|
|
772
780
|
# Creating the load project and workflow running function:
|
|
@@ -792,6 +800,7 @@ class _RemoteRunner(_PipelineRunner):
|
|
|
792
800
|
"engine": workflow_spec.engine,
|
|
793
801
|
"local": workflow_spec.run_local,
|
|
794
802
|
"schedule": workflow_spec.schedule,
|
|
803
|
+
"subpath": subpath,
|
|
795
804
|
},
|
|
796
805
|
handler="mlrun.projects.load_and_run",
|
|
797
806
|
),
|
|
@@ -826,8 +835,11 @@ class _RemoteRunner(_PipelineRunner):
|
|
|
826
835
|
)
|
|
827
836
|
if "://" not in current_source:
|
|
828
837
|
raise mlrun.errors.MLRunInvalidArgumentError(
|
|
829
|
-
f"
|
|
830
|
-
f" the
|
|
838
|
+
f"Remote workflows can only be performed by a project with remote source (e.g git:// or http://),"
|
|
839
|
+
f" but the specified source '{current_source}' is not remote. "
|
|
840
|
+
f"Either put your code in Git, or archive it and then set a source to it."
|
|
841
|
+
f" For more details, read"
|
|
842
|
+
f" https://docs.mlrun.org/en/latest/concepts/scheduled-jobs.html#scheduling-a-workflow"
|
|
831
843
|
)
|
|
832
844
|
|
|
833
845
|
# Creating the load project and workflow running function:
|
|
@@ -840,6 +852,7 @@ class _RemoteRunner(_PipelineRunner):
|
|
|
840
852
|
artifact_path=artifact_path,
|
|
841
853
|
workflow_handler=workflow_handler,
|
|
842
854
|
namespace=namespace,
|
|
855
|
+
subpath=project.spec.subpath,
|
|
843
856
|
)
|
|
844
857
|
|
|
845
858
|
# The returned engine for this runner is the engine of the workflow.
|
|
@@ -874,7 +887,8 @@ class _RemoteRunner(_PipelineRunner):
|
|
|
874
887
|
trace = traceback.format_exc()
|
|
875
888
|
logger.error(trace)
|
|
876
889
|
project.notifiers.push(
|
|
877
|
-
f"Workflow {workflow_name} run failed!, error: {e}\n{trace}",
|
|
890
|
+
f":x: Workflow {workflow_name} run failed!, error: {e}\n{trace}",
|
|
891
|
+
"error",
|
|
878
892
|
)
|
|
879
893
|
state = mlrun.run.RunStatuses.failed
|
|
880
894
|
return _PipelineRunStatus(
|
|
@@ -928,7 +942,11 @@ def create_pipeline(project, pipeline, functions, secrets=None, handler=None):
|
|
|
928
942
|
if not handler and hasattr(mod, "pipeline"):
|
|
929
943
|
handler = "pipeline"
|
|
930
944
|
if not handler or not hasattr(mod, handler):
|
|
931
|
-
raise ValueError(
|
|
945
|
+
raise ValueError(
|
|
946
|
+
f"'workflow_handler' is not defined. "
|
|
947
|
+
f"Either provide it as set_workflow argument, or include a function named"
|
|
948
|
+
f" '{handler or 'pipeline'}' in your workflow .py file."
|
|
949
|
+
)
|
|
932
950
|
|
|
933
951
|
return getattr(mod, handler)
|
|
934
952
|
|
|
@@ -967,7 +985,7 @@ def load_and_run(
|
|
|
967
985
|
ttl: int = None,
|
|
968
986
|
engine: str = None,
|
|
969
987
|
local: bool = None,
|
|
970
|
-
schedule: typing.Union[str, mlrun.
|
|
988
|
+
schedule: typing.Union[str, mlrun.common.schemas.ScheduleCronTrigger] = None,
|
|
971
989
|
cleanup_ttl: int = None,
|
|
972
990
|
):
|
|
973
991
|
"""
|
|
@@ -1033,7 +1051,7 @@ def load_and_run(
|
|
|
1033
1051
|
try:
|
|
1034
1052
|
notification_pusher.push(
|
|
1035
1053
|
message=message,
|
|
1036
|
-
severity=mlrun.
|
|
1054
|
+
severity=mlrun.common.schemas.NotificationSeverity.ERROR,
|
|
1037
1055
|
)
|
|
1038
1056
|
|
|
1039
1057
|
except Exception as exc:
|