genesis-flow 1.0.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.
- genesis_flow-1.0.0.dist-info/METADATA +822 -0
- genesis_flow-1.0.0.dist-info/RECORD +645 -0
- genesis_flow-1.0.0.dist-info/WHEEL +5 -0
- genesis_flow-1.0.0.dist-info/entry_points.txt +19 -0
- genesis_flow-1.0.0.dist-info/licenses/LICENSE.txt +202 -0
- genesis_flow-1.0.0.dist-info/top_level.txt +1 -0
- mlflow/__init__.py +367 -0
- mlflow/__main__.py +3 -0
- mlflow/ag2/__init__.py +56 -0
- mlflow/ag2/ag2_logger.py +294 -0
- mlflow/anthropic/__init__.py +40 -0
- mlflow/anthropic/autolog.py +129 -0
- mlflow/anthropic/chat.py +144 -0
- mlflow/artifacts/__init__.py +268 -0
- mlflow/autogen/__init__.py +144 -0
- mlflow/autogen/chat.py +142 -0
- mlflow/azure/__init__.py +26 -0
- mlflow/azure/auth_handler.py +257 -0
- mlflow/azure/client.py +319 -0
- mlflow/azure/config.py +120 -0
- mlflow/azure/connection_factory.py +340 -0
- mlflow/azure/exceptions.py +27 -0
- mlflow/azure/stores.py +327 -0
- mlflow/azure/utils.py +183 -0
- mlflow/bedrock/__init__.py +45 -0
- mlflow/bedrock/_autolog.py +202 -0
- mlflow/bedrock/chat.py +122 -0
- mlflow/bedrock/stream.py +160 -0
- mlflow/bedrock/utils.py +43 -0
- mlflow/cli.py +707 -0
- mlflow/client.py +12 -0
- mlflow/config/__init__.py +56 -0
- mlflow/crewai/__init__.py +79 -0
- mlflow/crewai/autolog.py +253 -0
- mlflow/crewai/chat.py +29 -0
- mlflow/data/__init__.py +75 -0
- mlflow/data/artifact_dataset_sources.py +170 -0
- mlflow/data/code_dataset_source.py +40 -0
- mlflow/data/dataset.py +123 -0
- mlflow/data/dataset_registry.py +168 -0
- mlflow/data/dataset_source.py +110 -0
- mlflow/data/dataset_source_registry.py +219 -0
- mlflow/data/delta_dataset_source.py +167 -0
- mlflow/data/digest_utils.py +108 -0
- mlflow/data/evaluation_dataset.py +562 -0
- mlflow/data/filesystem_dataset_source.py +81 -0
- mlflow/data/http_dataset_source.py +145 -0
- mlflow/data/huggingface_dataset.py +258 -0
- mlflow/data/huggingface_dataset_source.py +118 -0
- mlflow/data/meta_dataset.py +104 -0
- mlflow/data/numpy_dataset.py +223 -0
- mlflow/data/pandas_dataset.py +231 -0
- mlflow/data/polars_dataset.py +352 -0
- mlflow/data/pyfunc_dataset_mixin.py +31 -0
- mlflow/data/schema.py +76 -0
- mlflow/data/sources.py +1 -0
- mlflow/data/spark_dataset.py +406 -0
- mlflow/data/spark_dataset_source.py +74 -0
- mlflow/data/spark_delta_utils.py +118 -0
- mlflow/data/tensorflow_dataset.py +350 -0
- mlflow/data/uc_volume_dataset_source.py +81 -0
- mlflow/db.py +27 -0
- mlflow/dspy/__init__.py +17 -0
- mlflow/dspy/autolog.py +197 -0
- mlflow/dspy/callback.py +398 -0
- mlflow/dspy/constant.py +1 -0
- mlflow/dspy/load.py +93 -0
- mlflow/dspy/save.py +393 -0
- mlflow/dspy/util.py +109 -0
- mlflow/dspy/wrapper.py +226 -0
- mlflow/entities/__init__.py +104 -0
- mlflow/entities/_mlflow_object.py +52 -0
- mlflow/entities/assessment.py +545 -0
- mlflow/entities/assessment_error.py +80 -0
- mlflow/entities/assessment_source.py +141 -0
- mlflow/entities/dataset.py +92 -0
- mlflow/entities/dataset_input.py +51 -0
- mlflow/entities/dataset_summary.py +62 -0
- mlflow/entities/document.py +48 -0
- mlflow/entities/experiment.py +109 -0
- mlflow/entities/experiment_tag.py +35 -0
- mlflow/entities/file_info.py +45 -0
- mlflow/entities/input_tag.py +35 -0
- mlflow/entities/lifecycle_stage.py +35 -0
- mlflow/entities/logged_model.py +228 -0
- mlflow/entities/logged_model_input.py +26 -0
- mlflow/entities/logged_model_output.py +32 -0
- mlflow/entities/logged_model_parameter.py +46 -0
- mlflow/entities/logged_model_status.py +74 -0
- mlflow/entities/logged_model_tag.py +33 -0
- mlflow/entities/metric.py +200 -0
- mlflow/entities/model_registry/__init__.py +29 -0
- mlflow/entities/model_registry/_model_registry_entity.py +13 -0
- mlflow/entities/model_registry/model_version.py +243 -0
- mlflow/entities/model_registry/model_version_deployment_job_run_state.py +44 -0
- mlflow/entities/model_registry/model_version_deployment_job_state.py +70 -0
- mlflow/entities/model_registry/model_version_search.py +25 -0
- mlflow/entities/model_registry/model_version_stages.py +25 -0
- mlflow/entities/model_registry/model_version_status.py +35 -0
- mlflow/entities/model_registry/model_version_tag.py +35 -0
- mlflow/entities/model_registry/prompt.py +73 -0
- mlflow/entities/model_registry/prompt_version.py +244 -0
- mlflow/entities/model_registry/registered_model.py +175 -0
- mlflow/entities/model_registry/registered_model_alias.py +35 -0
- mlflow/entities/model_registry/registered_model_deployment_job_state.py +39 -0
- mlflow/entities/model_registry/registered_model_search.py +25 -0
- mlflow/entities/model_registry/registered_model_tag.py +35 -0
- mlflow/entities/multipart_upload.py +74 -0
- mlflow/entities/param.py +49 -0
- mlflow/entities/run.py +97 -0
- mlflow/entities/run_data.py +84 -0
- mlflow/entities/run_info.py +188 -0
- mlflow/entities/run_inputs.py +59 -0
- mlflow/entities/run_outputs.py +43 -0
- mlflow/entities/run_status.py +41 -0
- mlflow/entities/run_tag.py +36 -0
- mlflow/entities/source_type.py +31 -0
- mlflow/entities/span.py +774 -0
- mlflow/entities/span_event.py +96 -0
- mlflow/entities/span_status.py +102 -0
- mlflow/entities/trace.py +317 -0
- mlflow/entities/trace_data.py +71 -0
- mlflow/entities/trace_info.py +220 -0
- mlflow/entities/trace_info_v2.py +162 -0
- mlflow/entities/trace_location.py +173 -0
- mlflow/entities/trace_state.py +39 -0
- mlflow/entities/trace_status.py +68 -0
- mlflow/entities/view_type.py +51 -0
- mlflow/environment_variables.py +866 -0
- mlflow/evaluation/__init__.py +16 -0
- mlflow/evaluation/assessment.py +369 -0
- mlflow/evaluation/evaluation.py +411 -0
- mlflow/evaluation/evaluation_tag.py +61 -0
- mlflow/evaluation/fluent.py +48 -0
- mlflow/evaluation/utils.py +201 -0
- mlflow/exceptions.py +213 -0
- mlflow/experiments.py +140 -0
- mlflow/gemini/__init__.py +81 -0
- mlflow/gemini/autolog.py +186 -0
- mlflow/gemini/chat.py +261 -0
- mlflow/genai/__init__.py +71 -0
- mlflow/genai/datasets/__init__.py +67 -0
- mlflow/genai/datasets/evaluation_dataset.py +131 -0
- mlflow/genai/evaluation/__init__.py +3 -0
- mlflow/genai/evaluation/base.py +411 -0
- mlflow/genai/evaluation/constant.py +23 -0
- mlflow/genai/evaluation/utils.py +244 -0
- mlflow/genai/judges/__init__.py +21 -0
- mlflow/genai/judges/databricks.py +404 -0
- mlflow/genai/label_schemas/__init__.py +153 -0
- mlflow/genai/label_schemas/label_schemas.py +209 -0
- mlflow/genai/labeling/__init__.py +159 -0
- mlflow/genai/labeling/labeling.py +250 -0
- mlflow/genai/optimize/__init__.py +13 -0
- mlflow/genai/optimize/base.py +198 -0
- mlflow/genai/optimize/optimizers/__init__.py +4 -0
- mlflow/genai/optimize/optimizers/base_optimizer.py +38 -0
- mlflow/genai/optimize/optimizers/dspy_mipro_optimizer.py +221 -0
- mlflow/genai/optimize/optimizers/dspy_optimizer.py +91 -0
- mlflow/genai/optimize/optimizers/utils/dspy_mipro_callback.py +76 -0
- mlflow/genai/optimize/optimizers/utils/dspy_mipro_utils.py +18 -0
- mlflow/genai/optimize/types.py +75 -0
- mlflow/genai/optimize/util.py +30 -0
- mlflow/genai/prompts/__init__.py +206 -0
- mlflow/genai/scheduled_scorers.py +431 -0
- mlflow/genai/scorers/__init__.py +26 -0
- mlflow/genai/scorers/base.py +492 -0
- mlflow/genai/scorers/builtin_scorers.py +765 -0
- mlflow/genai/scorers/scorer_utils.py +138 -0
- mlflow/genai/scorers/validation.py +165 -0
- mlflow/genai/utils/data_validation.py +146 -0
- mlflow/genai/utils/enum_utils.py +23 -0
- mlflow/genai/utils/trace_utils.py +211 -0
- mlflow/groq/__init__.py +42 -0
- mlflow/groq/_groq_autolog.py +74 -0
- mlflow/johnsnowlabs/__init__.py +888 -0
- mlflow/langchain/__init__.py +24 -0
- mlflow/langchain/api_request_parallel_processor.py +330 -0
- mlflow/langchain/autolog.py +147 -0
- mlflow/langchain/chat_agent_langgraph.py +340 -0
- mlflow/langchain/constant.py +1 -0
- mlflow/langchain/constants.py +1 -0
- mlflow/langchain/databricks_dependencies.py +444 -0
- mlflow/langchain/langchain_tracer.py +597 -0
- mlflow/langchain/model.py +919 -0
- mlflow/langchain/output_parsers.py +142 -0
- mlflow/langchain/retriever_chain.py +153 -0
- mlflow/langchain/runnables.py +527 -0
- mlflow/langchain/utils/chat.py +402 -0
- mlflow/langchain/utils/logging.py +671 -0
- mlflow/langchain/utils/serialization.py +36 -0
- mlflow/legacy_databricks_cli/__init__.py +0 -0
- mlflow/legacy_databricks_cli/configure/__init__.py +0 -0
- mlflow/legacy_databricks_cli/configure/provider.py +482 -0
- mlflow/litellm/__init__.py +175 -0
- mlflow/llama_index/__init__.py +22 -0
- mlflow/llama_index/autolog.py +55 -0
- mlflow/llama_index/chat.py +43 -0
- mlflow/llama_index/constant.py +1 -0
- mlflow/llama_index/model.py +577 -0
- mlflow/llama_index/pyfunc_wrapper.py +332 -0
- mlflow/llama_index/serialize_objects.py +188 -0
- mlflow/llama_index/tracer.py +561 -0
- mlflow/metrics/__init__.py +479 -0
- mlflow/metrics/base.py +39 -0
- mlflow/metrics/genai/__init__.py +25 -0
- mlflow/metrics/genai/base.py +101 -0
- mlflow/metrics/genai/genai_metric.py +771 -0
- mlflow/metrics/genai/metric_definitions.py +450 -0
- mlflow/metrics/genai/model_utils.py +371 -0
- mlflow/metrics/genai/prompt_template.py +68 -0
- mlflow/metrics/genai/prompts/__init__.py +0 -0
- mlflow/metrics/genai/prompts/v1.py +422 -0
- mlflow/metrics/genai/utils.py +6 -0
- mlflow/metrics/metric_definitions.py +619 -0
- mlflow/mismatch.py +34 -0
- mlflow/mistral/__init__.py +34 -0
- mlflow/mistral/autolog.py +71 -0
- mlflow/mistral/chat.py +135 -0
- mlflow/ml_package_versions.py +452 -0
- mlflow/models/__init__.py +97 -0
- mlflow/models/auth_policy.py +83 -0
- mlflow/models/cli.py +354 -0
- mlflow/models/container/__init__.py +294 -0
- mlflow/models/container/scoring_server/__init__.py +0 -0
- mlflow/models/container/scoring_server/nginx.conf +39 -0
- mlflow/models/dependencies_schemas.py +287 -0
- mlflow/models/display_utils.py +158 -0
- mlflow/models/docker_utils.py +211 -0
- mlflow/models/evaluation/__init__.py +23 -0
- mlflow/models/evaluation/_shap_patch.py +64 -0
- mlflow/models/evaluation/artifacts.py +194 -0
- mlflow/models/evaluation/base.py +1811 -0
- mlflow/models/evaluation/calibration_curve.py +109 -0
- mlflow/models/evaluation/default_evaluator.py +996 -0
- mlflow/models/evaluation/deprecated.py +23 -0
- mlflow/models/evaluation/evaluator_registry.py +80 -0
- mlflow/models/evaluation/evaluators/classifier.py +704 -0
- mlflow/models/evaluation/evaluators/default.py +233 -0
- mlflow/models/evaluation/evaluators/regressor.py +96 -0
- mlflow/models/evaluation/evaluators/shap.py +296 -0
- mlflow/models/evaluation/lift_curve.py +178 -0
- mlflow/models/evaluation/utils/metric.py +123 -0
- mlflow/models/evaluation/utils/trace.py +179 -0
- mlflow/models/evaluation/validation.py +434 -0
- mlflow/models/flavor_backend.py +93 -0
- mlflow/models/flavor_backend_registry.py +53 -0
- mlflow/models/model.py +1639 -0
- mlflow/models/model_config.py +150 -0
- mlflow/models/notebook_resources/agent_evaluation_template.html +235 -0
- mlflow/models/notebook_resources/eval_with_dataset_example.py +22 -0
- mlflow/models/notebook_resources/eval_with_synthetic_example.py +22 -0
- mlflow/models/python_api.py +369 -0
- mlflow/models/rag_signatures.py +128 -0
- mlflow/models/resources.py +321 -0
- mlflow/models/signature.py +662 -0
- mlflow/models/utils.py +2054 -0
- mlflow/models/wheeled_model.py +280 -0
- mlflow/openai/__init__.py +57 -0
- mlflow/openai/_agent_tracer.py +364 -0
- mlflow/openai/api_request_parallel_processor.py +131 -0
- mlflow/openai/autolog.py +509 -0
- mlflow/openai/constant.py +1 -0
- mlflow/openai/model.py +824 -0
- mlflow/openai/utils/chat_schema.py +367 -0
- mlflow/optuna/__init__.py +3 -0
- mlflow/optuna/storage.py +646 -0
- mlflow/plugins/__init__.py +72 -0
- mlflow/plugins/base.py +358 -0
- mlflow/plugins/builtin/__init__.py +24 -0
- mlflow/plugins/builtin/pytorch_plugin.py +150 -0
- mlflow/plugins/builtin/sklearn_plugin.py +158 -0
- mlflow/plugins/builtin/transformers_plugin.py +187 -0
- mlflow/plugins/cli.py +321 -0
- mlflow/plugins/discovery.py +340 -0
- mlflow/plugins/manager.py +465 -0
- mlflow/plugins/registry.py +316 -0
- mlflow/plugins/templates/framework_plugin_template.py +329 -0
- mlflow/prompt/constants.py +20 -0
- mlflow/prompt/promptlab_model.py +197 -0
- mlflow/prompt/registry_utils.py +248 -0
- mlflow/promptflow/__init__.py +495 -0
- mlflow/protos/__init__.py +0 -0
- mlflow/protos/assessments_pb2.py +174 -0
- mlflow/protos/databricks_artifacts_pb2.py +489 -0
- mlflow/protos/databricks_filesystem_service_pb2.py +196 -0
- mlflow/protos/databricks_managed_catalog_messages_pb2.py +95 -0
- mlflow/protos/databricks_managed_catalog_service_pb2.py +86 -0
- mlflow/protos/databricks_pb2.py +267 -0
- mlflow/protos/databricks_trace_server_pb2.py +374 -0
- mlflow/protos/databricks_uc_registry_messages_pb2.py +1249 -0
- mlflow/protos/databricks_uc_registry_service_pb2.py +170 -0
- mlflow/protos/facet_feature_statistics_pb2.py +296 -0
- mlflow/protos/internal_pb2.py +77 -0
- mlflow/protos/mlflow_artifacts_pb2.py +336 -0
- mlflow/protos/model_registry_pb2.py +1073 -0
- mlflow/protos/scalapb/__init__.py +0 -0
- mlflow/protos/scalapb/scalapb_pb2.py +104 -0
- mlflow/protos/service_pb2.py +2600 -0
- mlflow/protos/unity_catalog_oss_messages_pb2.py +457 -0
- mlflow/protos/unity_catalog_oss_service_pb2.py +130 -0
- mlflow/protos/unity_catalog_prompt_messages_pb2.py +447 -0
- mlflow/protos/unity_catalog_prompt_messages_pb2_grpc.py +24 -0
- mlflow/protos/unity_catalog_prompt_service_pb2.py +164 -0
- mlflow/protos/unity_catalog_prompt_service_pb2_grpc.py +785 -0
- mlflow/py.typed +0 -0
- mlflow/pydantic_ai/__init__.py +57 -0
- mlflow/pydantic_ai/autolog.py +173 -0
- mlflow/pyfunc/__init__.py +3844 -0
- mlflow/pyfunc/_mlflow_pyfunc_backend_predict.py +61 -0
- mlflow/pyfunc/backend.py +523 -0
- mlflow/pyfunc/context.py +78 -0
- mlflow/pyfunc/dbconnect_artifact_cache.py +144 -0
- mlflow/pyfunc/loaders/__init__.py +7 -0
- mlflow/pyfunc/loaders/chat_agent.py +117 -0
- mlflow/pyfunc/loaders/chat_model.py +125 -0
- mlflow/pyfunc/loaders/code_model.py +31 -0
- mlflow/pyfunc/loaders/responses_agent.py +112 -0
- mlflow/pyfunc/mlserver.py +46 -0
- mlflow/pyfunc/model.py +1473 -0
- mlflow/pyfunc/scoring_server/__init__.py +604 -0
- mlflow/pyfunc/scoring_server/app.py +7 -0
- mlflow/pyfunc/scoring_server/client.py +146 -0
- mlflow/pyfunc/spark_model_cache.py +48 -0
- mlflow/pyfunc/stdin_server.py +44 -0
- mlflow/pyfunc/utils/__init__.py +3 -0
- mlflow/pyfunc/utils/data_validation.py +224 -0
- mlflow/pyfunc/utils/environment.py +22 -0
- mlflow/pyfunc/utils/input_converter.py +47 -0
- mlflow/pyfunc/utils/serving_data_parser.py +11 -0
- mlflow/pytorch/__init__.py +1171 -0
- mlflow/pytorch/_lightning_autolog.py +580 -0
- mlflow/pytorch/_pytorch_autolog.py +50 -0
- mlflow/pytorch/pickle_module.py +35 -0
- mlflow/rfunc/__init__.py +42 -0
- mlflow/rfunc/backend.py +134 -0
- mlflow/runs.py +89 -0
- mlflow/server/__init__.py +302 -0
- mlflow/server/auth/__init__.py +1224 -0
- mlflow/server/auth/__main__.py +4 -0
- mlflow/server/auth/basic_auth.ini +6 -0
- mlflow/server/auth/cli.py +11 -0
- mlflow/server/auth/client.py +537 -0
- mlflow/server/auth/config.py +34 -0
- mlflow/server/auth/db/__init__.py +0 -0
- mlflow/server/auth/db/cli.py +18 -0
- mlflow/server/auth/db/migrations/__init__.py +0 -0
- mlflow/server/auth/db/migrations/alembic.ini +110 -0
- mlflow/server/auth/db/migrations/env.py +76 -0
- mlflow/server/auth/db/migrations/versions/8606fa83a998_initial_migration.py +51 -0
- mlflow/server/auth/db/migrations/versions/__init__.py +0 -0
- mlflow/server/auth/db/models.py +67 -0
- mlflow/server/auth/db/utils.py +37 -0
- mlflow/server/auth/entities.py +165 -0
- mlflow/server/auth/logo.py +14 -0
- mlflow/server/auth/permissions.py +65 -0
- mlflow/server/auth/routes.py +18 -0
- mlflow/server/auth/sqlalchemy_store.py +263 -0
- mlflow/server/graphql/__init__.py +0 -0
- mlflow/server/graphql/autogenerated_graphql_schema.py +353 -0
- mlflow/server/graphql/graphql_custom_scalars.py +24 -0
- mlflow/server/graphql/graphql_errors.py +15 -0
- mlflow/server/graphql/graphql_no_batching.py +89 -0
- mlflow/server/graphql/graphql_schema_extensions.py +74 -0
- mlflow/server/handlers.py +3217 -0
- mlflow/server/prometheus_exporter.py +17 -0
- mlflow/server/validation.py +30 -0
- mlflow/shap/__init__.py +691 -0
- mlflow/sklearn/__init__.py +1994 -0
- mlflow/sklearn/utils.py +1041 -0
- mlflow/smolagents/__init__.py +66 -0
- mlflow/smolagents/autolog.py +139 -0
- mlflow/smolagents/chat.py +29 -0
- mlflow/store/__init__.py +10 -0
- mlflow/store/_unity_catalog/__init__.py +1 -0
- mlflow/store/_unity_catalog/lineage/__init__.py +1 -0
- mlflow/store/_unity_catalog/lineage/constants.py +2 -0
- mlflow/store/_unity_catalog/registry/__init__.py +6 -0
- mlflow/store/_unity_catalog/registry/prompt_info.py +75 -0
- mlflow/store/_unity_catalog/registry/rest_store.py +1740 -0
- mlflow/store/_unity_catalog/registry/uc_oss_rest_store.py +507 -0
- mlflow/store/_unity_catalog/registry/utils.py +121 -0
- mlflow/store/artifact/__init__.py +0 -0
- mlflow/store/artifact/artifact_repo.py +472 -0
- mlflow/store/artifact/artifact_repository_registry.py +154 -0
- mlflow/store/artifact/azure_blob_artifact_repo.py +275 -0
- mlflow/store/artifact/azure_data_lake_artifact_repo.py +295 -0
- mlflow/store/artifact/cli.py +141 -0
- mlflow/store/artifact/cloud_artifact_repo.py +332 -0
- mlflow/store/artifact/databricks_artifact_repo.py +729 -0
- mlflow/store/artifact/databricks_artifact_repo_resources.py +301 -0
- mlflow/store/artifact/databricks_logged_model_artifact_repo.py +93 -0
- mlflow/store/artifact/databricks_models_artifact_repo.py +216 -0
- mlflow/store/artifact/databricks_sdk_artifact_repo.py +134 -0
- mlflow/store/artifact/databricks_sdk_models_artifact_repo.py +97 -0
- mlflow/store/artifact/dbfs_artifact_repo.py +240 -0
- mlflow/store/artifact/ftp_artifact_repo.py +132 -0
- mlflow/store/artifact/gcs_artifact_repo.py +296 -0
- mlflow/store/artifact/hdfs_artifact_repo.py +209 -0
- mlflow/store/artifact/http_artifact_repo.py +218 -0
- mlflow/store/artifact/local_artifact_repo.py +142 -0
- mlflow/store/artifact/mlflow_artifacts_repo.py +94 -0
- mlflow/store/artifact/models_artifact_repo.py +259 -0
- mlflow/store/artifact/optimized_s3_artifact_repo.py +356 -0
- mlflow/store/artifact/presigned_url_artifact_repo.py +173 -0
- mlflow/store/artifact/r2_artifact_repo.py +70 -0
- mlflow/store/artifact/runs_artifact_repo.py +265 -0
- mlflow/store/artifact/s3_artifact_repo.py +330 -0
- mlflow/store/artifact/sftp_artifact_repo.py +141 -0
- mlflow/store/artifact/uc_volume_artifact_repo.py +76 -0
- mlflow/store/artifact/unity_catalog_models_artifact_repo.py +168 -0
- mlflow/store/artifact/unity_catalog_oss_models_artifact_repo.py +168 -0
- mlflow/store/artifact/utils/__init__.py +0 -0
- mlflow/store/artifact/utils/models.py +148 -0
- mlflow/store/db/__init__.py +0 -0
- mlflow/store/db/base_sql_model.py +3 -0
- mlflow/store/db/db_types.py +10 -0
- mlflow/store/db/utils.py +314 -0
- mlflow/store/db_migrations/__init__.py +0 -0
- mlflow/store/db_migrations/alembic.ini +74 -0
- mlflow/store/db_migrations/env.py +84 -0
- mlflow/store/db_migrations/versions/0584bdc529eb_add_cascading_deletion_to_datasets_from_experiments.py +88 -0
- mlflow/store/db_migrations/versions/0a8213491aaa_drop_duplicate_killed_constraint.py +49 -0
- mlflow/store/db_migrations/versions/0c779009ac13_add_deleted_time_field_to_runs_table.py +24 -0
- mlflow/store/db_migrations/versions/181f10493468_allow_nulls_for_metric_values.py +35 -0
- mlflow/store/db_migrations/versions/27a6a02d2cf1_add_model_version_tags_table.py +38 -0
- mlflow/store/db_migrations/versions/2b4d017a5e9b_add_model_registry_tables_to_db.py +77 -0
- mlflow/store/db_migrations/versions/2d6e25af4d3e_increase_max_param_val_length.py +33 -0
- mlflow/store/db_migrations/versions/3500859a5d39_add_model_aliases_table.py +50 -0
- mlflow/store/db_migrations/versions/39d1c3be5f05_add_is_nan_constraint_for_metrics_tables_if_necessary.py +41 -0
- mlflow/store/db_migrations/versions/400f98739977_add_logged_model_tables.py +123 -0
- mlflow/store/db_migrations/versions/4465047574b1_increase_max_dataset_schema_size.py +38 -0
- mlflow/store/db_migrations/versions/451aebb31d03_add_metric_step.py +35 -0
- mlflow/store/db_migrations/versions/5b0e9adcef9c_add_cascade_deletion_to_trace_tables_fk.py +40 -0
- mlflow/store/db_migrations/versions/6953534de441_add_step_to_inputs_table.py +25 -0
- mlflow/store/db_migrations/versions/728d730b5ebd_add_registered_model_tags_table.py +38 -0
- mlflow/store/db_migrations/versions/7ac759974ad8_update_run_tags_with_larger_limit.py +36 -0
- mlflow/store/db_migrations/versions/7f2a7d5fae7d_add_datasets_inputs_input_tags_tables.py +82 -0
- mlflow/store/db_migrations/versions/84291f40a231_add_run_link_to_model_version.py +26 -0
- mlflow/store/db_migrations/versions/867495a8f9d4_add_trace_tables.py +90 -0
- mlflow/store/db_migrations/versions/89d4b8295536_create_latest_metrics_table.py +169 -0
- mlflow/store/db_migrations/versions/90e64c465722_migrate_user_column_to_tags.py +64 -0
- mlflow/store/db_migrations/versions/97727af70f4d_creation_time_last_update_time_experiments.py +25 -0
- mlflow/store/db_migrations/versions/__init__.py +0 -0
- mlflow/store/db_migrations/versions/a8c4a736bde6_allow_nulls_for_run_id.py +27 -0
- mlflow/store/db_migrations/versions/acf3f17fdcc7_add_storage_location_field_to_model_.py +29 -0
- mlflow/store/db_migrations/versions/bd07f7e963c5_create_index_on_run_uuid.py +26 -0
- mlflow/store/db_migrations/versions/bda7b8c39065_increase_model_version_tag_value_limit.py +38 -0
- mlflow/store/db_migrations/versions/c48cb773bb87_reset_default_value_for_is_nan_in_metrics_table_for_mysql.py +41 -0
- mlflow/store/db_migrations/versions/cbc13b556ace_add_v3_trace_schema_columns.py +31 -0
- mlflow/store/db_migrations/versions/cc1f77228345_change_param_value_length_to_500.py +34 -0
- mlflow/store/db_migrations/versions/cfd24bdc0731_update_run_status_constraint_with_killed.py +78 -0
- mlflow/store/db_migrations/versions/df50e92ffc5e_add_experiment_tags_table.py +38 -0
- mlflow/store/db_migrations/versions/f5a4f2784254_increase_run_tag_value_limit.py +36 -0
- mlflow/store/entities/__init__.py +3 -0
- mlflow/store/entities/paged_list.py +18 -0
- mlflow/store/model_registry/__init__.py +10 -0
- mlflow/store/model_registry/abstract_store.py +1081 -0
- mlflow/store/model_registry/base_rest_store.py +44 -0
- mlflow/store/model_registry/databricks_workspace_model_registry_rest_store.py +37 -0
- mlflow/store/model_registry/dbmodels/__init__.py +0 -0
- mlflow/store/model_registry/dbmodels/models.py +206 -0
- mlflow/store/model_registry/file_store.py +1091 -0
- mlflow/store/model_registry/rest_store.py +481 -0
- mlflow/store/model_registry/sqlalchemy_store.py +1286 -0
- mlflow/store/tracking/__init__.py +23 -0
- mlflow/store/tracking/abstract_store.py +816 -0
- mlflow/store/tracking/dbmodels/__init__.py +0 -0
- mlflow/store/tracking/dbmodels/initial_models.py +243 -0
- mlflow/store/tracking/dbmodels/models.py +1073 -0
- mlflow/store/tracking/file_store.py +2438 -0
- mlflow/store/tracking/postgres_managed_identity.py +146 -0
- mlflow/store/tracking/rest_store.py +1131 -0
- mlflow/store/tracking/sqlalchemy_store.py +2785 -0
- mlflow/system_metrics/__init__.py +61 -0
- mlflow/system_metrics/metrics/__init__.py +0 -0
- mlflow/system_metrics/metrics/base_metrics_monitor.py +32 -0
- mlflow/system_metrics/metrics/cpu_monitor.py +23 -0
- mlflow/system_metrics/metrics/disk_monitor.py +21 -0
- mlflow/system_metrics/metrics/gpu_monitor.py +71 -0
- mlflow/system_metrics/metrics/network_monitor.py +34 -0
- mlflow/system_metrics/metrics/rocm_monitor.py +123 -0
- mlflow/system_metrics/system_metrics_monitor.py +198 -0
- mlflow/tracing/__init__.py +16 -0
- mlflow/tracing/assessment.py +356 -0
- mlflow/tracing/client.py +531 -0
- mlflow/tracing/config.py +125 -0
- mlflow/tracing/constant.py +105 -0
- mlflow/tracing/destination.py +81 -0
- mlflow/tracing/display/__init__.py +40 -0
- mlflow/tracing/display/display_handler.py +196 -0
- mlflow/tracing/export/async_export_queue.py +186 -0
- mlflow/tracing/export/inference_table.py +138 -0
- mlflow/tracing/export/mlflow_v3.py +137 -0
- mlflow/tracing/export/utils.py +70 -0
- mlflow/tracing/fluent.py +1417 -0
- mlflow/tracing/processor/base_mlflow.py +199 -0
- mlflow/tracing/processor/inference_table.py +175 -0
- mlflow/tracing/processor/mlflow_v3.py +47 -0
- mlflow/tracing/processor/otel.py +73 -0
- mlflow/tracing/provider.py +487 -0
- mlflow/tracing/trace_manager.py +200 -0
- mlflow/tracing/utils/__init__.py +616 -0
- mlflow/tracing/utils/artifact_utils.py +28 -0
- mlflow/tracing/utils/copy.py +55 -0
- mlflow/tracing/utils/environment.py +55 -0
- mlflow/tracing/utils/exception.py +21 -0
- mlflow/tracing/utils/once.py +35 -0
- mlflow/tracing/utils/otlp.py +63 -0
- mlflow/tracing/utils/processor.py +54 -0
- mlflow/tracing/utils/search.py +292 -0
- mlflow/tracing/utils/timeout.py +250 -0
- mlflow/tracing/utils/token.py +19 -0
- mlflow/tracing/utils/truncation.py +124 -0
- mlflow/tracing/utils/warning.py +76 -0
- mlflow/tracking/__init__.py +39 -0
- mlflow/tracking/_model_registry/__init__.py +1 -0
- mlflow/tracking/_model_registry/client.py +764 -0
- mlflow/tracking/_model_registry/fluent.py +853 -0
- mlflow/tracking/_model_registry/registry.py +67 -0
- mlflow/tracking/_model_registry/utils.py +251 -0
- mlflow/tracking/_tracking_service/__init__.py +0 -0
- mlflow/tracking/_tracking_service/client.py +883 -0
- mlflow/tracking/_tracking_service/registry.py +56 -0
- mlflow/tracking/_tracking_service/utils.py +275 -0
- mlflow/tracking/artifact_utils.py +179 -0
- mlflow/tracking/client.py +5900 -0
- mlflow/tracking/context/__init__.py +0 -0
- mlflow/tracking/context/abstract_context.py +35 -0
- mlflow/tracking/context/databricks_cluster_context.py +15 -0
- mlflow/tracking/context/databricks_command_context.py +15 -0
- mlflow/tracking/context/databricks_job_context.py +49 -0
- mlflow/tracking/context/databricks_notebook_context.py +41 -0
- mlflow/tracking/context/databricks_repo_context.py +43 -0
- mlflow/tracking/context/default_context.py +51 -0
- mlflow/tracking/context/git_context.py +32 -0
- mlflow/tracking/context/registry.py +98 -0
- mlflow/tracking/context/system_environment_context.py +15 -0
- mlflow/tracking/default_experiment/__init__.py +1 -0
- mlflow/tracking/default_experiment/abstract_context.py +43 -0
- mlflow/tracking/default_experiment/databricks_notebook_experiment_provider.py +44 -0
- mlflow/tracking/default_experiment/registry.py +75 -0
- mlflow/tracking/fluent.py +3595 -0
- mlflow/tracking/metric_value_conversion_utils.py +93 -0
- mlflow/tracking/multimedia.py +206 -0
- mlflow/tracking/registry.py +86 -0
- mlflow/tracking/request_auth/__init__.py +0 -0
- mlflow/tracking/request_auth/abstract_request_auth_provider.py +34 -0
- mlflow/tracking/request_auth/registry.py +60 -0
- mlflow/tracking/request_header/__init__.py +0 -0
- mlflow/tracking/request_header/abstract_request_header_provider.py +36 -0
- mlflow/tracking/request_header/databricks_request_header_provider.py +38 -0
- mlflow/tracking/request_header/default_request_header_provider.py +17 -0
- mlflow/tracking/request_header/registry.py +79 -0
- mlflow/transformers/__init__.py +2982 -0
- mlflow/transformers/flavor_config.py +258 -0
- mlflow/transformers/hub_utils.py +83 -0
- mlflow/transformers/llm_inference_utils.py +468 -0
- mlflow/transformers/model_io.py +301 -0
- mlflow/transformers/peft.py +51 -0
- mlflow/transformers/signature.py +183 -0
- mlflow/transformers/torch_utils.py +55 -0
- mlflow/types/__init__.py +21 -0
- mlflow/types/agent.py +270 -0
- mlflow/types/chat.py +240 -0
- mlflow/types/llm.py +935 -0
- mlflow/types/responses.py +139 -0
- mlflow/types/responses_helpers.py +416 -0
- mlflow/types/schema.py +1505 -0
- mlflow/types/type_hints.py +647 -0
- mlflow/types/utils.py +753 -0
- mlflow/utils/__init__.py +283 -0
- mlflow/utils/_capture_modules.py +256 -0
- mlflow/utils/_capture_transformers_modules.py +75 -0
- mlflow/utils/_spark_utils.py +201 -0
- mlflow/utils/_unity_catalog_oss_utils.py +97 -0
- mlflow/utils/_unity_catalog_utils.py +479 -0
- mlflow/utils/annotations.py +218 -0
- mlflow/utils/arguments_utils.py +16 -0
- mlflow/utils/async_logging/__init__.py +1 -0
- mlflow/utils/async_logging/async_artifacts_logging_queue.py +258 -0
- mlflow/utils/async_logging/async_logging_queue.py +366 -0
- mlflow/utils/async_logging/run_artifact.py +38 -0
- mlflow/utils/async_logging/run_batch.py +58 -0
- mlflow/utils/async_logging/run_operations.py +49 -0
- mlflow/utils/autologging_utils/__init__.py +737 -0
- mlflow/utils/autologging_utils/client.py +432 -0
- mlflow/utils/autologging_utils/config.py +33 -0
- mlflow/utils/autologging_utils/events.py +294 -0
- mlflow/utils/autologging_utils/logging_and_warnings.py +328 -0
- mlflow/utils/autologging_utils/metrics_queue.py +71 -0
- mlflow/utils/autologging_utils/safety.py +1104 -0
- mlflow/utils/autologging_utils/versioning.py +95 -0
- mlflow/utils/checkpoint_utils.py +206 -0
- mlflow/utils/class_utils.py +6 -0
- mlflow/utils/cli_args.py +257 -0
- mlflow/utils/conda.py +354 -0
- mlflow/utils/credentials.py +231 -0
- mlflow/utils/data_utils.py +17 -0
- mlflow/utils/databricks_utils.py +1436 -0
- mlflow/utils/docstring_utils.py +477 -0
- mlflow/utils/doctor.py +133 -0
- mlflow/utils/download_cloud_file_chunk.py +43 -0
- mlflow/utils/env_manager.py +16 -0
- mlflow/utils/env_pack.py +131 -0
- mlflow/utils/environment.py +1009 -0
- mlflow/utils/exception_utils.py +14 -0
- mlflow/utils/file_utils.py +978 -0
- mlflow/utils/git_utils.py +77 -0
- mlflow/utils/gorilla.py +797 -0
- mlflow/utils/import_hooks/__init__.py +363 -0
- mlflow/utils/lazy_load.py +51 -0
- mlflow/utils/logging_utils.py +168 -0
- mlflow/utils/mime_type_utils.py +58 -0
- mlflow/utils/mlflow_tags.py +103 -0
- mlflow/utils/model_utils.py +486 -0
- mlflow/utils/name_utils.py +346 -0
- mlflow/utils/nfs_on_spark.py +62 -0
- mlflow/utils/openai_utils.py +164 -0
- mlflow/utils/os.py +12 -0
- mlflow/utils/oss_registry_utils.py +29 -0
- mlflow/utils/plugins.py +17 -0
- mlflow/utils/process.py +182 -0
- mlflow/utils/promptlab_utils.py +146 -0
- mlflow/utils/proto_json_utils.py +743 -0
- mlflow/utils/pydantic_utils.py +54 -0
- mlflow/utils/request_utils.py +279 -0
- mlflow/utils/requirements_utils.py +704 -0
- mlflow/utils/rest_utils.py +673 -0
- mlflow/utils/search_logged_model_utils.py +127 -0
- mlflow/utils/search_utils.py +2111 -0
- mlflow/utils/secure_loading.py +221 -0
- mlflow/utils/security_validation.py +384 -0
- mlflow/utils/server_cli_utils.py +61 -0
- mlflow/utils/spark_utils.py +15 -0
- mlflow/utils/string_utils.py +138 -0
- mlflow/utils/thread_utils.py +63 -0
- mlflow/utils/time.py +54 -0
- mlflow/utils/timeout.py +42 -0
- mlflow/utils/uri.py +572 -0
- mlflow/utils/validation.py +662 -0
- mlflow/utils/virtualenv.py +458 -0
- mlflow/utils/warnings_utils.py +25 -0
- mlflow/utils/yaml_utils.py +179 -0
- mlflow/version.py +24 -0
mlflow/utils/uri.py
ADDED
@@ -0,0 +1,572 @@
|
|
1
|
+
import os
|
2
|
+
import pathlib
|
3
|
+
import posixpath
|
4
|
+
import re
|
5
|
+
import urllib.parse
|
6
|
+
import uuid
|
7
|
+
from typing import Any
|
8
|
+
|
9
|
+
from mlflow.exceptions import MlflowException
|
10
|
+
from mlflow.protos.databricks_pb2 import INVALID_PARAMETER_VALUE
|
11
|
+
from mlflow.utils.os import is_windows
|
12
|
+
from mlflow.utils.validation import _validate_db_type_string
|
13
|
+
|
14
|
+
_INVALID_DB_URI_MSG = (
|
15
|
+
"Please refer to https://mlflow.org/docs/latest/tracking.html#storage for "
|
16
|
+
"format specifications."
|
17
|
+
)
|
18
|
+
|
19
|
+
_DBFS_FUSE_PREFIX = "/dbfs/"
|
20
|
+
_DBFS_HDFS_URI_PREFIX = "dbfs:/"
|
21
|
+
_uc_volume_URI_PREFIX = "/Volumes/"
|
22
|
+
_uc_model_URI_PREFIX = "/Models/"
|
23
|
+
_UC_DBFS_SYMLINK_PREFIX = "/.fuse-mounts/"
|
24
|
+
_DATABRICKS_UNITY_CATALOG_SCHEME = "databricks-uc"
|
25
|
+
_OSS_UNITY_CATALOG_SCHEME = "uc"
|
26
|
+
|
27
|
+
|
28
|
+
def is_local_uri(uri, is_tracking_or_registry_uri=True):
|
29
|
+
"""Returns true if the specified URI is a local file path (/foo or file:/foo).
|
30
|
+
|
31
|
+
Args:
|
32
|
+
uri: The URI.
|
33
|
+
is_tracking_or_registry_uri: Whether or not the specified URI is an MLflow Tracking or
|
34
|
+
MLflow Model Registry URI. Examples of other URIs are MLflow artifact URIs,
|
35
|
+
filesystem paths, etc.
|
36
|
+
"""
|
37
|
+
if uri == "databricks" and is_tracking_or_registry_uri:
|
38
|
+
return False
|
39
|
+
|
40
|
+
if is_windows() and uri.startswith("\\\\"):
|
41
|
+
# windows network drive path looks like: "\\<server name>\path\..."
|
42
|
+
return False
|
43
|
+
|
44
|
+
parsed_uri = urllib.parse.urlparse(uri)
|
45
|
+
scheme = parsed_uri.scheme
|
46
|
+
if scheme == "":
|
47
|
+
return True
|
48
|
+
|
49
|
+
is_remote_hostname = parsed_uri.hostname and not (
|
50
|
+
parsed_uri.hostname == "."
|
51
|
+
or parsed_uri.hostname.startswith("localhost")
|
52
|
+
or parsed_uri.hostname.startswith("127.0.0.1")
|
53
|
+
)
|
54
|
+
if scheme == "file":
|
55
|
+
if is_remote_hostname:
|
56
|
+
raise MlflowException(
|
57
|
+
f"{uri} is not a valid remote uri. For remote access "
|
58
|
+
"on windows, please consider using a different scheme "
|
59
|
+
"such as SMB (e.g. smb://<hostname>/<path>)."
|
60
|
+
)
|
61
|
+
return True
|
62
|
+
|
63
|
+
if is_remote_hostname:
|
64
|
+
return False
|
65
|
+
|
66
|
+
if is_windows() and len(scheme) == 1 and scheme.lower() == pathlib.Path(uri).drive.lower()[0]:
|
67
|
+
return True
|
68
|
+
|
69
|
+
return False
|
70
|
+
|
71
|
+
|
72
|
+
def is_file_uri(uri):
|
73
|
+
scheme = urllib.parse.urlparse(uri).scheme
|
74
|
+
return scheme == "file"
|
75
|
+
|
76
|
+
|
77
|
+
def is_http_uri(uri):
|
78
|
+
scheme = urllib.parse.urlparse(uri).scheme
|
79
|
+
return scheme == "http" or scheme == "https"
|
80
|
+
|
81
|
+
|
82
|
+
def is_databricks_uri(uri):
|
83
|
+
"""
|
84
|
+
Databricks URIs look like 'databricks' (default profile) or 'databricks://profile'
|
85
|
+
or 'databricks://secret_scope:secret_key_prefix'.
|
86
|
+
"""
|
87
|
+
scheme = urllib.parse.urlparse(uri).scheme
|
88
|
+
return scheme == "databricks" or uri == "databricks"
|
89
|
+
|
90
|
+
|
91
|
+
def is_fuse_or_uc_volumes_uri(uri):
|
92
|
+
"""
|
93
|
+
Validates whether a provided URI is directed to a FUSE mount point or a UC volumes mount point.
|
94
|
+
Multiple directory paths are collapsed into a single designator for root path validation.
|
95
|
+
For example, "////Volumes/" will resolve to "/Volumes/" for validation purposes.
|
96
|
+
"""
|
97
|
+
resolved_uri = re.sub("/+", "/", uri).lower()
|
98
|
+
return any(
|
99
|
+
resolved_uri.startswith(x.lower())
|
100
|
+
for x in [
|
101
|
+
_DBFS_FUSE_PREFIX,
|
102
|
+
_DBFS_HDFS_URI_PREFIX,
|
103
|
+
_uc_volume_URI_PREFIX,
|
104
|
+
_uc_model_URI_PREFIX,
|
105
|
+
_UC_DBFS_SYMLINK_PREFIX,
|
106
|
+
]
|
107
|
+
)
|
108
|
+
|
109
|
+
|
110
|
+
def _is_uc_volumes_path(path: str) -> bool:
|
111
|
+
return re.match(r"^/[vV]olumes?/", path) is not None
|
112
|
+
|
113
|
+
|
114
|
+
def is_uc_volumes_uri(uri: str) -> bool:
|
115
|
+
parsed_uri = urllib.parse.urlparse(uri)
|
116
|
+
return parsed_uri.scheme == "dbfs" and _is_uc_volumes_path(parsed_uri.path)
|
117
|
+
|
118
|
+
|
119
|
+
def is_valid_uc_volumes_uri(uri: str) -> bool:
|
120
|
+
parsed_uri = urllib.parse.urlparse(uri)
|
121
|
+
return parsed_uri.scheme == "dbfs" and bool(
|
122
|
+
re.match(r"^/[vV]olumes?/[^/]+/[^/]+/[^/]+/[^/]+", parsed_uri.path)
|
123
|
+
)
|
124
|
+
|
125
|
+
|
126
|
+
def is_databricks_unity_catalog_uri(uri):
|
127
|
+
scheme = urllib.parse.urlparse(uri).scheme
|
128
|
+
return scheme == _DATABRICKS_UNITY_CATALOG_SCHEME or uri == _DATABRICKS_UNITY_CATALOG_SCHEME
|
129
|
+
|
130
|
+
|
131
|
+
def is_oss_unity_catalog_uri(uri):
|
132
|
+
scheme = urllib.parse.urlparse(uri).scheme
|
133
|
+
return scheme == "uc"
|
134
|
+
|
135
|
+
|
136
|
+
def construct_db_uri_from_profile(profile):
|
137
|
+
if profile:
|
138
|
+
return "databricks://" + profile
|
139
|
+
|
140
|
+
|
141
|
+
def construct_db_uc_uri_from_profile(profile):
|
142
|
+
"""
|
143
|
+
Construct a databricks-uc URI from a profile.
|
144
|
+
|
145
|
+
Args:
|
146
|
+
profile: The profile name, optionally with key_prefix (e.g., "profile" or "scope:key")
|
147
|
+
|
148
|
+
Returns:
|
149
|
+
A databricks-uc URI string, or the scheme alone if no profile is provided
|
150
|
+
"""
|
151
|
+
if profile:
|
152
|
+
return f"{_DATABRICKS_UNITY_CATALOG_SCHEME}://{profile}"
|
153
|
+
else:
|
154
|
+
return _DATABRICKS_UNITY_CATALOG_SCHEME
|
155
|
+
|
156
|
+
|
157
|
+
# Both scope and key_prefix should not contain special chars for URIs, like '/'
|
158
|
+
# and ':'.
|
159
|
+
def validate_db_scope_prefix_info(scope, prefix):
|
160
|
+
for c in ["/", ":", " "]:
|
161
|
+
if c in scope:
|
162
|
+
raise MlflowException(
|
163
|
+
f"Unsupported Databricks profile name: {scope}. Profile names cannot contain '{c}'."
|
164
|
+
)
|
165
|
+
if prefix and c in prefix:
|
166
|
+
raise MlflowException(
|
167
|
+
f"Unsupported Databricks profile key prefix: {prefix}."
|
168
|
+
f" Key prefixes cannot contain '{c}'."
|
169
|
+
)
|
170
|
+
if prefix is not None and prefix.strip() == "":
|
171
|
+
raise MlflowException(
|
172
|
+
f"Unsupported Databricks profile key prefix: '{prefix}'. Key prefixes cannot be empty."
|
173
|
+
)
|
174
|
+
|
175
|
+
|
176
|
+
def get_db_info_from_uri(uri):
|
177
|
+
"""
|
178
|
+
Get the Databricks profile specified by the tracking URI (if any), otherwise
|
179
|
+
returns None.
|
180
|
+
"""
|
181
|
+
parsed_uri = urllib.parse.urlparse(uri)
|
182
|
+
if parsed_uri.scheme == "databricks" or parsed_uri.scheme == _DATABRICKS_UNITY_CATALOG_SCHEME:
|
183
|
+
# netloc should not be an empty string unless URI is formatted incorrectly.
|
184
|
+
if parsed_uri.netloc == "":
|
185
|
+
raise MlflowException(
|
186
|
+
f"URI is formatted incorrectly: no netloc in URI '{uri}'."
|
187
|
+
" This may be the case if there is only one slash in the URI."
|
188
|
+
)
|
189
|
+
profile_tokens = parsed_uri.netloc.split(":")
|
190
|
+
parsed_scope = profile_tokens[0]
|
191
|
+
if len(profile_tokens) == 1:
|
192
|
+
parsed_key_prefix = None
|
193
|
+
elif len(profile_tokens) == 2:
|
194
|
+
parsed_key_prefix = profile_tokens[1]
|
195
|
+
else:
|
196
|
+
# parse the content before the first colon as the profile.
|
197
|
+
parsed_key_prefix = ":".join(profile_tokens[1:])
|
198
|
+
validate_db_scope_prefix_info(parsed_scope, parsed_key_prefix)
|
199
|
+
return parsed_scope, parsed_key_prefix
|
200
|
+
return None, None
|
201
|
+
|
202
|
+
|
203
|
+
def get_databricks_profile_uri_from_artifact_uri(uri, result_scheme="databricks"):
|
204
|
+
"""
|
205
|
+
Retrieves the netloc portion of the URI as a ``databricks://`` or `databricks-uc://` URI,
|
206
|
+
if it is a proper Databricks profile specification, e.g.
|
207
|
+
``profile@databricks`` or ``secret_scope:key_prefix@databricks``.
|
208
|
+
"""
|
209
|
+
parsed = urllib.parse.urlparse(uri)
|
210
|
+
if not parsed.netloc or parsed.hostname != result_scheme:
|
211
|
+
return None
|
212
|
+
if not parsed.username: # no profile or scope:key
|
213
|
+
return result_scheme # the default tracking/registry URI
|
214
|
+
validate_db_scope_prefix_info(parsed.username, parsed.password)
|
215
|
+
key_prefix = ":" + parsed.password if parsed.password else ""
|
216
|
+
return f"{result_scheme}://" + parsed.username + key_prefix
|
217
|
+
|
218
|
+
|
219
|
+
def remove_databricks_profile_info_from_artifact_uri(artifact_uri):
|
220
|
+
"""
|
221
|
+
Only removes the netloc portion of the URI if it is a Databricks
|
222
|
+
profile specification, e.g.
|
223
|
+
``profile@databricks`` or ``secret_scope:key_prefix@databricks``.
|
224
|
+
"""
|
225
|
+
parsed = urllib.parse.urlparse(artifact_uri)
|
226
|
+
if not parsed.netloc or parsed.hostname != "databricks":
|
227
|
+
return artifact_uri
|
228
|
+
return urllib.parse.urlunparse(parsed._replace(netloc=""))
|
229
|
+
|
230
|
+
|
231
|
+
def add_databricks_profile_info_to_artifact_uri(artifact_uri, databricks_profile_uri):
|
232
|
+
"""
|
233
|
+
Throws an exception if ``databricks_profile_uri`` is not valid.
|
234
|
+
"""
|
235
|
+
if not databricks_profile_uri or not is_databricks_uri(databricks_profile_uri):
|
236
|
+
return artifact_uri
|
237
|
+
artifact_uri_parsed = urllib.parse.urlparse(artifact_uri)
|
238
|
+
# Do not overwrite the authority section if there is already one
|
239
|
+
if artifact_uri_parsed.netloc:
|
240
|
+
return artifact_uri
|
241
|
+
|
242
|
+
scheme = artifact_uri_parsed.scheme
|
243
|
+
if scheme == "dbfs" or scheme == "runs" or scheme == "models":
|
244
|
+
if databricks_profile_uri == "databricks":
|
245
|
+
netloc = "databricks"
|
246
|
+
else:
|
247
|
+
(profile, key_prefix) = get_db_info_from_uri(databricks_profile_uri)
|
248
|
+
prefix = ":" + key_prefix if key_prefix else ""
|
249
|
+
netloc = profile + prefix + "@databricks"
|
250
|
+
new_parsed = artifact_uri_parsed._replace(netloc=netloc)
|
251
|
+
return urllib.parse.urlunparse(new_parsed)
|
252
|
+
else:
|
253
|
+
return artifact_uri
|
254
|
+
|
255
|
+
|
256
|
+
def extract_db_type_from_uri(db_uri):
|
257
|
+
"""
|
258
|
+
Parse the specified DB URI to extract the database type. Confirm the database type is
|
259
|
+
supported. If a driver is specified, confirm it passes a plausible regex.
|
260
|
+
"""
|
261
|
+
scheme = urllib.parse.urlparse(db_uri).scheme
|
262
|
+
scheme_plus_count = scheme.count("+")
|
263
|
+
|
264
|
+
if scheme_plus_count == 0:
|
265
|
+
db_type = scheme
|
266
|
+
elif scheme_plus_count == 1:
|
267
|
+
db_type, _ = scheme.split("+")
|
268
|
+
else:
|
269
|
+
error_msg = f"Invalid database URI: '{db_uri}'. {_INVALID_DB_URI_MSG}"
|
270
|
+
raise MlflowException(error_msg, INVALID_PARAMETER_VALUE)
|
271
|
+
|
272
|
+
_validate_db_type_string(db_type)
|
273
|
+
|
274
|
+
return db_type
|
275
|
+
|
276
|
+
|
277
|
+
def get_uri_scheme(uri_or_path):
|
278
|
+
from mlflow.store.db.db_types import DATABASE_ENGINES
|
279
|
+
|
280
|
+
scheme = urllib.parse.urlparse(uri_or_path).scheme
|
281
|
+
if any(scheme.lower().startswith(db) for db in DATABASE_ENGINES):
|
282
|
+
return extract_db_type_from_uri(uri_or_path)
|
283
|
+
return scheme
|
284
|
+
|
285
|
+
|
286
|
+
def extract_and_normalize_path(uri):
|
287
|
+
parsed_uri_path = urllib.parse.urlparse(uri).path
|
288
|
+
normalized_path = posixpath.normpath(parsed_uri_path)
|
289
|
+
return normalized_path.lstrip("/")
|
290
|
+
|
291
|
+
|
292
|
+
def append_to_uri_path(uri, *paths):
|
293
|
+
"""Appends the specified POSIX `paths` to the path component of the specified `uri`.
|
294
|
+
|
295
|
+
Args:
|
296
|
+
uri: The input URI, represented as a string.
|
297
|
+
paths: The POSIX paths to append to the specified `uri`'s path component.
|
298
|
+
|
299
|
+
Returns:
|
300
|
+
A new URI with a path component consisting of the specified `paths` appended to
|
301
|
+
the path component of the specified `uri`.
|
302
|
+
|
303
|
+
.. code-block:: python
|
304
|
+
uri1 = "s3://root/base/path?param=value"
|
305
|
+
uri1 = append_to_uri_path(uri1, "some/subpath", "/anotherpath")
|
306
|
+
assert uri1 == "s3://root/base/path/some/subpath/anotherpath?param=value"
|
307
|
+
uri2 = "a/posix/path"
|
308
|
+
uri2 = append_to_uri_path(uri2, "/some", "subpath")
|
309
|
+
assert uri2 == "a/posixpath/some/subpath"
|
310
|
+
"""
|
311
|
+
path = ""
|
312
|
+
for subpath in paths:
|
313
|
+
path = _join_posixpaths_and_append_absolute_suffixes(path, subpath)
|
314
|
+
|
315
|
+
parsed_uri = urllib.parse.urlparse(uri)
|
316
|
+
|
317
|
+
# Validate query string not to contain any traversal path (../) before appending
|
318
|
+
# to the end of the path, otherwise they will be resolved as part of the path.
|
319
|
+
validate_query_string(parsed_uri.query)
|
320
|
+
|
321
|
+
if len(parsed_uri.scheme) == 0:
|
322
|
+
# If the input URI does not define a scheme, we assume that it is a POSIX path
|
323
|
+
# and join it with the specified input paths
|
324
|
+
return _join_posixpaths_and_append_absolute_suffixes(uri, path)
|
325
|
+
|
326
|
+
prefix = ""
|
327
|
+
if not parsed_uri.path.startswith("/"):
|
328
|
+
# For certain URI schemes (e.g., "file:"), urllib's unparse routine does
|
329
|
+
# not preserve the relative URI path component properly. In certain cases,
|
330
|
+
# urlunparse converts relative paths to absolute paths. We introduce this logic
|
331
|
+
# to circumvent urlunparse's erroneous conversion
|
332
|
+
prefix = parsed_uri.scheme + ":"
|
333
|
+
parsed_uri = parsed_uri._replace(scheme="")
|
334
|
+
|
335
|
+
new_uri_path = _join_posixpaths_and_append_absolute_suffixes(parsed_uri.path, path)
|
336
|
+
new_parsed_uri = parsed_uri._replace(path=new_uri_path)
|
337
|
+
return prefix + urllib.parse.urlunparse(new_parsed_uri)
|
338
|
+
|
339
|
+
|
340
|
+
def append_to_uri_query_params(uri, *query_params: tuple[str, Any]) -> str:
|
341
|
+
"""Appends the specified query parameters to an existing URI.
|
342
|
+
|
343
|
+
Args:
|
344
|
+
uri: The URI to which to append query parameters.
|
345
|
+
query_params: Query parameters to append. Each parameter should
|
346
|
+
be a 2-element tuple. For example, ``("key", "value")``.
|
347
|
+
"""
|
348
|
+
parsed_uri = urllib.parse.urlparse(uri)
|
349
|
+
parsed_query = urllib.parse.parse_qsl(parsed_uri.query)
|
350
|
+
new_parsed_query = parsed_query + list(query_params)
|
351
|
+
new_query = urllib.parse.urlencode(new_parsed_query)
|
352
|
+
new_parsed_uri = parsed_uri._replace(query=new_query)
|
353
|
+
return urllib.parse.urlunparse(new_parsed_uri)
|
354
|
+
|
355
|
+
|
356
|
+
def _join_posixpaths_and_append_absolute_suffixes(prefix_path, suffix_path):
|
357
|
+
"""
|
358
|
+
Joins the POSIX path `prefix_path` with the POSIX path `suffix_path`. Unlike posixpath.join(),
|
359
|
+
if `suffix_path` is an absolute path, it is appended to prefix_path.
|
360
|
+
|
361
|
+
>>> result1 = _join_posixpaths_and_append_absolute_suffixes("relpath1", "relpath2")
|
362
|
+
>>> assert result1 == "relpath1/relpath2"
|
363
|
+
>>> result2 = _join_posixpaths_and_append_absolute_suffixes("relpath", "/absolutepath")
|
364
|
+
>>> assert result2 == "relpath/absolutepath"
|
365
|
+
>>> result3 = _join_posixpaths_and_append_absolute_suffixes("/absolutepath", "relpath")
|
366
|
+
>>> assert result3 == "/absolutepath/relpath"
|
367
|
+
>>> result4 = _join_posixpaths_and_append_absolute_suffixes(
|
368
|
+
... "/absolutepath1", "/absolutepath2"
|
369
|
+
... )
|
370
|
+
>>> assert result4 == "/absolutepath1/absolutepath2"
|
371
|
+
"""
|
372
|
+
if len(prefix_path) == 0:
|
373
|
+
return suffix_path
|
374
|
+
|
375
|
+
# If the specified prefix path is non-empty, we must relativize the suffix path by removing
|
376
|
+
# the leading slash, if present. Otherwise, posixpath.join() would omit the prefix from the
|
377
|
+
# joined path
|
378
|
+
suffix_path = suffix_path.lstrip(posixpath.sep)
|
379
|
+
return posixpath.join(prefix_path, suffix_path)
|
380
|
+
|
381
|
+
|
382
|
+
def is_databricks_acled_artifacts_uri(artifact_uri):
|
383
|
+
_ACLED_ARTIFACT_URI = "databricks/mlflow-tracking/"
|
384
|
+
artifact_uri_path = extract_and_normalize_path(artifact_uri)
|
385
|
+
return artifact_uri_path.startswith(_ACLED_ARTIFACT_URI)
|
386
|
+
|
387
|
+
|
388
|
+
def is_databricks_model_registry_artifacts_uri(artifact_uri):
|
389
|
+
_MODEL_REGISTRY_ARTIFACT_URI = "databricks/mlflow-registry/"
|
390
|
+
artifact_uri_path = extract_and_normalize_path(artifact_uri)
|
391
|
+
return artifact_uri_path.startswith(_MODEL_REGISTRY_ARTIFACT_URI)
|
392
|
+
|
393
|
+
|
394
|
+
def is_valid_dbfs_uri(uri):
|
395
|
+
parsed = urllib.parse.urlparse(uri)
|
396
|
+
if parsed.scheme != "dbfs":
|
397
|
+
return False
|
398
|
+
try:
|
399
|
+
db_profile_uri = get_databricks_profile_uri_from_artifact_uri(uri)
|
400
|
+
except MlflowException:
|
401
|
+
db_profile_uri = None
|
402
|
+
return not parsed.netloc or db_profile_uri is not None
|
403
|
+
|
404
|
+
|
405
|
+
def dbfs_hdfs_uri_to_fuse_path(dbfs_uri):
|
406
|
+
"""Converts the provided DBFS URI into a DBFS FUSE path
|
407
|
+
|
408
|
+
Args:
|
409
|
+
dbfs_uri: A DBFS URI like "dbfs:/my-directory". Can also be a scheme-less URI like
|
410
|
+
"/my-directory" if running in an environment where the default HDFS filesystem
|
411
|
+
is "dbfs:/" (e.g. Databricks)
|
412
|
+
|
413
|
+
Returns:
|
414
|
+
A DBFS FUSE-style path, e.g. "/dbfs/my-directory"
|
415
|
+
|
416
|
+
"""
|
417
|
+
if not is_valid_dbfs_uri(dbfs_uri) and dbfs_uri == posixpath.abspath(dbfs_uri):
|
418
|
+
# Convert posixpaths (e.g. "/tmp/mlflow") to DBFS URIs by adding "dbfs:/" as a prefix
|
419
|
+
dbfs_uri = "dbfs:" + dbfs_uri
|
420
|
+
if not dbfs_uri.startswith(_DBFS_HDFS_URI_PREFIX):
|
421
|
+
raise MlflowException(
|
422
|
+
f"Path '{dbfs_uri}' did not start with expected DBFS URI "
|
423
|
+
f"prefix '{_DBFS_HDFS_URI_PREFIX}'",
|
424
|
+
)
|
425
|
+
|
426
|
+
return _DBFS_FUSE_PREFIX + dbfs_uri[len(_DBFS_HDFS_URI_PREFIX) :]
|
427
|
+
|
428
|
+
|
429
|
+
def resolve_uri_if_local(local_uri):
|
430
|
+
"""
|
431
|
+
if `local_uri` is passed in as a relative local path, this function
|
432
|
+
resolves it to absolute path relative to current working directory.
|
433
|
+
|
434
|
+
Args:
|
435
|
+
local_uri: Relative or absolute path or local file uri
|
436
|
+
|
437
|
+
Returns:
|
438
|
+
a fully-formed absolute uri path or an absolute filesystem path
|
439
|
+
"""
|
440
|
+
from mlflow.utils.file_utils import local_file_uri_to_path
|
441
|
+
|
442
|
+
if local_uri is not None and is_local_uri(local_uri):
|
443
|
+
scheme = get_uri_scheme(local_uri)
|
444
|
+
cwd = pathlib.Path.cwd()
|
445
|
+
local_path = local_file_uri_to_path(local_uri)
|
446
|
+
if not pathlib.Path(local_path).is_absolute():
|
447
|
+
if scheme == "":
|
448
|
+
if is_windows():
|
449
|
+
return urllib.parse.urlunsplit(
|
450
|
+
(
|
451
|
+
"file",
|
452
|
+
None,
|
453
|
+
cwd.joinpath(local_path).as_posix(),
|
454
|
+
None,
|
455
|
+
None,
|
456
|
+
)
|
457
|
+
)
|
458
|
+
return cwd.joinpath(local_path).as_posix()
|
459
|
+
local_uri_split = urllib.parse.urlsplit(local_uri)
|
460
|
+
return urllib.parse.urlunsplit(
|
461
|
+
(
|
462
|
+
local_uri_split.scheme,
|
463
|
+
None,
|
464
|
+
cwd.joinpath(local_path).as_posix(),
|
465
|
+
local_uri_split.query,
|
466
|
+
local_uri_split.fragment,
|
467
|
+
)
|
468
|
+
)
|
469
|
+
return local_uri
|
470
|
+
|
471
|
+
|
472
|
+
def generate_tmp_dfs_path(dfs_tmp):
|
473
|
+
return posixpath.join(dfs_tmp, str(uuid.uuid4()))
|
474
|
+
|
475
|
+
|
476
|
+
def join_paths(*paths: str) -> str:
|
477
|
+
stripped = (p.strip("/") for p in paths)
|
478
|
+
return "/" + posixpath.normpath(posixpath.join(*stripped))
|
479
|
+
|
480
|
+
|
481
|
+
_OS_ALT_SEPS = [sep for sep in [os.sep, os.path.altsep] if sep is not None and sep != "/"]
|
482
|
+
|
483
|
+
|
484
|
+
def validate_path_is_safe(path):
|
485
|
+
"""
|
486
|
+
Validates that the specified path is safe to join with a trusted prefix. This is a security
|
487
|
+
measure to prevent path traversal attacks.
|
488
|
+
A valid path should:
|
489
|
+
not contain separators other than '/'
|
490
|
+
not contain .. to navigate to parent dir in path
|
491
|
+
not be an absolute path
|
492
|
+
"""
|
493
|
+
from mlflow.utils.file_utils import local_file_uri_to_path
|
494
|
+
|
495
|
+
# We must decode path before validating it
|
496
|
+
path = _decode(path)
|
497
|
+
# If control characters are included in the path, escape them.
|
498
|
+
path = _escape_control_characters(path)
|
499
|
+
|
500
|
+
exc = MlflowException("Invalid path", error_code=INVALID_PARAMETER_VALUE)
|
501
|
+
if "#" in path:
|
502
|
+
raise exc
|
503
|
+
|
504
|
+
if is_file_uri(path):
|
505
|
+
path = local_file_uri_to_path(path)
|
506
|
+
if (
|
507
|
+
any((s in path) for s in _OS_ALT_SEPS)
|
508
|
+
or ".." in path.split("/")
|
509
|
+
or pathlib.PureWindowsPath(path).is_absolute()
|
510
|
+
or pathlib.PurePosixPath(path).is_absolute()
|
511
|
+
or (is_windows() and len(path) >= 2 and path[1] == ":")
|
512
|
+
):
|
513
|
+
raise exc
|
514
|
+
|
515
|
+
return path
|
516
|
+
|
517
|
+
|
518
|
+
def _escape_control_characters(text: str) -> str:
|
519
|
+
# Method to escape control characters (e.g. \u0017)
|
520
|
+
def escape_char(c):
|
521
|
+
code_point = ord(c)
|
522
|
+
|
523
|
+
# If it's a control character (ASCII 0-31 or 127), escape it
|
524
|
+
if (0 <= code_point <= 31) or (code_point == 127):
|
525
|
+
return f"%{code_point:02x}"
|
526
|
+
return c
|
527
|
+
|
528
|
+
return "".join(escape_char(c) for c in text)
|
529
|
+
|
530
|
+
|
531
|
+
def validate_query_string(query):
|
532
|
+
query = _decode(query)
|
533
|
+
# Block query strings contain any traversal path (../) because they
|
534
|
+
# could be resolved as part of the path and allow path traversal.
|
535
|
+
if ".." in query:
|
536
|
+
raise MlflowException("Invalid query string", error_code=INVALID_PARAMETER_VALUE)
|
537
|
+
|
538
|
+
|
539
|
+
def _decode(url):
|
540
|
+
# Keep decoding until the url stops changing (with a max of 10 iterations)
|
541
|
+
for _ in range(10):
|
542
|
+
decoded = urllib.parse.unquote(url)
|
543
|
+
parsed = urllib.parse.urlunparse(urllib.parse.urlparse(decoded))
|
544
|
+
if parsed == url:
|
545
|
+
return url
|
546
|
+
url = parsed
|
547
|
+
|
548
|
+
raise ValueError("Failed to decode url")
|
549
|
+
|
550
|
+
|
551
|
+
def strip_scheme(uri: str) -> str:
|
552
|
+
"""
|
553
|
+
Strips the scheme from the specified URI.
|
554
|
+
|
555
|
+
Example:
|
556
|
+
|
557
|
+
>>> strip_scheme("http://example.com")
|
558
|
+
'//example.com'
|
559
|
+
"""
|
560
|
+
parsed = urllib.parse.urlparse(uri)
|
561
|
+
# `_replace` looks like a private method, but it's actually part of the public API:
|
562
|
+
# https://docs.python.org/3/library/collections.html#collections.somenamedtuple._replace
|
563
|
+
return urllib.parse.urlunparse(parsed._replace(scheme=""))
|
564
|
+
|
565
|
+
|
566
|
+
def is_models_uri(uri: str) -> bool:
|
567
|
+
try:
|
568
|
+
parsed = urllib.parse.urlparse(uri)
|
569
|
+
except ValueError:
|
570
|
+
return False
|
571
|
+
|
572
|
+
return parsed.scheme == "models"
|