openrunner-sdk 2.41.4__tar.gz → 2.41.6__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 (227) hide show
  1. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/PKG-INFO +1 -1
  2. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/CLAUDE.md +27 -0
  3. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/__init__.py +7 -0
  4. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/_native.py +4 -2
  5. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/datasets.py +213 -3
  6. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/install_commands.py +42 -2
  7. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/pyproject.toml +1 -1
  8. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_datasets_module.py +179 -0
  9. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/.gitignore +0 -0
  10. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/=6.0 +0 -0
  11. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/=8.1 +0 -0
  12. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/README.md +0 -0
  13. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/_retry_transport.py +0 -0
  14. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/_safepath.py +0 -0
  15. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/_secret_rules.py +0 -0
  16. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/api_client.py +0 -0
  17. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/artifact.py +0 -0
  18. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/autoresearch.py +0 -0
  19. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/buffer.py +0 -0
  20. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/cache.py +0 -0
  21. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/cli.py +0 -0
  22. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/config.py +0 -0
  23. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/cost.py +0 -0
  24. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/dataset.py +0 -0
  25. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/environment.py +0 -0
  26. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/evaluation.py +0 -0
  27. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/feedback.py +0 -0
  28. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/git_info.py +0 -0
  29. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/gpu/__init__.py +0 -0
  30. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/gpu/api_integration.py +0 -0
  31. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/gpu/cost_guard.py +0 -0
  32. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/gpu/gpu_types.py +0 -0
  33. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/gpu/price_compare.py +0 -0
  34. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/gpu/provider_base.py +0 -0
  35. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/gpu/providers/__init__.py +0 -0
  36. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/gpu/providers/forge_provider.py +0 -0
  37. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/gpu/providers/lambda_cloud.py +0 -0
  38. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/gpu/providers/modal_provider.py +0 -0
  39. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/gpu/providers/ovhcloud.py +0 -0
  40. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/gpu/providers/runpod.py +0 -0
  41. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/gpu/providers/vastai.py +0 -0
  42. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/gpu/runner.py +0 -0
  43. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/gpu/workspace_sync.py +0 -0
  44. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/guardrails.py +0 -0
  45. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/handover.py +0 -0
  46. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/hooks/patent-lab-post-commit +0 -0
  47. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/integration/__init__.py +0 -0
  48. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/integration/accelerate.py +0 -0
  49. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/integration/anthropic_tracer.py +0 -0
  50. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/integration/catboost.py +0 -0
  51. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/integration/diffusers.py +0 -0
  52. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/integration/fastai.py +0 -0
  53. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/integration/forced_alignment.py +0 -0
  54. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/integration/gladia.py +0 -0
  55. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/integration/gymnasium.py +0 -0
  56. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/integration/huggingface.py +0 -0
  57. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/integration/hydra.py +0 -0
  58. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/integration/ignite.py +0 -0
  59. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/integration/jax.py +0 -0
  60. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/integration/keras.py +0 -0
  61. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/integration/langchain.py +0 -0
  62. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/integration/lightgbm.py +0 -0
  63. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/integration/lightning.py +0 -0
  64. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/integration/llamaindex.py +0 -0
  65. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/integration/openai_finetune.py +0 -0
  66. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/integration/openai_tracer.py +0 -0
  67. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/integration/optuna.py +0 -0
  68. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/integration/pytorch.py +0 -0
  69. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/integration/sb3.py +0 -0
  70. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/integration/sklearn.py +0 -0
  71. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/integration/skypilot.py +0 -0
  72. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/integration/tensorflow.py +0 -0
  73. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/integration/trl.py +0 -0
  74. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/integration/tts.py +0 -0
  75. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/integration/ultralytics.py +0 -0
  76. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/integration/voice_agent.py +0 -0
  77. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/integration/whisper.py +0 -0
  78. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/integration/xgboost.py +0 -0
  79. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/launch.py +0 -0
  80. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/machine.py +0 -0
  81. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/mcp_server.py +0 -0
  82. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/media.py +0 -0
  83. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/migrate.py +0 -0
  84. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/model.py +0 -0
  85. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/model_card.py +0 -0
  86. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/offline.py +0 -0
  87. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/patent_scan.py +0 -0
  88. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/pii.py +0 -0
  89. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/plot.py +0 -0
  90. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/projects.py +0 -0
  91. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/prompt.py +0 -0
  92. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/query_api.py +0 -0
  93. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/redact.py +0 -0
  94. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/reload.py +0 -0
  95. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/research.py +0 -0
  96. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/research_policy.py +0 -0
  97. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/run.py +0 -0
  98. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/scorers.py +0 -0
  99. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/sender.py +0 -0
  100. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/session.py +0 -0
  101. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/settings.py +0 -0
  102. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/summary.py +0 -0
  103. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/sweep.py +0 -0
  104. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/sync.py +0 -0
  105. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/system_metrics.py +0 -0
  106. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/tensorboard.py +0 -0
  107. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/tools/__init__.py +0 -0
  108. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/tools/patent_report.py +0 -0
  109. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/trace.py +0 -0
  110. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/transcript_formatter.py +0 -0
  111. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/wal.py +0 -0
  112. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/wandb_compat/__init__.py +0 -0
  113. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/wandb_compat/_shim.py +0 -0
  114. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/openrunner/wer.py +0 -0
  115. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/scripts/gen_betterleaks_rules.py +0 -0
  116. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/__init__.py +0 -0
  117. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/conftest.py +0 -0
  118. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/fixtures/wandb-export-mini/run-aaa/config.json +0 -0
  119. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/fixtures/wandb-export-mini/run-aaa/metadata.json +0 -0
  120. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/fixtures/wandb-export-mini/run-aaa/metrics.jsonl +0 -0
  121. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/fixtures/wandb-export-mini/run-aaa/summary.json +0 -0
  122. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/fixtures/wandb-export-mini/run-bbb/artifacts/model-checkpoint/manifest.json +0 -0
  123. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/fixtures/wandb-export-mini/run-bbb/artifacts/model-checkpoint/weights.bin +0 -0
  124. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/fixtures/wandb-export-mini/run-bbb/artifacts/sample-image/manifest.json +0 -0
  125. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/fixtures/wandb-export-mini/run-bbb/artifacts/sample-image/preview.png +0 -0
  126. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/fixtures/wandb-export-mini/run-bbb/config.json +0 -0
  127. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/fixtures/wandb-export-mini/run-bbb/metadata.json +0 -0
  128. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/fixtures/wandb-export-mini/run-bbb/metrics.jsonl +0 -0
  129. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/fixtures/wandb-export-mini/run-bbb/summary.json +0 -0
  130. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/integration/__init__.py +0 -0
  131. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/integration/conftest.py +0 -0
  132. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/integration/test_artifact_round_trip.py +0 -0
  133. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_alert.py +0 -0
  134. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_aliases.py +0 -0
  135. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_api_client.py +0 -0
  136. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_api_client_methods.py +0 -0
  137. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_api_client_transport.py +0 -0
  138. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_artifact.py +0 -0
  139. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_buffer.py +0 -0
  140. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_cache.py +0 -0
  141. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_class_scorers.py +0 -0
  142. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_cli.py +0 -0
  143. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_cli_artifact_sweep.py +0 -0
  144. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_cli_datasets.py +0 -0
  145. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_cli_gpu_registry_deploy.py +0 -0
  146. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_cli_infra.py +0 -0
  147. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_cli_remainder.py +0 -0
  148. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_cli_topup.py +0 -0
  149. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_config.py +0 -0
  150. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_evaluation.py +0 -0
  151. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_finish.py +0 -0
  152. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_git_info.py +0 -0
  153. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_gpu/__init__.py +0 -0
  154. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_gpu/conftest.py +0 -0
  155. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_gpu/test_cost_guard.py +0 -0
  156. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_gpu/test_engine_serverside.py +0 -0
  157. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_gpu/test_forge.py +0 -0
  158. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_gpu/test_governed_jobs.py +0 -0
  159. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_gpu/test_gpu_cluster.py +0 -0
  160. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_gpu/test_gpu_types.py +0 -0
  161. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_gpu/test_lambda.py +0 -0
  162. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_gpu/test_modal.py +0 -0
  163. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_gpu/test_ovh_training.py +0 -0
  164. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_gpu/test_ovhcloud.py +0 -0
  165. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_gpu/test_price_compare.py +0 -0
  166. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_gpu/test_provider_base.py +0 -0
  167. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_gpu/test_runner.py +0 -0
  168. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_gpu/test_runpod.py +0 -0
  169. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_gpu/test_sdk_gpu_api.py +0 -0
  170. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_gpu/test_vastai.py +0 -0
  171. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_gpu/test_workspace_sync.py +0 -0
  172. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_gpu_modal_creds.py +0 -0
  173. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_init.py +0 -0
  174. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_init_facade.py +0 -0
  175. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_install_commands.py +0 -0
  176. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_integration_fastai.py +0 -0
  177. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_integration_huggingface.py +0 -0
  178. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_integration_keras.py +0 -0
  179. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_integration_langchain.py +0 -0
  180. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_integration_lightning.py +0 -0
  181. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_integration_pytorch.py +0 -0
  182. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_integration_setA.py +0 -0
  183. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_integration_setB.py +0 -0
  184. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_integration_setC.py +0 -0
  185. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_integration_sklearn.py +0 -0
  186. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_integration_xgboost.py +0 -0
  187. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_launch.py +0 -0
  188. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_log.py +0 -0
  189. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_log_code.py +0 -0
  190. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_machine_migrate.py +0 -0
  191. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_mcp_decisions.py +0 -0
  192. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_mcp_monitor.py +0 -0
  193. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_mcp_predictions.py +0 -0
  194. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_mcp_server.py +0 -0
  195. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_media.py +0 -0
  196. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_media_extra.py +0 -0
  197. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_migrate.py +0 -0
  198. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_offline.py +0 -0
  199. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_offline_sync.py +0 -0
  200. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_patent_scan.py +0 -0
  201. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_pii.py +0 -0
  202. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_plot.py +0 -0
  203. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_plot_media_extra2.py +0 -0
  204. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_prompt_module.py +0 -0
  205. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_pure_modules.py +0 -0
  206. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_query_api.py +0 -0
  207. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_redact.py +0 -0
  208. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_reload_module.py +0 -0
  209. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_research_module.py +0 -0
  210. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_resume.py +0 -0
  211. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_retry_transport.py +0 -0
  212. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_run_module.py +0 -0
  213. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_sdk_cluster_j1.py +0 -0
  214. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_sdk_cluster_j2.py +0 -0
  215. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_sdk_cluster_j3.py +0 -0
  216. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_sdk_cluster_j4.py +0 -0
  217. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_sdk_core_edges.py +0 -0
  218. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_sdk_features.py +0 -0
  219. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_sender.py +0 -0
  220. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_session_module.py +0 -0
  221. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_session_sync.py +0 -0
  222. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_summary.py +0 -0
  223. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_sweep.py +0 -0
  224. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_system_metrics.py +0 -0
  225. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_topup_hi.py +0 -0
  226. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/tests/test_trace.py +0 -0
  227. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.6}/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.41.4
3
+ Version: 2.41.6
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
@@ -84,6 +84,33 @@ CLI: `openrunner datasets index org/name --text-col en --text-col fr`,
84
84
  combined `_text` column so one query spans all text fields; preview/search read
85
85
  the LanceDB table on the dataset's own connection.
86
86
 
87
+ ### Search modes + query-derived datasets
88
+
89
+ Beyond FTS, the client exposes semantic / lexical search and **derivation by
90
+ query** — build a child dataset from a SUBSET of a parent selected by a search
91
+ (only matching primary keys stored; no media copied; de-dup + lineage automatic).
92
+ These delegate to the native Rust core (`openrunner-core` wheel) when installed,
93
+ falling back to pure-Python httpx otherwise:
94
+
95
+ ```python
96
+ ord.search_dataset(repo, q, mode="mixed"|"exact", lang="fr") # BM25 / phrase, lang filter
97
+ ord.optimize_embedding_search(repo) # build ANN index (once)
98
+ ord.semantic_search(repo, q, lang="en,fr") # vector (cosine) search
99
+ ord.regex_search(repo, r"\bcancel(led)?\b", lang="en") # Python-re over the text column (bounded)
100
+ ord.word_lookup(repo, "medical,doctor", op="union"|"intersect", lang="fr") # lexical_map
101
+ ord.keyword_expand("medical terms in french", count=300) # LLM -> {keywords, csv, count}
102
+
103
+ # derive: mode = word (op union/intersect) | fts | exact | regex | semantic; lang filter; append via target_repo_id
104
+ child = ord.derive_by_query(parent, keywords_csv, name="org/medical-fr",
105
+ mode="word", lang="fr", limit=5000)
106
+ ord.derive_by_query(parent, "more,terms", target_repo_id="org/medical-fr", mode="word") # append, de-dup
107
+ ord.derived_rows("org/medical-fr", limit=50) # member keys + inherited parent fields
108
+ ```
109
+
110
+ `word`+`op="union"` = rows matching ANY term; `op="intersect"` (via `word_lookup`)
111
+ = rows matching ALL. `semantic` needs `optimize_embedding_search` first. Slash
112
+ command: `/openrunner:derive-dataset` (query-derivation **or** computed-column).
113
+
87
114
  # OpenRunner MCP Integration
88
115
 
89
116
  When the user publishes a MODEL, or asks to write/update a model card:
@@ -101,8 +101,15 @@ from openrunner.datasets import (
101
101
  link_project,
102
102
  load_dataset,
103
103
  add_derivation,
104
+ derive_by_query,
105
+ derived_rows,
106
+ keyword_expand,
107
+ optimize_embedding_search,
104
108
  push_dataset,
105
109
  search_dataset,
110
+ regex_search,
111
+ semantic_search,
112
+ word_lookup,
106
113
  set_dataset_card,
107
114
  set_storage_policy,
108
115
  upload_file,
@@ -9,8 +9,10 @@ single-implementation point, never a hard dependency.
9
9
 
10
10
  Covered surface today: projects (incl. linked repo), artifacts/versions,
11
11
  presigned downloads (selective, GIL released during transfers), container
12
- registries + broker login tokens, and dataset editable-overlay columns
13
- (add column / set cell / edit row / get row — source columns stay read-only).
12
+ registries + broker login tokens, dataset editable-overlay columns
13
+ (add column / set cell / edit row / get row — source columns stay read-only),
14
+ and dataset search + query-derivation (full-text / semantic / regex / word
15
+ union·intersect, LLM keyword-expand, derive-by-query + derived rows).
14
16
  """
15
17
 
16
18
  from __future__ import annotations
@@ -746,13 +746,188 @@ class DatasetsClient:
746
746
  _check(r)
747
747
  return r.json()
748
748
 
749
- def search_dataset(self, repo_id: str, query: str, *, limit: int = 20) -> list[dict]:
750
- """Full-text search a dataset's index. Call ``index_dataset`` first."""
749
+ def search_dataset(
750
+ self,
751
+ repo_id: str,
752
+ query: str,
753
+ *,
754
+ limit: int = 20,
755
+ mode: str = "mixed",
756
+ lang: str = "",
757
+ ) -> list[dict]:
758
+ """Full-text search a dataset's index. Call ``index_dataset`` first.
759
+
760
+ ``mode``: "mixed" (ranked tokens, default) or "exact" (phrase match).
761
+ ``lang``: restrict to a language / CSV ("fr" or "fr,en"); "" = all.
762
+ Delegates to the native (Rust) core when the ``openrunner-core`` wheel is
763
+ installed, else pure-Python httpx.
764
+ """
751
765
  ds = self._resolve(repo_id)
752
- r = self._http.get(f"/datasets/{ds.id}/search", params={"q": query, "limit": limit})
766
+ nat = self._native_client()
767
+ if nat is not None:
768
+ return nat.dataset_search(str(ds.id), query, mode, lang, limit).get("rows", [])
769
+ params: dict[str, Any] = {"q": query, "limit": limit, "mode": mode}
770
+ if lang:
771
+ params["lang"] = lang
772
+ r = self._http.get(f"/datasets/{ds.id}/search", params=params)
753
773
  _check(r)
754
774
  return r.json().get("rows", [])
755
775
 
776
+ # -- semantic / lexical / query-derivation -------------------------------
777
+ def semantic_search(
778
+ self, repo_id: str, query: str, *, limit: int = 20, lang: str = ""
779
+ ) -> list[dict]:
780
+ """Vector (cosine ANN) search over a dataset's embeddings.
781
+
782
+ Requires the embedding index built first via
783
+ ``optimize_embedding_search``. Native core when available, else httpx.
784
+ """
785
+ ds = self._resolve(repo_id)
786
+ nat = self._native_client()
787
+ if nat is not None:
788
+ out = nat.semantic_search(str(ds.id), query, lang, limit)
789
+ return out.get("rows", out.get("hits", []))
790
+ params: dict[str, Any] = {"q": query, "limit": limit}
791
+ if lang:
792
+ params["lang"] = lang
793
+ r = self._http.get(f"/datasets/{ds.id}/semantic", params=params)
794
+ _check(r)
795
+ return r.json().get("rows", r.json().get("hits", []))
796
+
797
+ def regex_search(
798
+ self, repo_id: str, pattern: str, *, limit: int = 20, lang: str = ""
799
+ ) -> list[dict]:
800
+ """Regex search: match a Python-``re`` ``pattern`` against the dataset's
801
+ text column (streamed, bounded — no index needed). Case-insensitive is
802
+ opt-in via an inline ``(?i)`` flag. Native core when available, else httpx.
803
+ Pairs with ``derive_by_query(mode="regex")`` to build a regex-derived set.
804
+ """
805
+ ds = self._resolve(repo_id)
806
+ nat = self._native_client()
807
+ if nat is not None:
808
+ return nat.regex_search(str(ds.id), pattern, lang, limit).get("rows", [])
809
+ params: dict[str, Any] = {"q": pattern, "limit": limit, "mode": "regex"}
810
+ if lang:
811
+ params["lang"] = lang
812
+ r = self._http.get(f"/datasets/{ds.id}/search", params=params)
813
+ _check(r)
814
+ return r.json().get("rows", [])
815
+
816
+ def optimize_embedding_search(
817
+ self,
818
+ repo_id: str,
819
+ *,
820
+ text_column: str | None = None,
821
+ max_rows: int = 200000,
822
+ model: str | None = None,
823
+ ) -> dict:
824
+ """Embed missing rows and build the ANN index that ``semantic_search``
825
+ (and derive ``mode="semantic"``) need. Native core when available."""
826
+ ds = self._resolve(repo_id)
827
+ nat = self._native_client()
828
+ if nat is not None:
829
+ return nat.optimize_embedding_search(str(ds.id), text_column, max_rows, model)
830
+ body = {"text_column": text_column, "max_rows": max_rows, "model": model}
831
+ r = self._http.post(
832
+ f"/datasets/{ds.id}/optimize-embedding-search", json=body, timeout=1800.0
833
+ )
834
+ _check(r)
835
+ return r.json()
836
+
837
+ def word_lookup(
838
+ self, repo_id: str, terms: str | list[str], *, op: str = "union", lang: str = ""
839
+ ) -> dict:
840
+ """Word(s) -> matching-row lookup via the ``lexical_map`` table.
841
+
842
+ ``terms`` is one word, a CSV string, or a list. ``op`` combines
843
+ multi-term hits: "union" (ANY) or "intersect" (ALL). ``lang`` scopes to a
844
+ language / CSV. Returns per-term df + combined ids. Native core when
845
+ available, else httpx.
846
+ """
847
+ ds = self._resolve(repo_id)
848
+ term = ",".join(terms) if isinstance(terms, (list, tuple)) else terms
849
+ nat = self._native_client()
850
+ if nat is not None:
851
+ return nat.word_lookup(str(ds.id), term, op, lang)
852
+ params: dict[str, Any] = {"term": term, "op": op}
853
+ if lang:
854
+ params["lang"] = lang
855
+ r = self._http.get(f"/datasets/{ds.id}/word-lookup", params=params)
856
+ _check(r)
857
+ return r.json()
858
+
859
+ def keyword_expand(
860
+ self, prompt: str, *, count: int = 500, model: str | None = None
861
+ ) -> dict:
862
+ """Expand a domain prompt into many search keywords via an LLM.
863
+
864
+ Returns ``{keywords, csv, count, model, prompt}`` — feed ``csv`` into
865
+ ``word_lookup`` or ``derive_by_query(mode="word", q=csv)``. Native core
866
+ when available, else httpx.
867
+ """
868
+ nat = self._native_client()
869
+ if nat is not None:
870
+ return nat.keyword_expand(prompt, count, model)
871
+ body = {"prompt": prompt, "count": count, "model": model}
872
+ r = self._http.post("/datasets/keyword-expand", json=body, timeout=120.0)
873
+ _check(r)
874
+ return r.json()
875
+
876
+ def derive_by_query(
877
+ self,
878
+ repo_id: str,
879
+ q: str,
880
+ *,
881
+ name: str | None = None,
882
+ mode: str = "semantic",
883
+ lang: str | None = None,
884
+ limit: int = 2000,
885
+ target_repo_id: str | None = None,
886
+ project_id: str | None = None,
887
+ ) -> DatasetInfo:
888
+ """Create (or append to) a dataset **derived from a query** over ``repo_id``.
889
+
890
+ ``mode``: "word" (``q`` = term / CSV; pairs with LLM ``keyword_expand``),
891
+ "fts" (BM25), "exact" (phrase), "regex" (``q`` = a Python-``re`` pattern
892
+ matched over the text column, bounded), "semantic" (vector — needs
893
+ ``optimize_embedding_search``). ``lang`` filters by language / CSV. Pass
894
+ ``name`` to create, or ``target_repo_id`` to append (must derive from the
895
+ same parent). Lineage is recorded automatically. The query runs and
896
+ member keys are recorded natively when the core wheel is installed; the
897
+ parent/target resolution + DatasetInfo wrapping stay in Python.
898
+ """
899
+ ds = self._resolve(repo_id)
900
+ body: dict[str, Any] = {"mode": mode, "q": q, "limit": limit}
901
+ if name:
902
+ body["name"] = name
903
+ if lang:
904
+ body["lang"] = lang
905
+ if project_id:
906
+ body["project_id"] = str(project_id)
907
+ if target_repo_id:
908
+ body["target_dataset_id"] = str(self._resolve(target_repo_id).id)
909
+ elif not name:
910
+ raise ValueError("derive_by_query needs either name= (create) or target_repo_id= (append)")
911
+ nat = self._native_client()
912
+ if nat is not None:
913
+ return DatasetInfo._from_json(nat.derive_dataset(str(ds.id), body))
914
+ r = self._http.post(f"/datasets/{ds.id}/derive", json=body, timeout=600.0)
915
+ _check(r)
916
+ return DatasetInfo._from_json(r.json())
917
+
918
+ def derived_rows(self, repo_id: str, *, limit: int = 50, offset: int = 0) -> dict:
919
+ """Page a query-derived dataset's rows: member keys + inherited parent
920
+ fields (lineage-namespaced) + extra columns. Native core when available."""
921
+ ds = self._resolve(repo_id)
922
+ nat = self._native_client()
923
+ if nat is not None:
924
+ return nat.derived_rows(str(ds.id), limit, offset)
925
+ r = self._http.get(
926
+ f"/datasets/{ds.id}/derived-rows", params={"limit": limit, "offset": offset}
927
+ )
928
+ _check(r)
929
+ return r.json()
930
+
756
931
  def update_dataset(self, repo_id: str, **fields: Any) -> DatasetInfo:
757
932
  ds = self._resolve(repo_id)
758
933
  if "card" in fields:
@@ -1132,6 +1307,41 @@ def search_dataset(repo_id: str, query: str, **kwargs: Any) -> list[dict]:
1132
1307
  return _c().search_dataset(repo_id, query, **kwargs)
1133
1308
 
1134
1309
 
1310
+ def semantic_search(repo_id: str, query: str, **kwargs: Any) -> list[dict]:
1311
+ """Vector (cosine ANN) search — needs ``optimize_embedding_search`` first."""
1312
+ return _c().semantic_search(repo_id, query, **kwargs)
1313
+
1314
+
1315
+ def regex_search(repo_id: str, pattern: str, **kwargs: Any) -> list[dict]:
1316
+ """Regex search — Python-``re`` ``pattern`` over the text column (bounded)."""
1317
+ return _c().regex_search(repo_id, pattern, **kwargs)
1318
+
1319
+
1320
+ def optimize_embedding_search(repo_id: str, **kwargs: Any) -> dict:
1321
+ """Embed rows + build the ANN index for semantic search / semantic-derive."""
1322
+ return _c().optimize_embedding_search(repo_id, **kwargs)
1323
+
1324
+
1325
+ def word_lookup(repo_id: str, terms: "str | list[str]", **kwargs: Any) -> dict:
1326
+ """Word(s) -> rows via lexical_map; ``op`` union|intersect, ``lang`` filter."""
1327
+ return _c().word_lookup(repo_id, terms, **kwargs)
1328
+
1329
+
1330
+ def keyword_expand(prompt: str, **kwargs: Any) -> dict:
1331
+ """LLM-expand a domain prompt into search keywords ({keywords, csv, count})."""
1332
+ return _c().keyword_expand(prompt, **kwargs)
1333
+
1334
+
1335
+ def derive_by_query(repo_id: str, q: str, **kwargs: Any) -> "DatasetInfo":
1336
+ """Create/append a dataset derived from a word|fts|exact|semantic query."""
1337
+ return _c().derive_by_query(repo_id, q, **kwargs)
1338
+
1339
+
1340
+ def derived_rows(repo_id: str, **kwargs: Any) -> dict:
1341
+ """Page a query-derived dataset's rows (member keys + inherited parent fields)."""
1342
+ return _c().derived_rows(repo_id, **kwargs)
1343
+
1344
+
1135
1345
  def set_storage_policy(repo_id: str, tier: str) -> dict:
1136
1346
  return _c().set_storage_policy(repo_id, tier)
1137
1347
 
@@ -2135,14 +2135,54 @@ Give the dataset **URL** (`<base>/datasets/<id>`), the modality/tasks/languages,
2135
2135
 
2136
2136
  DERIVE_DATASET_CMD = """---
2137
2137
  name: {prefix}derive-dataset
2138
- description: Derive a dataset from an existing one by adding a computed column (e.g. a quality/`suspicious` flag) — keeps lineage, never re-uploads the parent's media
2139
- argument-hint: "[parent org/name] [child org/name] [--column NAME]"
2138
+ description: Derive a dataset from an existing one — either by a SEARCH QUERY (semantic / regex / word union·intersect / fts / exact, with language filter + LLM keyword expansion) or by adding a computed column. Keeps lineage, never re-uploads the parent's media.
2139
+ argument-hint: "[parent org/name] [child org/name] [--query ... | --column NAME]"
2140
2140
  allowed-tools:
2141
2141
  - Bash
2142
2142
  - Read
2143
2143
  - AskUserQuestion
2144
2144
  ---
2145
2145
 
2146
+ Two ways to derive a NEW dataset from a parent, both lineage-tracked and media-free:
2147
+
2148
+ - **A. Query-derivation** — select a SUBSET of the parent's rows by a search: `semantic`, `word` (term list, UNION or INTERSECT), `fts` (BM25), or `exact` (phrase), with an optional **language filter** and optional **LLM keyword expansion**. Only matching primary keys are stored — no rows/media copied, de-dup automatic. Use when the user says "make a dataset of the medical/french/... clips", "everything matching X", "semantically similar to X".
2149
+ - **B. Computed-column** — add one or more computed columns (e.g. a heuristic `suspicious` GT-quality flag) keyed 1:1 to the parent rows.
2150
+
2151
+ Pick by intent: **subset/select rows -> A**; **annotate/flag rows -> B**.
2152
+
2153
+ ---
2154
+
2155
+ ## A. Query-derivation (semantic / regex / word union·intersect / fts / exact + lang + LLM keywords)
2156
+
2157
+ All server-side; the SDK delegates to the native Rust core when installed. `PARENT` must be indexed (`ds.index_dataset(...)`; for `semantic`, also `ds.optimize_embedding_search(...)`).
2158
+
2159
+ ```bash
2160
+ python3 -c "
2161
+ from openrunner import datasets as ds
2162
+
2163
+ kw = ds.keyword_expand('medical terms in french', count=300) # {{keywords, csv, count}}
2164
+ child = ds.derive_by_query('ORG/PARENT', kw['csv'],
2165
+ name='ORG/medical-fr', mode='word', lang='fr', limit=5000) # WORD union + lang filter
2166
+ print('created', child.name, child.id)
2167
+
2168
+ hit = ds.word_lookup('ORG/PARENT', 'medical,doctor,prescription', op='intersect', lang='fr') # ALL terms
2169
+
2170
+ ds.optimize_embedding_search('ORG/PARENT') # build ANN index once
2171
+ ds.derive_by_query('ORG/PARENT', 'patient describing symptoms',
2172
+ name='ORG/symptom-desc', mode='semantic', lang='en,fr') # SEMANTIC
2173
+
2174
+ ds.derive_by_query('ORG/PARENT', 'insurance claim', name='ORG/claims', mode='fts') # BM25
2175
+ ds.derive_by_query('ORG/PARENT', 'pharmacy,pharmacist', target_repo_id='ORG/medical-fr', mode='word') # append, de-dup
2176
+ print(ds.derived_rows('ORG/medical-fr', limit=10))
2177
+ "
2178
+ ```
2179
+
2180
+ Query modes (`mode=`): `word` (CSV of terms; `op='union'|'intersect'`), `fts` (BM25), `exact` (phrase), `regex` (a Python-`re` pattern over the text column, e.g. `ds.regex_search('ORG/PARENT', r'\\bcancel(led)?\\b')` / `ds.derive_by_query('ORG/PARENT', r'\\brefund', name='ORG/refunds', mode='regex')`), `semantic` (vector ANN). `lang=` takes a language or CSV ("fr" / "en,fr"); "" = all. Lineage to `PARENT` is recorded automatically by `derive_by_query`.
2181
+
2182
+ ---
2183
+
2184
+ ## B. Computed-column derivation
2185
+
2146
2186
  Derive a NEW dataset from an existing parent by adding one or more **computed columns** (e.g. a heuristic `suspicious` GT-quality flag), preserving lineage.
2147
2187
 
2148
2188
  **Datasets are first-class — do NOT use `openrunner.Artifact` for this.** An Artifact is a model/file blob attached to a run; a dataset is a governed, queryable, lineage-tracked entity. Deriving = a child dataset linked to its parent via `add_derivation`, so the platform shows the lineage graph and **blocks deleting the parent while children exist**.
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "openrunner-sdk"
3
- version = "2.41.4"
3
+ version = "2.41.6"
4
4
  description = "OpenRunner SDK - W&B-compatible ML experiment tracking client"
5
5
  readme = "README.md"
6
6
  license = {text = "MIT"}
@@ -684,11 +684,155 @@ def test_index_dataset_truncated_warns(monkeypatch):
684
684
 
685
685
  def test_search_dataset(monkeypatch):
686
686
  c = _client(monkeypatch)
687
+ c._native = None # force httpx fallback (no native wheel)
687
688
  c._resolve = MagicMock(return_value=DatasetInfo._from_json(_DS_JSON))
688
689
  c._http.get.return_value = _resp(200, {"rows": [{"id": 1}]})
689
690
  assert c.search_dataset("gladia/wmt", "hi") == [{"id": 1}]
690
691
 
691
692
 
693
+ def test_search_dataset_mode_and_lang(monkeypatch):
694
+ c = _client(monkeypatch)
695
+ c._native = None
696
+ c._resolve = MagicMock(return_value=DatasetInfo._from_json(_DS_JSON))
697
+ c._http.get.return_value = _resp(200, {"rows": []})
698
+ c.search_dataset("g/n", "hi", mode="exact", lang="fr")
699
+ params = c._http.get.call_args.kwargs["params"]
700
+ assert params["mode"] == "exact" and params["lang"] == "fr"
701
+
702
+
703
+ def test_search_dataset_native_delegates(monkeypatch):
704
+ c = _client(monkeypatch)
705
+ c._resolve = MagicMock(return_value=DatasetInfo._from_json(_DS_JSON))
706
+ nat = MagicMock()
707
+ nat.dataset_search.return_value = {"rows": [{"id": 42}]}
708
+ c._native = nat
709
+ assert c.search_dataset("g/n", "hi", mode="exact", lang="fr", limit=5) == [{"id": 42}]
710
+ nat.dataset_search.assert_called_once_with("ds-1", "hi", "exact", "fr", 5)
711
+ c._http.get.assert_not_called()
712
+
713
+
714
+ def test_semantic_search(monkeypatch):
715
+ c = _client(monkeypatch)
716
+ c._native = None
717
+ c._resolve = MagicMock(return_value=DatasetInfo._from_json(_DS_JSON))
718
+ c._http.get.return_value = _resp(200, {"hits": [{"id": 9, "score": 0.8}]})
719
+ assert c.semantic_search("g/n", "symptoms", lang="en,fr")[0]["id"] == 9
720
+ assert "/semantic" in c._http.get.call_args.args[0]
721
+
722
+
723
+ def test_regex_search(monkeypatch):
724
+ c = _client(monkeypatch)
725
+ c._native = None
726
+ c._resolve = MagicMock(return_value=DatasetInfo._from_json(_DS_JSON))
727
+ c._http.get.return_value = _resp(200, {"rows": [{"debug_id": "r1"}]})
728
+ out = c.regex_search("g/n", r"\bcancel(led)?\b", lang="en", limit=5)
729
+ assert out[0]["debug_id"] == "r1"
730
+ params = c._http.get.call_args.kwargs["params"]
731
+ assert params["mode"] == "regex" and params["q"] == r"\bcancel(led)?\b"
732
+ assert params["lang"] == "en"
733
+ assert "/search" in c._http.get.call_args.args[0]
734
+
735
+
736
+ def test_regex_search_native_delegates(monkeypatch):
737
+ c = _client(monkeypatch)
738
+ c._resolve = MagicMock(return_value=DatasetInfo._from_json(_DS_JSON))
739
+ nat = MagicMock()
740
+ nat.regex_search.return_value = {"rows": [{"debug_id": "x"}]}
741
+ c._native = nat
742
+ assert c.regex_search("g/n", "foo.*bar", lang="fr", limit=7) == [{"debug_id": "x"}]
743
+ nat.regex_search.assert_called_once_with("ds-1", "foo.*bar", "fr", 7)
744
+ c._http.get.assert_not_called()
745
+
746
+
747
+ def test_derive_by_query_regex_mode(monkeypatch):
748
+ c = _client(monkeypatch)
749
+ c._native = None
750
+ c._resolve = MagicMock(return_value=DatasetInfo._from_json(_DS_JSON))
751
+ c._http.post.return_value = _resp(200, dict(_DS_JSON, name="cancels"))
752
+ c.derive_by_query("g/parent", r"\bcancel", name="g/cancels", mode="regex", lang="en")
753
+ body = c._http.post.call_args.kwargs["json"]
754
+ assert body["mode"] == "regex" and body["q"] == r"\bcancel" and body["lang"] == "en"
755
+
756
+
757
+ def test_optimize_embedding_search(monkeypatch):
758
+ c = _client(monkeypatch)
759
+ c._native = None
760
+ c._resolve = MagicMock(return_value=DatasetInfo._from_json(_DS_JSON))
761
+ c._http.post.return_value = _resp(200, {"status": "running"})
762
+ assert c.optimize_embedding_search("g/n")["status"] == "running"
763
+
764
+
765
+ def test_word_lookup_union_intersect(monkeypatch):
766
+ c = _client(monkeypatch)
767
+ c._native = None
768
+ c._resolve = MagicMock(return_value=DatasetInfo._from_json(_DS_JSON))
769
+ c._http.get.return_value = _resp(200, {"ids": [1, 2]})
770
+ c.word_lookup("g/n", ["a", "b"], op="intersect", lang="fr")
771
+ params = c._http.get.call_args.kwargs["params"]
772
+ assert params["term"] == "a,b" and params["op"] == "intersect" and params["lang"] == "fr"
773
+
774
+
775
+ def test_keyword_expand(monkeypatch):
776
+ c = _client(monkeypatch)
777
+ c._native = None
778
+ c._http.post.return_value = _resp(200, {"keywords": ["a", "b"], "csv": "a, b", "count": 2})
779
+ out = c.keyword_expand("medical terms in french", count=2)
780
+ assert out["count"] == 2
781
+ assert c._http.post.call_args.args[0] == "/datasets/keyword-expand"
782
+
783
+
784
+ def test_derive_by_query_create(monkeypatch):
785
+ c = _client(monkeypatch)
786
+ c._native = None
787
+ c._resolve = MagicMock(return_value=DatasetInfo._from_json(_DS_JSON))
788
+ c._http.post.return_value = _resp(200, dict(_DS_JSON, name="medical-fr"))
789
+ out = c.derive_by_query("g/parent", "a,b", name="g/medical-fr", mode="word", lang="fr")
790
+ assert out.name == "medical-fr"
791
+ body = c._http.post.call_args.kwargs["json"]
792
+ assert body["mode"] == "word" and body["name"] == "g/medical-fr" and body["lang"] == "fr"
793
+
794
+
795
+ def test_derive_by_query_native_delegates(monkeypatch):
796
+ c = _client(monkeypatch)
797
+ c._resolve = MagicMock(return_value=DatasetInfo._from_json(_DS_JSON))
798
+ nat = MagicMock()
799
+ nat.derive_dataset.return_value = dict(_DS_JSON, name="medical-fr")
800
+ c._native = nat
801
+ out = c.derive_by_query("g/parent", "a,b", name="g/medical-fr", mode="word")
802
+ assert out.name == "medical-fr"
803
+ nat.derive_dataset.assert_called_once()
804
+ c._http.post.assert_not_called()
805
+
806
+
807
+ def test_derive_by_query_append(monkeypatch):
808
+ c = _client(monkeypatch)
809
+ c._native = None
810
+ parent = DatasetInfo._from_json(_DS_JSON)
811
+ target = DatasetInfo._from_json(dict(_DS_JSON, id="ds-2", name="medical-fr"))
812
+ c._resolve = MagicMock(side_effect=[parent, target])
813
+ c._http.post.return_value = _resp(200, dict(_DS_JSON, id="ds-2"))
814
+ c.derive_by_query("g/parent", "c,d", target_repo_id="g/medical-fr", mode="word")
815
+ body = c._http.post.call_args.kwargs["json"]
816
+ assert body["target_dataset_id"] == "ds-2" and "name" not in body
817
+
818
+
819
+ def test_derive_by_query_requires_name_or_target(monkeypatch):
820
+ c = _client(monkeypatch)
821
+ c._native = None
822
+ c._resolve = MagicMock(return_value=DatasetInfo._from_json(_DS_JSON))
823
+ with pytest.raises(ValueError, match="name= .* target_repo_id="):
824
+ c.derive_by_query("g/parent", "q", mode="word")
825
+
826
+
827
+ def test_derived_rows(monkeypatch):
828
+ c = _client(monkeypatch)
829
+ c._native = None
830
+ c._resolve = MagicMock(return_value=DatasetInfo._from_json(_DS_JSON))
831
+ c._http.get.return_value = _resp(200, {"rows": [{"k": 1}], "total": 1, "offset": 0, "limit": 50})
832
+ assert c.derived_rows("g/n")["total"] == 1
833
+ assert "/derived-rows" in c._http.get.call_args.args[0]
834
+
835
+
692
836
  # ===========================================================================
693
837
  # update / card / preview / links / derivation / delete
694
838
  # ===========================================================================
@@ -978,6 +1122,41 @@ def test_module_link_project(fake_singleton):
978
1122
  assert ds_mod.link_project("g/n", "proj-1") == "P"
979
1123
 
980
1124
 
1125
+ def test_module_semantic_search(fake_singleton):
1126
+ fake_singleton.semantic_search.return_value = [{"id": 2}]
1127
+ assert ds_mod.semantic_search("g/n", "q", lang="fr") == [{"id": 2}]
1128
+
1129
+
1130
+ def test_module_regex_search(fake_singleton):
1131
+ fake_singleton.regex_search.return_value = [{"debug_id": "r1"}]
1132
+ assert ds_mod.regex_search("g/n", r"\bfoo", lang="en") == [{"debug_id": "r1"}]
1133
+
1134
+
1135
+ def test_module_optimize_embedding_search(fake_singleton):
1136
+ fake_singleton.optimize_embedding_search.return_value = {"status": "ready"}
1137
+ assert ds_mod.optimize_embedding_search("g/n") == {"status": "ready"}
1138
+
1139
+
1140
+ def test_module_word_lookup(fake_singleton):
1141
+ fake_singleton.word_lookup.return_value = {"ids": [1]}
1142
+ assert ds_mod.word_lookup("g/n", "a,b", op="union") == {"ids": [1]}
1143
+
1144
+
1145
+ def test_module_keyword_expand(fake_singleton):
1146
+ fake_singleton.keyword_expand.return_value = {"csv": "a, b", "count": 2}
1147
+ assert ds_mod.keyword_expand("prompt", count=2)["count"] == 2
1148
+
1149
+
1150
+ def test_module_derive_by_query(fake_singleton):
1151
+ fake_singleton.derive_by_query.return_value = DatasetInfo._from_json(_DS_JSON)
1152
+ assert ds_mod.derive_by_query("g/p", "q", name="g/c").name == "wmt"
1153
+
1154
+
1155
+ def test_module_derived_rows(fake_singleton):
1156
+ fake_singleton.derived_rows.return_value = {"total": 3}
1157
+ assert ds_mod.derived_rows("g/c")["total"] == 3
1158
+
1159
+
981
1160
  def test_module_upload_file(fake_singleton):
982
1161
  fake_singleton.upload_file.return_value = {"ok": True}
983
1162
  assert ds_mod.upload_file("g/n", "f.txt") == {"ok": True}
File without changes
File without changes