openrunner-sdk 2.37.1__tar.gz → 2.37.4__tar.gz
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.
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/.gitignore +4 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/PKG-INFO +1 -1
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/openrunner/__init__.py +322 -2
- openrunner_sdk-2.37.4/openrunner/_safepath.py +33 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/openrunner/api_client.py +237 -8
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/openrunner/artifact.py +23 -12
- openrunner_sdk-2.37.4/openrunner/cache.py +263 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/openrunner/cli.py +606 -1
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/openrunner/datasets.py +236 -13
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/openrunner/gpu/__init__.py +2 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/openrunner/gpu/api_integration.py +23 -0
- openrunner_sdk-2.37.4/openrunner/gpu/runner.py +214 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/openrunner/gpu/workspace_sync.py +2 -5
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/openrunner/install_commands.py +335 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/openrunner/mcp_server.py +252 -8
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/openrunner/migrate.py +2 -3
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/openrunner/model.py +12 -2
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/openrunner/reload.py +10 -3
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/openrunner/run.py +129 -52
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/openrunner/session.py +10 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/pyproject.toml +1 -1
- openrunner_sdk-2.37.4/tests/test_gpu/test_runner.py +154 -0
- openrunner_sdk-2.37.1/openrunner/cache.py +0 -92
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/=6.0 +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/=8.1 +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/README.md +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/openrunner/CLAUDE.md +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/openrunner/_secret_rules.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/openrunner/autoresearch.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/openrunner/buffer.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/openrunner/config.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/openrunner/cost.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/openrunner/dataset.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/openrunner/environment.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/openrunner/evaluation.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/openrunner/feedback.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/openrunner/git_info.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/openrunner/gpu/cost_guard.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/openrunner/gpu/gpu_types.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/openrunner/gpu/price_compare.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/openrunner/gpu/provider_base.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/openrunner/gpu/providers/__init__.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/openrunner/gpu/providers/lambda_cloud.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/openrunner/gpu/providers/modal_provider.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/openrunner/gpu/providers/ovhcloud.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/openrunner/gpu/providers/runpod.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/openrunner/gpu/providers/vastai.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/openrunner/guardrails.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/openrunner/handover.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/openrunner/hooks/patent-lab-post-commit +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/openrunner/integration/__init__.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/openrunner/integration/accelerate.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/openrunner/integration/anthropic_tracer.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/openrunner/integration/catboost.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/openrunner/integration/diffusers.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/openrunner/integration/fastai.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/openrunner/integration/forced_alignment.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/openrunner/integration/gladia.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/openrunner/integration/gymnasium.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/openrunner/integration/huggingface.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/openrunner/integration/hydra.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/openrunner/integration/ignite.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/openrunner/integration/jax.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/openrunner/integration/keras.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/openrunner/integration/langchain.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/openrunner/integration/lightgbm.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/openrunner/integration/lightning.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/openrunner/integration/llamaindex.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/openrunner/integration/openai_finetune.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/openrunner/integration/openai_tracer.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/openrunner/integration/optuna.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/openrunner/integration/pytorch.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/openrunner/integration/sb3.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/openrunner/integration/sklearn.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/openrunner/integration/skypilot.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/openrunner/integration/tensorflow.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/openrunner/integration/trl.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/openrunner/integration/tts.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/openrunner/integration/ultralytics.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/openrunner/integration/voice_agent.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/openrunner/integration/whisper.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/openrunner/integration/xgboost.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/openrunner/launch.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/openrunner/machine.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/openrunner/media.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/openrunner/model_card.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/openrunner/offline.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/openrunner/patent_scan.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/openrunner/pii.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/openrunner/plot.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/openrunner/projects.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/openrunner/prompt.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/openrunner/query_api.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/openrunner/redact.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/openrunner/research.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/openrunner/research_policy.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/openrunner/scorers.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/openrunner/sender.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/openrunner/settings.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/openrunner/summary.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/openrunner/sweep.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/openrunner/sync.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/openrunner/system_metrics.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/openrunner/tensorboard.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/openrunner/tools/__init__.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/openrunner/tools/patent_report.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/openrunner/trace.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/openrunner/transcript_formatter.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/openrunner/wal.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/openrunner/wandb_compat/__init__.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/openrunner/wandb_compat/_shim.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/openrunner/wer.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/scripts/gen_betterleaks_rules.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/tests/__init__.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/tests/conftest.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/tests/fixtures/wandb-export-mini/run-aaa/config.json +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/tests/fixtures/wandb-export-mini/run-aaa/metadata.json +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/tests/fixtures/wandb-export-mini/run-aaa/metrics.jsonl +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/tests/fixtures/wandb-export-mini/run-aaa/summary.json +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/tests/fixtures/wandb-export-mini/run-bbb/artifacts/model-checkpoint/manifest.json +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/tests/fixtures/wandb-export-mini/run-bbb/artifacts/model-checkpoint/weights.bin +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/tests/fixtures/wandb-export-mini/run-bbb/artifacts/sample-image/manifest.json +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/tests/fixtures/wandb-export-mini/run-bbb/artifacts/sample-image/preview.png +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/tests/fixtures/wandb-export-mini/run-bbb/config.json +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/tests/fixtures/wandb-export-mini/run-bbb/metadata.json +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/tests/fixtures/wandb-export-mini/run-bbb/metrics.jsonl +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/tests/fixtures/wandb-export-mini/run-bbb/summary.json +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/tests/integration/__init__.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/tests/integration/conftest.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/tests/integration/test_artifact_round_trip.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/tests/test_alert.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/tests/test_aliases.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/tests/test_api_client.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/tests/test_artifact.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/tests/test_buffer.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/tests/test_cache.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/tests/test_class_scorers.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/tests/test_cli.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/tests/test_config.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/tests/test_evaluation.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/tests/test_finish.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/tests/test_git_info.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/tests/test_gpu/__init__.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/tests/test_gpu/conftest.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/tests/test_gpu/test_cost_guard.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/tests/test_gpu/test_gpu_types.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/tests/test_gpu/test_lambda.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/tests/test_gpu/test_modal.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/tests/test_gpu/test_ovhcloud.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/tests/test_gpu/test_price_compare.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/tests/test_gpu/test_provider_base.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/tests/test_gpu/test_runpod.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/tests/test_gpu/test_sdk_gpu_api.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/tests/test_gpu/test_vastai.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/tests/test_gpu/test_workspace_sync.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/tests/test_init.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/tests/test_install_commands.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/tests/test_integration_fastai.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/tests/test_integration_huggingface.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/tests/test_integration_keras.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/tests/test_integration_langchain.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/tests/test_integration_lightning.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/tests/test_integration_pytorch.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/tests/test_integration_sklearn.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/tests/test_integration_xgboost.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/tests/test_launch.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/tests/test_log.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/tests/test_log_code.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/tests/test_mcp_decisions.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/tests/test_mcp_monitor.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/tests/test_mcp_predictions.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/tests/test_media.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/tests/test_migrate.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/tests/test_offline.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/tests/test_offline_sync.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/tests/test_pii.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/tests/test_plot.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/tests/test_query_api.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/tests/test_resume.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/tests/test_sdk_features.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/tests/test_sender.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/tests/test_session_sync.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/tests/test_summary.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/tests/test_sweep.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/tests/test_system_metrics.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/tests/test_trace.py +0 -0
- {openrunner_sdk-2.37.1 → openrunner_sdk-2.37.4}/tests/test_wandb_compat.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: openrunner-sdk
|
|
3
|
-
Version: 2.37.
|
|
3
|
+
Version: 2.37.4
|
|
4
4
|
Summary: OpenRunner SDK - W&B-compatible ML experiment tracking client
|
|
5
5
|
Project-URL: Homepage, https://github.com/jqueguiner/openrunner
|
|
6
6
|
Project-URL: Repository, https://github.com/jqueguiner/openrunner
|
|
@@ -30,6 +30,10 @@ Public API:
|
|
|
30
30
|
openrunner.alert -> Send an alert for the active run
|
|
31
31
|
openrunner.log_artifact -> Upload an artifact
|
|
32
32
|
openrunner.use_artifact -> Download an artifact (cached)
|
|
33
|
+
openrunner.push -> Publish a model/artifact in one call (HF push_to_hub)
|
|
34
|
+
openrunner.pull -> Download a model/artifact in one call (HF from_pretrained)
|
|
35
|
+
openrunner.load_model -> Pull + unpickle a Model (or return the local dir)
|
|
36
|
+
openrunner.list_files -> List file paths in an artifact version
|
|
33
37
|
openrunner.sweep -> Create a hyperparameter sweep
|
|
34
38
|
openrunner.agent -> Run a sweep agent loop
|
|
35
39
|
openrunner.launch -> Create a remote execution job
|
|
@@ -92,9 +96,9 @@ from openrunner.datasets import (
|
|
|
92
96
|
create_dataset,
|
|
93
97
|
dataset_info,
|
|
94
98
|
index_dataset,
|
|
99
|
+
iter_rows,
|
|
95
100
|
list_datasets,
|
|
96
101
|
link_project,
|
|
97
|
-
list_files,
|
|
98
102
|
load_dataset,
|
|
99
103
|
add_derivation,
|
|
100
104
|
push_dataset,
|
|
@@ -177,7 +181,7 @@ launch.from_run = _launch_from_run # type: ignore[attr-defined]
|
|
|
177
181
|
# openrunner.trace.patch_openai() syntax
|
|
178
182
|
trace.patch_openai = _patch_openai # type: ignore[attr-defined]
|
|
179
183
|
|
|
180
|
-
__version__ = "2.37.
|
|
184
|
+
__version__ = "2.37.4"
|
|
181
185
|
|
|
182
186
|
logger = logging.getLogger("openrunner")
|
|
183
187
|
|
|
@@ -936,6 +940,24 @@ def get_model_card(name: str) -> str | None:
|
|
|
936
940
|
return None
|
|
937
941
|
|
|
938
942
|
|
|
943
|
+
# --- README aliases -------------------------------------------------------
|
|
944
|
+
# Artifacts are untyped file buckets; each carries a README.md, which is
|
|
945
|
+
# stored as the artifact's model card (``card_markdown``). ``set_readme`` /
|
|
946
|
+
# ``get_readme`` are thin aliases over ``set_model_card`` / ``get_model_card``
|
|
947
|
+
# for callers who think of it as a README rather than a "model card".
|
|
948
|
+
|
|
949
|
+
def set_readme(name: str, readme: str) -> dict[str, Any] | None:
|
|
950
|
+
"""Set the README (model card) on an artifact by name. Alias of
|
|
951
|
+
:func:`set_model_card`. Never raises."""
|
|
952
|
+
return set_model_card(name, readme)
|
|
953
|
+
|
|
954
|
+
|
|
955
|
+
def get_readme(name: str) -> str | None:
|
|
956
|
+
"""Return the README (card_markdown) for an artifact by name. Alias of
|
|
957
|
+
:func:`get_model_card`. Never raises."""
|
|
958
|
+
return get_model_card(name)
|
|
959
|
+
|
|
960
|
+
|
|
939
961
|
def use_artifact(
|
|
940
962
|
name: str, version: int | None = None, alias: str | None = None
|
|
941
963
|
) -> Path | None:
|
|
@@ -962,6 +984,304 @@ def use_artifact(
|
|
|
962
984
|
return None
|
|
963
985
|
|
|
964
986
|
|
|
987
|
+
# ---------------------------------------------------------------------------
|
|
988
|
+
# HuggingFace-style one-liner ergonomics: push / pull / load_model / list_files
|
|
989
|
+
# ---------------------------------------------------------------------------
|
|
990
|
+
|
|
991
|
+
|
|
992
|
+
def _split_name(name: str, project: str | None) -> tuple[str, str | None]:
|
|
993
|
+
"""Split a ``"project/name"`` (or ``"org/project/name"``) reference.
|
|
994
|
+
|
|
995
|
+
Accepts either the combined ``"project/name"`` form or a bare ``name``
|
|
996
|
+
plus an explicit ``project=`` argument. The project part may itself be an
|
|
997
|
+
``"org/project"`` reference (which ``init()`` requires).
|
|
998
|
+
|
|
999
|
+
Returns ``(artifact_name, project_or_None)``.
|
|
1000
|
+
|
|
1001
|
+
Examples:
|
|
1002
|
+
_split_name("gladia/my-proj/my-model", None) -> ("my-model", "gladia/my-proj")
|
|
1003
|
+
_split_name("my-proj/my-model", None) -> ("my-model", "my-proj")
|
|
1004
|
+
_split_name("my-model", "gladia/my-proj") -> ("my-model", "gladia/my-proj")
|
|
1005
|
+
"""
|
|
1006
|
+
if "/" in name and project is None:
|
|
1007
|
+
proj, _, artifact = name.rpartition("/")
|
|
1008
|
+
return artifact, (proj or None)
|
|
1009
|
+
return name, project
|
|
1010
|
+
|
|
1011
|
+
|
|
1012
|
+
def _ensure_run(project: str | None) -> "Run | None":
|
|
1013
|
+
"""Return the active run, auto-initializing one if none exists.
|
|
1014
|
+
|
|
1015
|
+
Mirrors how ``model.Model`` resolves a run: reuse ``_active_run`` if set,
|
|
1016
|
+
otherwise create one with ``init(project=...)``. Never double-creates.
|
|
1017
|
+
"""
|
|
1018
|
+
if _active_run is not None:
|
|
1019
|
+
return _active_run
|
|
1020
|
+
return init(project=project, save_code=False)
|
|
1021
|
+
|
|
1022
|
+
|
|
1023
|
+
def push(
|
|
1024
|
+
path: str,
|
|
1025
|
+
name: str,
|
|
1026
|
+
*,
|
|
1027
|
+
aliases: list[str] | None = None,
|
|
1028
|
+
description: str | None = None,
|
|
1029
|
+
card: str | None = None,
|
|
1030
|
+
metadata: dict[str, Any] | None = None,
|
|
1031
|
+
project: str | None = None,
|
|
1032
|
+
) -> dict[str, Any] | None:
|
|
1033
|
+
"""Publish a model/artifact in one call (HuggingFace ``push_to_hub`` style).
|
|
1034
|
+
|
|
1035
|
+
Uploads the file OR directory at ``path`` as an artifact named ``name``.
|
|
1036
|
+
Auto-initializes a run if none is active (reusing the active run otherwise).
|
|
1037
|
+
|
|
1038
|
+
Args:
|
|
1039
|
+
path: Path to a file or directory to upload.
|
|
1040
|
+
name: Artifact name — either ``"project/name"`` or a bare ``name`` with
|
|
1041
|
+
``project=`` supplied.
|
|
1042
|
+
aliases: Optional aliases to tag the version (e.g. ``["production"]``).
|
|
1043
|
+
description: Optional artifact description.
|
|
1044
|
+
card: Optional markdown model card / README set on the artifact after
|
|
1045
|
+
upload (via :func:`set_model_card`).
|
|
1046
|
+
metadata: Optional artifact metadata dict.
|
|
1047
|
+
project: Project (``"org/project"``) when ``name`` is bare.
|
|
1048
|
+
|
|
1049
|
+
Returns:
|
|
1050
|
+
The created version info dict, or None on failure.
|
|
1051
|
+
|
|
1052
|
+
Example::
|
|
1053
|
+
|
|
1054
|
+
openrunner.push("model.safetensors", "gladia/my-project/my-model",
|
|
1055
|
+
aliases=["production"], card=open("README.md").read())
|
|
1056
|
+
"""
|
|
1057
|
+
try:
|
|
1058
|
+
artifact_name, proj = _split_name(name, project)
|
|
1059
|
+
run = _ensure_run(proj)
|
|
1060
|
+
if run is None:
|
|
1061
|
+
logger.warning("openrunner.push(): could not resolve/create a run")
|
|
1062
|
+
return None
|
|
1063
|
+
result = run.log_model(
|
|
1064
|
+
path,
|
|
1065
|
+
name=artifact_name,
|
|
1066
|
+
aliases=aliases,
|
|
1067
|
+
description=description,
|
|
1068
|
+
metadata=metadata,
|
|
1069
|
+
)
|
|
1070
|
+
if result is not None and card:
|
|
1071
|
+
try:
|
|
1072
|
+
run.set_model_card(artifact_name, card)
|
|
1073
|
+
except Exception as e: # noqa: BLE001
|
|
1074
|
+
logger.warning("openrunner.push(): set_model_card failed: %s", e)
|
|
1075
|
+
return result
|
|
1076
|
+
except Exception as e: # noqa: BLE001
|
|
1077
|
+
logger.warning("openrunner.push() failed: %s", e)
|
|
1078
|
+
return None
|
|
1079
|
+
|
|
1080
|
+
|
|
1081
|
+
def pull(
|
|
1082
|
+
name: str,
|
|
1083
|
+
*,
|
|
1084
|
+
revision: int | str | None = None,
|
|
1085
|
+
filename: str | None = None,
|
|
1086
|
+
local_dir: str | None = None,
|
|
1087
|
+
project: str | None = None,
|
|
1088
|
+
) -> str | None:
|
|
1089
|
+
"""Download a model/artifact in one call (HuggingFace ``from_pretrained`` style).
|
|
1090
|
+
|
|
1091
|
+
Auto-initializes a run if none is active (read-only use still needs a run
|
|
1092
|
+
context today).
|
|
1093
|
+
|
|
1094
|
+
Args:
|
|
1095
|
+
name: Artifact name — ``"project/name"`` or bare ``name`` with ``project=``.
|
|
1096
|
+
revision: A version int OR an alias string (e.g. ``"production"``,
|
|
1097
|
+
``"latest"``). Ints map to ``version=``; strings map to ``alias=``.
|
|
1098
|
+
filename: If given, return the path to just this one file within the
|
|
1099
|
+
version (the whole version is still fetched).
|
|
1100
|
+
local_dir: If given, download into this directory instead of the cache.
|
|
1101
|
+
project: Project (``"org/project"``) when ``name`` is bare.
|
|
1102
|
+
|
|
1103
|
+
Returns:
|
|
1104
|
+
The local directory path (or, when ``filename`` is set, the path to that
|
|
1105
|
+
file), or None on failure.
|
|
1106
|
+
|
|
1107
|
+
Example::
|
|
1108
|
+
|
|
1109
|
+
path = openrunner.pull("gladia/my-project/my-model", revision="production")
|
|
1110
|
+
"""
|
|
1111
|
+
try:
|
|
1112
|
+
from pathlib import Path
|
|
1113
|
+
|
|
1114
|
+
artifact_name, proj = _split_name(name, project)
|
|
1115
|
+
run = _ensure_run(proj)
|
|
1116
|
+
if run is None:
|
|
1117
|
+
logger.warning("openrunner.pull(): could not resolve/create a run")
|
|
1118
|
+
return None
|
|
1119
|
+
|
|
1120
|
+
version: int | None = None
|
|
1121
|
+
alias: str | None = None
|
|
1122
|
+
if isinstance(revision, bool): # guard: bool is an int subclass
|
|
1123
|
+
revision = None
|
|
1124
|
+
if isinstance(revision, int):
|
|
1125
|
+
version = revision
|
|
1126
|
+
elif isinstance(revision, str):
|
|
1127
|
+
alias = revision
|
|
1128
|
+
|
|
1129
|
+
if local_dir is not None:
|
|
1130
|
+
local_path = run.use_model(
|
|
1131
|
+
artifact_name, version=version, alias=alias, dest_dir=local_dir
|
|
1132
|
+
)
|
|
1133
|
+
else:
|
|
1134
|
+
result = run.use_artifact(artifact_name, version=version, alias=alias)
|
|
1135
|
+
local_path = str(result) if result is not None else None
|
|
1136
|
+
|
|
1137
|
+
if local_path is None:
|
|
1138
|
+
return None
|
|
1139
|
+
|
|
1140
|
+
if filename:
|
|
1141
|
+
candidate = Path(local_path) / filename
|
|
1142
|
+
if candidate.exists():
|
|
1143
|
+
return str(candidate)
|
|
1144
|
+
# Fall back to a basename match anywhere in the tree.
|
|
1145
|
+
for p in Path(local_path).rglob("*"):
|
|
1146
|
+
if p.is_file() and p.name == filename:
|
|
1147
|
+
return str(p)
|
|
1148
|
+
logger.warning("openrunner.pull(): file %r not found in %s", filename, local_path)
|
|
1149
|
+
return None
|
|
1150
|
+
|
|
1151
|
+
return local_path
|
|
1152
|
+
except Exception as e: # noqa: BLE001
|
|
1153
|
+
logger.warning("openrunner.pull() failed: %s", e)
|
|
1154
|
+
return None
|
|
1155
|
+
|
|
1156
|
+
|
|
1157
|
+
def load_model(
|
|
1158
|
+
name: str,
|
|
1159
|
+
*,
|
|
1160
|
+
revision: int | str | None = None,
|
|
1161
|
+
project: str | None = None,
|
|
1162
|
+
) -> "Any":
|
|
1163
|
+
"""Load a model in one call. Thin wrapper over :func:`pull`.
|
|
1164
|
+
|
|
1165
|
+
If the pulled artifact looks like a pickled :class:`~openrunner.model.Model`
|
|
1166
|
+
(a single ``.pkl`` / ``model.pkl``), it is deserialized via
|
|
1167
|
+
``Model.load``. Otherwise the local directory path is returned.
|
|
1168
|
+
|
|
1169
|
+
Args:
|
|
1170
|
+
name: Artifact name — ``"project/name"`` or bare ``name`` with ``project=``.
|
|
1171
|
+
revision: Version int or alias string.
|
|
1172
|
+
project: Project (``"org/project"``) when ``name`` is bare.
|
|
1173
|
+
|
|
1174
|
+
Returns:
|
|
1175
|
+
A :class:`~openrunner.model.Model` instance if the artifact is a
|
|
1176
|
+
pickled model, else the local directory path (str), or None on failure.
|
|
1177
|
+
|
|
1178
|
+
Example::
|
|
1179
|
+
|
|
1180
|
+
m = openrunner.load_model("gladia/my-project/my-model", revision="production")
|
|
1181
|
+
"""
|
|
1182
|
+
try:
|
|
1183
|
+
from pathlib import Path
|
|
1184
|
+
|
|
1185
|
+
local_path = pull(name, revision=revision, project=project)
|
|
1186
|
+
if local_path is None:
|
|
1187
|
+
return None
|
|
1188
|
+
|
|
1189
|
+
p = Path(local_path)
|
|
1190
|
+
pkl = None
|
|
1191
|
+
if p.is_dir():
|
|
1192
|
+
candidate = p / "model.pkl"
|
|
1193
|
+
if candidate.exists():
|
|
1194
|
+
pkl = candidate
|
|
1195
|
+
else:
|
|
1196
|
+
pkls = list(p.glob("*.pkl"))
|
|
1197
|
+
if len(pkls) == 1:
|
|
1198
|
+
pkl = pkls[0]
|
|
1199
|
+
elif p.suffix == ".pkl":
|
|
1200
|
+
pkl = p
|
|
1201
|
+
|
|
1202
|
+
if pkl is not None:
|
|
1203
|
+
artifact_name, proj = _split_name(name, project)
|
|
1204
|
+
version = revision if isinstance(revision, int) and not isinstance(revision, bool) else None
|
|
1205
|
+
loaded = Model.load(artifact_name, version=version, project=proj)
|
|
1206
|
+
if loaded is not None:
|
|
1207
|
+
return loaded
|
|
1208
|
+
# Fall back to a direct unpickle if Model.load couldn't resolve it.
|
|
1209
|
+
try:
|
|
1210
|
+
import pickle
|
|
1211
|
+
with open(pkl, "rb") as f:
|
|
1212
|
+
return pickle.load(f)
|
|
1213
|
+
except Exception as e: # noqa: BLE001
|
|
1214
|
+
logger.warning("openrunner.load_model(): unpickle failed: %s", e)
|
|
1215
|
+
|
|
1216
|
+
return local_path
|
|
1217
|
+
except Exception as e: # noqa: BLE001
|
|
1218
|
+
logger.warning("openrunner.load_model() failed: %s", e)
|
|
1219
|
+
return None
|
|
1220
|
+
|
|
1221
|
+
|
|
1222
|
+
def list_files(
|
|
1223
|
+
name: str,
|
|
1224
|
+
*,
|
|
1225
|
+
revision: int | str | None = None,
|
|
1226
|
+
project: str | None = None,
|
|
1227
|
+
) -> list[str]:
|
|
1228
|
+
"""Return the file paths in an artifact version. Never raises.
|
|
1229
|
+
|
|
1230
|
+
Args:
|
|
1231
|
+
name: Artifact name — ``"project/name"`` or bare ``name`` with ``project=``.
|
|
1232
|
+
revision: Version int or alias string (default: latest).
|
|
1233
|
+
project: Project (``"org/project"``) when ``name`` is bare.
|
|
1234
|
+
|
|
1235
|
+
Returns:
|
|
1236
|
+
A list of file paths in the version (empty list on failure).
|
|
1237
|
+
|
|
1238
|
+
Example::
|
|
1239
|
+
|
|
1240
|
+
openrunner.list_files("gladia/my-project/my-model", revision="production")
|
|
1241
|
+
"""
|
|
1242
|
+
try:
|
|
1243
|
+
artifact_name, proj = _split_name(name, project)
|
|
1244
|
+
run = _ensure_run(proj)
|
|
1245
|
+
if run is None:
|
|
1246
|
+
logger.warning("openrunner.list_files(): could not resolve/create a run")
|
|
1247
|
+
return []
|
|
1248
|
+
|
|
1249
|
+
version: int | None = None
|
|
1250
|
+
alias: str | None = None
|
|
1251
|
+
if isinstance(revision, bool):
|
|
1252
|
+
revision = None
|
|
1253
|
+
if isinstance(revision, int):
|
|
1254
|
+
version = revision
|
|
1255
|
+
elif isinstance(revision, str):
|
|
1256
|
+
alias = revision
|
|
1257
|
+
|
|
1258
|
+
info = run._client.use_artifact(run.id, artifact_name, version=version, alias=alias)
|
|
1259
|
+
if not info:
|
|
1260
|
+
return []
|
|
1261
|
+
|
|
1262
|
+
# Prefer the version's file listing if a version_id is available.
|
|
1263
|
+
version_id = info.get("version_id")
|
|
1264
|
+
if version_id:
|
|
1265
|
+
files = run._client.list_artifact_files(str(version_id))
|
|
1266
|
+
paths = [
|
|
1267
|
+
f.get("name") or f.get("path")
|
|
1268
|
+
for f in files
|
|
1269
|
+
if (f.get("name") or f.get("path"))
|
|
1270
|
+
]
|
|
1271
|
+
if paths:
|
|
1272
|
+
return [str(p) for p in paths]
|
|
1273
|
+
|
|
1274
|
+
# Fall back to the file names embedded in the use-artifact response.
|
|
1275
|
+
return [
|
|
1276
|
+
str(f.get("name") or f.get("path"))
|
|
1277
|
+
for f in info.get("files", [])
|
|
1278
|
+
if (f.get("name") or f.get("path"))
|
|
1279
|
+
]
|
|
1280
|
+
except Exception as e: # noqa: BLE001
|
|
1281
|
+
logger.warning("openrunner.list_files() failed: %s", e)
|
|
1282
|
+
return []
|
|
1283
|
+
|
|
1284
|
+
|
|
965
1285
|
def should_stop() -> bool:
|
|
966
1286
|
"""Check if the server has requested the active run to stop.
|
|
967
1287
|
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"""Path-containment helper — the server controls artifact/dataset file names, so
|
|
2
|
+
a name like ``../../.ssh/authorized_keys`` or an absolute path must never escape
|
|
3
|
+
the download directory (would be arbitrary file write == RCE on the user's box)."""
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def safe_join(base, rel: str) -> Path:
|
|
8
|
+
"""Return ``base/rel`` resolved, guaranteeing it stays under ``base``.
|
|
9
|
+
Raises ValueError if ``rel`` is absolute or traverses outside ``base``."""
|
|
10
|
+
base_p = Path(base).resolve()
|
|
11
|
+
target = (base_p / str(rel)).resolve()
|
|
12
|
+
if target != base_p and base_p not in target.parents:
|
|
13
|
+
raise ValueError(f"unsafe path escapes destination: {rel!r}")
|
|
14
|
+
return target
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def safe_extractall(tar, path) -> None:
|
|
18
|
+
"""Extract a tarball with zip-slip protection on ALL Python versions
|
|
19
|
+
(``filter='data'`` only exists on 3.12+; a malicious member with ``..`` or an
|
|
20
|
+
absolute path or a link would otherwise write outside ``path``)."""
|
|
21
|
+
import sys
|
|
22
|
+
|
|
23
|
+
if sys.version_info >= (3, 12):
|
|
24
|
+
tar.extractall(path=path, filter="data")
|
|
25
|
+
return
|
|
26
|
+
base = Path(path).resolve()
|
|
27
|
+
for m in tar.getmembers():
|
|
28
|
+
target = (base / m.name).resolve()
|
|
29
|
+
if target != base and base not in target.parents:
|
|
30
|
+
raise ValueError(f"unsafe tar member escapes destination: {m.name!r}")
|
|
31
|
+
if m.issym() or m.islnk():
|
|
32
|
+
raise ValueError(f"refusing tar link member: {m.name!r}")
|
|
33
|
+
tar.extractall(path=path)
|