openrunner-sdk 2.37.34__tar.gz → 2.37.35__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.
Files changed (219) hide show
  1. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/PKG-INFO +5 -1
  2. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/cli.py +31 -4
  3. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/datasets.py +32 -4
  4. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/gpu/__init__.py +54 -0
  5. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/gpu/providers/modal_provider.py +7 -1
  6. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/mcp_server.py +5 -2
  7. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/pyproject.toml +2 -2
  8. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/tests/conftest.py +12 -2
  9. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/tests/integration/conftest.py +7 -1
  10. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/tests/test_aliases.py +4 -0
  11. openrunner_sdk-2.37.35/tests/test_api_client_methods.py +596 -0
  12. openrunner_sdk-2.37.35/tests/test_api_client_transport.py +981 -0
  13. openrunner_sdk-2.37.35/tests/test_cli_artifact_sweep.py +562 -0
  14. openrunner_sdk-2.37.35/tests/test_cli_datasets.py +505 -0
  15. openrunner_sdk-2.37.35/tests/test_cli_gpu_registry_deploy.py +648 -0
  16. openrunner_sdk-2.37.35/tests/test_cli_infra.py +628 -0
  17. openrunner_sdk-2.37.35/tests/test_cli_remainder.py +1525 -0
  18. openrunner_sdk-2.37.35/tests/test_cli_topup.py +989 -0
  19. openrunner_sdk-2.37.35/tests/test_datasets_module.py +1048 -0
  20. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/tests/test_finish.py +14 -15
  21. openrunner_sdk-2.37.35/tests/test_gpu/test_gpu_cluster.py +994 -0
  22. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/tests/test_gpu/test_sdk_gpu_api.py +9 -7
  23. openrunner_sdk-2.37.35/tests/test_gpu_modal_creds.py +183 -0
  24. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/tests/test_init.py +7 -7
  25. openrunner_sdk-2.37.35/tests/test_init_facade.py +908 -0
  26. openrunner_sdk-2.37.35/tests/test_integration_setA.py +895 -0
  27. openrunner_sdk-2.37.35/tests/test_integration_setB.py +1387 -0
  28. openrunner_sdk-2.37.35/tests/test_integration_setC.py +1099 -0
  29. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/tests/test_log.py +16 -9
  30. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/tests/test_log_code.py +13 -13
  31. openrunner_sdk-2.37.35/tests/test_machine_migrate.py +922 -0
  32. openrunner_sdk-2.37.35/tests/test_mcp_server.py +2503 -0
  33. openrunner_sdk-2.37.35/tests/test_media_extra.py +756 -0
  34. openrunner_sdk-2.37.35/tests/test_patent_scan.py +777 -0
  35. openrunner_sdk-2.37.35/tests/test_plot_media_extra2.py +647 -0
  36. openrunner_sdk-2.37.35/tests/test_prompt_module.py +603 -0
  37. openrunner_sdk-2.37.35/tests/test_pure_modules.py +551 -0
  38. openrunner_sdk-2.37.35/tests/test_redact.py +476 -0
  39. openrunner_sdk-2.37.35/tests/test_reload_module.py +795 -0
  40. openrunner_sdk-2.37.35/tests/test_research_module.py +669 -0
  41. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/tests/test_resume.py +6 -6
  42. openrunner_sdk-2.37.35/tests/test_run_module.py +1201 -0
  43. openrunner_sdk-2.37.35/tests/test_sdk_cluster_j1.py +744 -0
  44. openrunner_sdk-2.37.35/tests/test_sdk_cluster_j2.py +863 -0
  45. openrunner_sdk-2.37.35/tests/test_sdk_cluster_j3.py +1086 -0
  46. openrunner_sdk-2.37.35/tests/test_sdk_cluster_j4.py +1569 -0
  47. openrunner_sdk-2.37.35/tests/test_sdk_core_edges.py +200 -0
  48. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/tests/test_sdk_features.py +18 -17
  49. openrunner_sdk-2.37.35/tests/test_session_module.py +848 -0
  50. openrunner_sdk-2.37.35/tests/test_topup_hi.py +733 -0
  51. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/.gitignore +0 -0
  52. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/=6.0 +0 -0
  53. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/=8.1 +0 -0
  54. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/README.md +0 -0
  55. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/CLAUDE.md +0 -0
  56. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/__init__.py +0 -0
  57. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/_safepath.py +0 -0
  58. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/_secret_rules.py +0 -0
  59. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/api_client.py +0 -0
  60. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/artifact.py +0 -0
  61. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/autoresearch.py +0 -0
  62. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/buffer.py +0 -0
  63. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/cache.py +0 -0
  64. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/config.py +0 -0
  65. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/cost.py +0 -0
  66. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/dataset.py +0 -0
  67. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/environment.py +0 -0
  68. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/evaluation.py +0 -0
  69. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/feedback.py +0 -0
  70. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/git_info.py +0 -0
  71. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/gpu/api_integration.py +0 -0
  72. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/gpu/cost_guard.py +0 -0
  73. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/gpu/gpu_types.py +0 -0
  74. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/gpu/price_compare.py +0 -0
  75. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/gpu/provider_base.py +0 -0
  76. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/gpu/providers/__init__.py +0 -0
  77. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/gpu/providers/lambda_cloud.py +0 -0
  78. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/gpu/providers/ovhcloud.py +0 -0
  79. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/gpu/providers/runpod.py +0 -0
  80. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/gpu/providers/vastai.py +0 -0
  81. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/gpu/runner.py +0 -0
  82. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/gpu/workspace_sync.py +0 -0
  83. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/guardrails.py +0 -0
  84. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/handover.py +0 -0
  85. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/hooks/patent-lab-post-commit +0 -0
  86. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/install_commands.py +0 -0
  87. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/integration/__init__.py +0 -0
  88. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/integration/accelerate.py +0 -0
  89. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/integration/anthropic_tracer.py +0 -0
  90. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/integration/catboost.py +0 -0
  91. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/integration/diffusers.py +0 -0
  92. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/integration/fastai.py +0 -0
  93. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/integration/forced_alignment.py +0 -0
  94. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/integration/gladia.py +0 -0
  95. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/integration/gymnasium.py +0 -0
  96. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/integration/huggingface.py +0 -0
  97. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/integration/hydra.py +0 -0
  98. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/integration/ignite.py +0 -0
  99. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/integration/jax.py +0 -0
  100. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/integration/keras.py +0 -0
  101. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/integration/langchain.py +0 -0
  102. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/integration/lightgbm.py +0 -0
  103. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/integration/lightning.py +0 -0
  104. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/integration/llamaindex.py +0 -0
  105. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/integration/openai_finetune.py +0 -0
  106. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/integration/openai_tracer.py +0 -0
  107. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/integration/optuna.py +0 -0
  108. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/integration/pytorch.py +0 -0
  109. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/integration/sb3.py +0 -0
  110. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/integration/sklearn.py +0 -0
  111. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/integration/skypilot.py +0 -0
  112. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/integration/tensorflow.py +0 -0
  113. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/integration/trl.py +0 -0
  114. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/integration/tts.py +0 -0
  115. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/integration/ultralytics.py +0 -0
  116. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/integration/voice_agent.py +0 -0
  117. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/integration/whisper.py +0 -0
  118. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/integration/xgboost.py +0 -0
  119. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/launch.py +0 -0
  120. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/machine.py +0 -0
  121. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/media.py +0 -0
  122. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/migrate.py +0 -0
  123. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/model.py +0 -0
  124. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/model_card.py +0 -0
  125. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/offline.py +0 -0
  126. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/patent_scan.py +0 -0
  127. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/pii.py +0 -0
  128. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/plot.py +0 -0
  129. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/projects.py +0 -0
  130. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/prompt.py +0 -0
  131. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/query_api.py +0 -0
  132. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/redact.py +0 -0
  133. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/reload.py +0 -0
  134. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/research.py +0 -0
  135. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/research_policy.py +0 -0
  136. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/run.py +0 -0
  137. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/scorers.py +0 -0
  138. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/sender.py +0 -0
  139. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/session.py +0 -0
  140. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/settings.py +0 -0
  141. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/summary.py +0 -0
  142. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/sweep.py +0 -0
  143. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/sync.py +0 -0
  144. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/system_metrics.py +0 -0
  145. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/tensorboard.py +0 -0
  146. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/tools/__init__.py +0 -0
  147. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/tools/patent_report.py +0 -0
  148. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/trace.py +0 -0
  149. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/transcript_formatter.py +0 -0
  150. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/wal.py +0 -0
  151. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/wandb_compat/__init__.py +0 -0
  152. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/wandb_compat/_shim.py +0 -0
  153. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/openrunner/wer.py +0 -0
  154. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/scripts/gen_betterleaks_rules.py +0 -0
  155. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/tests/__init__.py +0 -0
  156. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/tests/fixtures/wandb-export-mini/run-aaa/config.json +0 -0
  157. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/tests/fixtures/wandb-export-mini/run-aaa/metadata.json +0 -0
  158. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/tests/fixtures/wandb-export-mini/run-aaa/metrics.jsonl +0 -0
  159. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/tests/fixtures/wandb-export-mini/run-aaa/summary.json +0 -0
  160. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/tests/fixtures/wandb-export-mini/run-bbb/artifacts/model-checkpoint/manifest.json +0 -0
  161. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/tests/fixtures/wandb-export-mini/run-bbb/artifacts/model-checkpoint/weights.bin +0 -0
  162. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/tests/fixtures/wandb-export-mini/run-bbb/artifacts/sample-image/manifest.json +0 -0
  163. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/tests/fixtures/wandb-export-mini/run-bbb/artifacts/sample-image/preview.png +0 -0
  164. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/tests/fixtures/wandb-export-mini/run-bbb/config.json +0 -0
  165. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/tests/fixtures/wandb-export-mini/run-bbb/metadata.json +0 -0
  166. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/tests/fixtures/wandb-export-mini/run-bbb/metrics.jsonl +0 -0
  167. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/tests/fixtures/wandb-export-mini/run-bbb/summary.json +0 -0
  168. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/tests/integration/__init__.py +0 -0
  169. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/tests/integration/test_artifact_round_trip.py +0 -0
  170. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/tests/test_alert.py +0 -0
  171. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/tests/test_api_client.py +0 -0
  172. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/tests/test_artifact.py +0 -0
  173. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/tests/test_buffer.py +0 -0
  174. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/tests/test_cache.py +0 -0
  175. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/tests/test_class_scorers.py +0 -0
  176. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/tests/test_cli.py +0 -0
  177. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/tests/test_config.py +0 -0
  178. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/tests/test_evaluation.py +0 -0
  179. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/tests/test_git_info.py +0 -0
  180. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/tests/test_gpu/__init__.py +0 -0
  181. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/tests/test_gpu/conftest.py +0 -0
  182. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/tests/test_gpu/test_cost_guard.py +0 -0
  183. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/tests/test_gpu/test_gpu_types.py +0 -0
  184. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/tests/test_gpu/test_lambda.py +0 -0
  185. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/tests/test_gpu/test_modal.py +0 -0
  186. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/tests/test_gpu/test_ovhcloud.py +0 -0
  187. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/tests/test_gpu/test_price_compare.py +0 -0
  188. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/tests/test_gpu/test_provider_base.py +0 -0
  189. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/tests/test_gpu/test_runner.py +0 -0
  190. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/tests/test_gpu/test_runpod.py +0 -0
  191. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/tests/test_gpu/test_vastai.py +0 -0
  192. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/tests/test_gpu/test_workspace_sync.py +0 -0
  193. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/tests/test_install_commands.py +0 -0
  194. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/tests/test_integration_fastai.py +0 -0
  195. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/tests/test_integration_huggingface.py +0 -0
  196. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/tests/test_integration_keras.py +0 -0
  197. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/tests/test_integration_langchain.py +0 -0
  198. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/tests/test_integration_lightning.py +0 -0
  199. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/tests/test_integration_pytorch.py +0 -0
  200. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/tests/test_integration_sklearn.py +0 -0
  201. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/tests/test_integration_xgboost.py +0 -0
  202. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/tests/test_launch.py +0 -0
  203. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/tests/test_mcp_decisions.py +0 -0
  204. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/tests/test_mcp_monitor.py +0 -0
  205. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/tests/test_mcp_predictions.py +0 -0
  206. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/tests/test_media.py +0 -0
  207. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/tests/test_migrate.py +0 -0
  208. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/tests/test_offline.py +0 -0
  209. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/tests/test_offline_sync.py +0 -0
  210. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/tests/test_pii.py +0 -0
  211. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/tests/test_plot.py +0 -0
  212. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/tests/test_query_api.py +0 -0
  213. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/tests/test_sender.py +0 -0
  214. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/tests/test_session_sync.py +0 -0
  215. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/tests/test_summary.py +0 -0
  216. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/tests/test_sweep.py +0 -0
  217. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/tests/test_system_metrics.py +0 -0
  218. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/tests/test_trace.py +0 -0
  219. {openrunner_sdk-2.37.34 → openrunner_sdk-2.37.35}/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.34
3
+ Version: 2.37.35
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
@@ -32,10 +32,14 @@ Requires-Dist: anthropic<1.0,>=0.20; extra == 'anthropic'
32
32
  Provides-Extra: catboost
33
33
  Requires-Dist: catboost<2.0,>=1.2; extra == 'catboost'
34
34
  Provides-Extra: dev
35
+ Requires-Dist: matplotlib<5.0,>=3.7; extra == 'dev'
36
+ Requires-Dist: num2words2<2.0,>=0.1; extra == 'dev'
35
37
  Requires-Dist: numpy<3.0,>=1.24; extra == 'dev'
38
+ Requires-Dist: pillow<13.0,>=10.0; extra == 'dev'
36
39
  Requires-Dist: pytest-asyncio<1.0,>=0.23; extra == 'dev'
37
40
  Requires-Dist: pytest-cov<6.0,>=5.0; extra == 'dev'
38
41
  Requires-Dist: pytest<9.0,>=8.0; extra == 'dev'
42
+ Requires-Dist: scikit-learn<2.0,>=1.3; extra == 'dev'
39
43
  Provides-Extra: diffusers
40
44
  Requires-Dist: diffusers<1.0,>=0.25; extra == 'diffusers'
41
45
  Provides-Extra: fastai
@@ -4110,10 +4110,37 @@ def gpu_credentials() -> None:
4110
4110
 
4111
4111
  @gpu_credentials.command("add")
4112
4112
  @click.option("--org", "org_id", required=True, help="Organization ID (UUID)")
4113
- @click.option("--provider", required=True, help="Provider, e.g. runpod, vastai, ovhcloud, lambda")
4114
- @click.option("--api-key", "provider_key", required=True, help="Provider API key. For ovhcloud pass a JSON blob: '{\"application_key\":..,\"application_secret\":..,\"consumer_key\":..,\"service_name\":..,\"endpoint\":\"ovh-eu\",\"region\":\"GRA11\"}'")
4115
- def gpu_credentials_add(org_id: str, provider: str, provider_key: str) -> None:
4116
- """Store a provider API key on the platform (Fernet-encrypted, never returned)."""
4113
+ @click.option("--provider", required=True, help="Provider, e.g. runpod, vastai, ovhcloud, lambda, modal")
4114
+ @click.option("--api-key", "provider_key", default=None, help="Provider API key. For ovhcloud/lambda pass a JSON blob. For modal use --token-id/--token-secret instead.")
4115
+ @click.option("--token-id", default=None, help="Modal token id (from `modal token new`). Use with --token-secret.")
4116
+ @click.option("--token-secret", default=None, help="Modal token secret. Use with --token-id.")
4117
+ @click.option("--profile", default=None, help="Modal profile / workspace (org), e.g. gladia. Optional.")
4118
+ def gpu_credentials_add(org_id: str, provider: str, provider_key: str | None,
4119
+ token_id: str | None, token_secret: str | None,
4120
+ profile: str | None) -> None:
4121
+ """Store a provider credential on the platform (Fernet-encrypted, never returned).
4122
+
4123
+ Modal authenticates with a token PAIR, not a single key, plus an optional
4124
+ profile (workspace/org):
4125
+
4126
+ openrunner gpu credentials add --org ORG --provider modal \\
4127
+ --token-id ak-xxxx --token-secret as-xxxx --profile gladia
4128
+ """
4129
+ import json as _json
4130
+
4131
+ # Modal: pack the token pair (+ optional profile) into the JSON blob.
4132
+ if token_id or token_secret:
4133
+ if not (token_id and token_secret):
4134
+ click.echo("Error: modal needs BOTH --token-id and --token-secret.", err=True)
4135
+ raise SystemExit(1)
4136
+ blob = {"token_id": token_id, "token_secret": token_secret}
4137
+ if profile:
4138
+ blob["profile"] = profile
4139
+ provider_key = _json.dumps(blob)
4140
+ if not provider_key:
4141
+ click.echo("Error: pass --api-key (or --token-id/--token-secret for modal).", err=True)
4142
+ raise SystemExit(1)
4143
+
4117
4144
  from openrunner.gpu.api_integration import GpuAPIClient
4118
4145
 
4119
4146
  settings = _load_settings()
@@ -330,8 +330,17 @@ class DatasetsClient:
330
330
  try:
331
331
  pr = self._http.post(f"/datasets/{ds_id}/files/presign", json=body)
332
332
  _check(pr)
333
- url = pr.json()["url"]
334
- put = httpx.put(url, content=data, timeout=300.0)
333
+ pj = pr.json()
334
+ url = pj["url"]
335
+ # If the presign signed a storage class (SignedHeaders include
336
+ # x-amz-storage-class), the PUT MUST echo that exact header value
337
+ # or S3 returns SignatureDoesNotMatch (403). OVH maps non-json
338
+ # content types to EXPRESS_ONEZONE, so a plain PUT fails for .jsonl.
339
+ put_headers = {}
340
+ sc = pj.get("storage_class")
341
+ if sc:
342
+ put_headers["x-amz-storage-class"] = sc
343
+ put = httpx.put(url, content=data, headers=put_headers, timeout=300.0)
335
344
  put.raise_for_status()
336
345
  return {"path": rel, "size_bytes": len(data), "sha256": sha, "content_type": ctype}
337
346
  except Exception as e: # noqa: BLE001
@@ -765,9 +774,28 @@ class DatasetsClient:
765
774
  return DatasetInfo._from_json(r.json())
766
775
 
767
776
  def add_derivation(self, repo_id: str, parent_repo_id: str) -> DatasetInfo:
777
+ """Record that ``repo_id`` is derived from ``parent_repo_id``.
778
+
779
+ The parent may be another OpenRunner dataset (``org/name``) OR an external
780
+ HuggingFace dataset. Prefix the ref with ``hf://`` (or pass a HF repo that
781
+ isn't an internal dataset) to record external Hub provenance, e.g.::
782
+
783
+ add_derivation("gladia/common-voice-16-1", "hf://fsicoli/common_voice_16_1")
784
+ add_derivation("gladia/common-voice-16-1", "fsicoli/common_voice_16_1")
785
+ """
768
786
  ds = self._resolve(repo_id)
769
- parent = self._resolve(parent_repo_id)
770
- r = self._http.post(f"/datasets/{ds.id}/derived-from", json={"parent_dataset_id": parent.id})
787
+ explicit_hf = parent_repo_id.startswith(("hf://", "hf:"))
788
+ if not explicit_hf:
789
+ try:
790
+ parent = self._resolve(parent_repo_id)
791
+ r = self._http.post(f"/datasets/{ds.id}/derived-from",
792
+ json={"parent_dataset_id": str(parent.id)})
793
+ _check(r)
794
+ return DatasetInfo._from_json(r.json())
795
+ except Exception:
796
+ pass # not an internal dataset -> treat as external HF ref
797
+ r = self._http.post(f"/datasets/{ds.id}/derived-from",
798
+ json={"parent_hf_repo": parent_repo_id})
771
799
  _check(r)
772
800
  return DatasetInfo._from_json(r.json())
773
801
 
@@ -142,6 +142,20 @@ def _get_provider_instance(
142
142
  Raises:
143
143
  ValueError: If provider is unknown or no API key found.
144
144
  """
145
+ # Modal authenticates with a token PAIR (token_id + token_secret), not a
146
+ # single key. Resolve both and pass them through to ModalProvider.
147
+ if provider == "modal":
148
+ token_id, token_secret, profile = _resolve_modal_tokens(api_key)
149
+ if not (token_id and token_secret):
150
+ raise ValueError(
151
+ "No Modal credentials found. Set MODAL_TOKEN_ID + MODAL_TOKEN_SECRET "
152
+ "(from `modal token new`), pass api_key='{\"token_id\":..,\"token_secret\":..}', "
153
+ "or store them on the platform: "
154
+ "`openrunner gpu credentials add --provider modal --token-id .. --token-secret ..`."
155
+ )
156
+ cls = get_provider("modal")
157
+ return cls(api_key=token_id, api_secret=token_secret, profile=profile)
158
+
145
159
  resolved_key = _resolve_api_key(provider, api_key, api_client)
146
160
  if not resolved_key:
147
161
  raise ValueError(
@@ -154,6 +168,46 @@ def _get_provider_instance(
154
168
  return cls(api_key=resolved_key)
155
169
 
156
170
 
171
+ def _resolve_modal_tokens(
172
+ api_key: str | None,
173
+ ) -> tuple[str | None, str | None, str | None]:
174
+ """Resolve Modal's (token_id, token_secret, profile) triple.
175
+
176
+ ``profile`` is Modal's workspace/organization (e.g. ``gladia``) and is
177
+ OPTIONAL. Priority: explicit ``api_key`` (a JSON blob
178
+ ``{"token_id","token_secret","profile"?}``) > MODAL_TOKEN_ID +
179
+ MODAL_TOKEN_SECRET (+ MODAL_PROFILE) env > a JSON blob in MODAL_API_KEY.
180
+ Returns (None, None, None) if the tokens aren't resolvable.
181
+ """
182
+ import json as _json
183
+
184
+ def _from_blob(raw: str) -> tuple[str | None, str | None, str | None]:
185
+ try:
186
+ c = _json.loads(raw)
187
+ except Exception:
188
+ return None, None, None
189
+ if not isinstance(c, dict):
190
+ return None, None, None
191
+ return (
192
+ c.get("token_id") or c.get("MODAL_TOKEN_ID"),
193
+ c.get("token_secret") or c.get("MODAL_TOKEN_SECRET"),
194
+ c.get("profile") or c.get("MODAL_PROFILE"),
195
+ )
196
+
197
+ if api_key:
198
+ tid, tsec, prof = _from_blob(api_key)
199
+ if tid and tsec:
200
+ return tid, tsec, prof
201
+ tid = os.environ.get("MODAL_TOKEN_ID")
202
+ tsec = os.environ.get("MODAL_TOKEN_SECRET")
203
+ if tid and tsec:
204
+ return tid, tsec, os.environ.get("MODAL_PROFILE")
205
+ blob = os.environ.get("MODAL_API_KEY")
206
+ if blob:
207
+ return _from_blob(blob)
208
+ return None, None, None
209
+
210
+
157
211
  def _cost_guard_loop(
158
212
  provider: GpuProvider,
159
213
  instance: GpuInstance,
@@ -86,7 +86,7 @@ class ModalProvider(GpuProvider):
86
86
  it runs Python functions on-demand on GPU containers.
87
87
  """
88
88
 
89
- def __init__(self, api_key: str, api_secret: str = "") -> None:
89
+ def __init__(self, api_key: str, api_secret: str = "", profile: str | None = None) -> None:
90
90
  if not HAS_MODAL:
91
91
  raise ProviderError(
92
92
  provider="modal",
@@ -97,6 +97,12 @@ class ModalProvider(GpuProvider):
97
97
  )
98
98
  self._api_key = api_key
99
99
  self._api_secret = api_secret
100
+ # Modal's workspace/organization (e.g. "gladia"); optional. Surfaced to
101
+ # the Modal client via the MODAL_PROFILE env var so deploys target it.
102
+ self._profile = profile or None
103
+ if self._profile:
104
+ import os
105
+ os.environ.setdefault("MODAL_PROFILE", self._profile)
100
106
  # Track deployed apps in memory (Modal doesn't have a list-instances API)
101
107
  self._apps: dict[str, dict[str, Any]] = {}
102
108
 
@@ -3232,7 +3232,10 @@ async def _tool_upload_artifact(args: dict) -> str:
3232
3232
  # 3. Create a lightweight run for the upload
3233
3233
  ts = datetime.now().strftime("%Y%m%d-%H%M%S")
3234
3234
  run_data = await _api_post("/runs", data={
3235
- "project": project,
3235
+ # project_id already resolved above — pass it directly so run creation
3236
+ # never re-resolves the "org/project" string (which needs a separate org
3237
+ # field server-side and 400s without it).
3238
+ "project_id": project_id,
3236
3239
  "display_name": f"artifact-upload-{art_name}-{ts}",
3237
3240
  "tags": ["artifact-upload"] + ([art_type] if art_type else []),
3238
3241
  "config": {"artifact_name": art_name, "artifact_type": art_type, "file_count": len(file_entries)},
@@ -3276,7 +3279,7 @@ async def _tool_upload_artifact(args: dict) -> str:
3276
3279
  # 5. Upload files to presigned URLs
3277
3280
  uploaded = 0
3278
3281
  skipped = 0
3279
- url_map = {u["name"]: u["url"] for u in upload_urls}
3282
+ url_map = {u["name"]: (u.get("url") or u.get("presigned_url")) for u in upload_urls}
3280
3283
 
3281
3284
  async with httpx.AsyncClient(timeout=300.0) as client:
3282
3285
  for entry in file_entries:
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "openrunner-sdk"
3
- version = "2.37.34"
3
+ version = "2.37.35"
4
4
  description = "OpenRunner SDK - W&B-compatible ML experiment tracking client"
5
5
  readme = "README.md"
6
6
  license = {text = "MIT"}
@@ -65,7 +65,7 @@ voice-agent = []
65
65
  forced-alignment = ["matplotlib>=3.7,<4.0", "numpy>=1.24,<3.0"]
66
66
  mcp = ["mcp>=1.0,<2.0"]
67
67
  patent = ["httpx>=0.27,<1.0"]
68
- dev = ["pytest>=8.0,<9.0", "pytest-asyncio>=0.23,<1.0", "pytest-cov>=5.0,<6.0", "numpy>=1.24,<3.0"]
68
+ dev = ["pytest>=8.0,<9.0", "pytest-asyncio>=0.23,<1.0", "pytest-cov>=5.0,<6.0", "numpy>=1.24,<3.0", "Pillow>=10.0,<13.0", "scikit-learn>=1.3,<2.0", "matplotlib>=3.7,<5.0", "num2words2>=0.1,<2.0"]
69
69
 
70
70
  [tool.hatch.build.targets.wheel]
71
71
  packages = ["openrunner"]
@@ -13,11 +13,21 @@ import pytest
13
13
 
14
14
 
15
15
  @pytest.fixture
16
- def clean_env(monkeypatch: pytest.MonkeyPatch) -> pytest.MonkeyPatch:
17
- """Clear all OPENRUNNER_*, OPENRUN_*, and WANDB_* env vars for a clean test environment."""
16
+ def clean_env(monkeypatch: pytest.MonkeyPatch, tmp_path: Path) -> pytest.MonkeyPatch:
17
+ """Clear all OPENRUNNER_*, OPENRUN_*, and WANDB_* env vars for a clean test environment.
18
+
19
+ Also redirects HOME (and USERPROFILE) to a throwaway dir so tests never pick up
20
+ the developer's real ``~/.openrunner/session_config.json`` creds -- otherwise a
21
+ machine that has run ``openrunner login`` fails "no api key" / default-URL tests
22
+ that pass on a clean CI box.
23
+ """
18
24
  for var in list(os.environ):
19
25
  if var.startswith(("OPENRUNNER_", "OPENRUN_", "WANDB_")):
20
26
  monkeypatch.delenv(var, raising=False)
27
+ fake_home = tmp_path / "home"
28
+ fake_home.mkdir(exist_ok=True)
29
+ monkeypatch.setenv("HOME", str(fake_home))
30
+ monkeypatch.setenv("USERPROFILE", str(fake_home))
21
31
  return monkeypatch
22
32
 
23
33
 
@@ -23,5 +23,11 @@ def pytest_collection_modifyitems(config: pytest.Config, items: list[pytest.Item
23
23
  skip = pytest.mark.skip(
24
24
  reason=f"live integration: set {', '.join(missing)} to enable"
25
25
  )
26
+ # NOTE: a subdirectory conftest's modifyitems hook receives the WHOLE session's
27
+ # items, not just this directory's. Only skip the live integration tests that
28
+ # actually live under tests/integration/ -- otherwise the entire unit suite is
29
+ # skipped whenever these env vars are unset.
30
+ integration_dir = os.path.dirname(__file__)
26
31
  for item in items:
27
- item.add_marker(skip)
32
+ if str(item.fspath).startswith(integration_dir):
33
+ item.add_marker(skip)
@@ -187,6 +187,8 @@ def test_run_link_artifact_sets_aliases():
187
187
  run._job_type = None
188
188
  run._step = 0
189
189
  run._state = "running"
190
+ run._artifacts_logged = 0
191
+ run._artifacts_used = 0
190
192
 
191
193
  from openrunner.api_client import APIClient
192
194
  from openrunner.buffer import WriteBuffer
@@ -236,6 +238,8 @@ def test_run_use_artifact_colon_syntax():
236
238
  run._name = "test-run"
237
239
  run._step = 0
238
240
  run._state = "running"
241
+ run._artifacts_logged = 0
242
+ run._artifacts_used = 0
239
243
  run._client = APIClient("http://test", "test-key", transport=transport)
240
244
  run._buffer = WriteBuffer()
241
245
  run._summary = Summary()