openrunner-sdk 2.41.4__tar.gz → 2.41.5__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.5}/PKG-INFO +1 -1
  2. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/CLAUDE.md +26 -0
  3. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/__init__.py +6 -0
  4. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/_native.py +4 -2
  5. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/datasets.py +188 -3
  6. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/install_commands.py +42 -2
  7. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/pyproject.toml +1 -1
  8. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/test_datasets_module.py +140 -0
  9. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/.gitignore +0 -0
  10. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/=6.0 +0 -0
  11. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/=8.1 +0 -0
  12. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/README.md +0 -0
  13. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/_retry_transport.py +0 -0
  14. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/_safepath.py +0 -0
  15. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/_secret_rules.py +0 -0
  16. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/api_client.py +0 -0
  17. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/artifact.py +0 -0
  18. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/autoresearch.py +0 -0
  19. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/buffer.py +0 -0
  20. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/cache.py +0 -0
  21. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/cli.py +0 -0
  22. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/config.py +0 -0
  23. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/cost.py +0 -0
  24. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/dataset.py +0 -0
  25. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/environment.py +0 -0
  26. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/evaluation.py +0 -0
  27. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/feedback.py +0 -0
  28. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/git_info.py +0 -0
  29. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/gpu/__init__.py +0 -0
  30. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/gpu/api_integration.py +0 -0
  31. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/gpu/cost_guard.py +0 -0
  32. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/gpu/gpu_types.py +0 -0
  33. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/gpu/price_compare.py +0 -0
  34. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/gpu/provider_base.py +0 -0
  35. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/gpu/providers/__init__.py +0 -0
  36. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/gpu/providers/forge_provider.py +0 -0
  37. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/gpu/providers/lambda_cloud.py +0 -0
  38. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/gpu/providers/modal_provider.py +0 -0
  39. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/gpu/providers/ovhcloud.py +0 -0
  40. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/gpu/providers/runpod.py +0 -0
  41. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/gpu/providers/vastai.py +0 -0
  42. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/gpu/runner.py +0 -0
  43. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/gpu/workspace_sync.py +0 -0
  44. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/guardrails.py +0 -0
  45. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/handover.py +0 -0
  46. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/hooks/patent-lab-post-commit +0 -0
  47. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/integration/__init__.py +0 -0
  48. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/integration/accelerate.py +0 -0
  49. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/integration/anthropic_tracer.py +0 -0
  50. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/integration/catboost.py +0 -0
  51. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/integration/diffusers.py +0 -0
  52. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/integration/fastai.py +0 -0
  53. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/integration/forced_alignment.py +0 -0
  54. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/integration/gladia.py +0 -0
  55. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/integration/gymnasium.py +0 -0
  56. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/integration/huggingface.py +0 -0
  57. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/integration/hydra.py +0 -0
  58. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/integration/ignite.py +0 -0
  59. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/integration/jax.py +0 -0
  60. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/integration/keras.py +0 -0
  61. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/integration/langchain.py +0 -0
  62. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/integration/lightgbm.py +0 -0
  63. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/integration/lightning.py +0 -0
  64. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/integration/llamaindex.py +0 -0
  65. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/integration/openai_finetune.py +0 -0
  66. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/integration/openai_tracer.py +0 -0
  67. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/integration/optuna.py +0 -0
  68. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/integration/pytorch.py +0 -0
  69. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/integration/sb3.py +0 -0
  70. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/integration/sklearn.py +0 -0
  71. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/integration/skypilot.py +0 -0
  72. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/integration/tensorflow.py +0 -0
  73. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/integration/trl.py +0 -0
  74. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/integration/tts.py +0 -0
  75. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/integration/ultralytics.py +0 -0
  76. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/integration/voice_agent.py +0 -0
  77. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/integration/whisper.py +0 -0
  78. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/integration/xgboost.py +0 -0
  79. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/launch.py +0 -0
  80. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/machine.py +0 -0
  81. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/mcp_server.py +0 -0
  82. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/media.py +0 -0
  83. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/migrate.py +0 -0
  84. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/model.py +0 -0
  85. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/model_card.py +0 -0
  86. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/offline.py +0 -0
  87. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/patent_scan.py +0 -0
  88. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/pii.py +0 -0
  89. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/plot.py +0 -0
  90. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/projects.py +0 -0
  91. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/prompt.py +0 -0
  92. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/query_api.py +0 -0
  93. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/redact.py +0 -0
  94. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/reload.py +0 -0
  95. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/research.py +0 -0
  96. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/research_policy.py +0 -0
  97. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/run.py +0 -0
  98. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/scorers.py +0 -0
  99. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/sender.py +0 -0
  100. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/session.py +0 -0
  101. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/settings.py +0 -0
  102. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/summary.py +0 -0
  103. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/sweep.py +0 -0
  104. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/sync.py +0 -0
  105. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/system_metrics.py +0 -0
  106. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/tensorboard.py +0 -0
  107. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/tools/__init__.py +0 -0
  108. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/tools/patent_report.py +0 -0
  109. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/trace.py +0 -0
  110. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/transcript_formatter.py +0 -0
  111. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/wal.py +0 -0
  112. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/wandb_compat/__init__.py +0 -0
  113. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/wandb_compat/_shim.py +0 -0
  114. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/openrunner/wer.py +0 -0
  115. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/scripts/gen_betterleaks_rules.py +0 -0
  116. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/__init__.py +0 -0
  117. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/conftest.py +0 -0
  118. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/fixtures/wandb-export-mini/run-aaa/config.json +0 -0
  119. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/fixtures/wandb-export-mini/run-aaa/metadata.json +0 -0
  120. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/fixtures/wandb-export-mini/run-aaa/metrics.jsonl +0 -0
  121. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/fixtures/wandb-export-mini/run-aaa/summary.json +0 -0
  122. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/fixtures/wandb-export-mini/run-bbb/artifacts/model-checkpoint/manifest.json +0 -0
  123. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/fixtures/wandb-export-mini/run-bbb/artifacts/model-checkpoint/weights.bin +0 -0
  124. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/fixtures/wandb-export-mini/run-bbb/artifacts/sample-image/manifest.json +0 -0
  125. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/fixtures/wandb-export-mini/run-bbb/artifacts/sample-image/preview.png +0 -0
  126. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/fixtures/wandb-export-mini/run-bbb/config.json +0 -0
  127. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/fixtures/wandb-export-mini/run-bbb/metadata.json +0 -0
  128. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/fixtures/wandb-export-mini/run-bbb/metrics.jsonl +0 -0
  129. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/fixtures/wandb-export-mini/run-bbb/summary.json +0 -0
  130. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/integration/__init__.py +0 -0
  131. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/integration/conftest.py +0 -0
  132. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/integration/test_artifact_round_trip.py +0 -0
  133. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/test_alert.py +0 -0
  134. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/test_aliases.py +0 -0
  135. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/test_api_client.py +0 -0
  136. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/test_api_client_methods.py +0 -0
  137. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/test_api_client_transport.py +0 -0
  138. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/test_artifact.py +0 -0
  139. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/test_buffer.py +0 -0
  140. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/test_cache.py +0 -0
  141. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/test_class_scorers.py +0 -0
  142. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/test_cli.py +0 -0
  143. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/test_cli_artifact_sweep.py +0 -0
  144. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/test_cli_datasets.py +0 -0
  145. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/test_cli_gpu_registry_deploy.py +0 -0
  146. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/test_cli_infra.py +0 -0
  147. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/test_cli_remainder.py +0 -0
  148. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/test_cli_topup.py +0 -0
  149. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/test_config.py +0 -0
  150. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/test_evaluation.py +0 -0
  151. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/test_finish.py +0 -0
  152. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/test_git_info.py +0 -0
  153. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/test_gpu/__init__.py +0 -0
  154. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/test_gpu/conftest.py +0 -0
  155. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/test_gpu/test_cost_guard.py +0 -0
  156. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/test_gpu/test_engine_serverside.py +0 -0
  157. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/test_gpu/test_forge.py +0 -0
  158. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/test_gpu/test_governed_jobs.py +0 -0
  159. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/test_gpu/test_gpu_cluster.py +0 -0
  160. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/test_gpu/test_gpu_types.py +0 -0
  161. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/test_gpu/test_lambda.py +0 -0
  162. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/test_gpu/test_modal.py +0 -0
  163. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/test_gpu/test_ovh_training.py +0 -0
  164. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/test_gpu/test_ovhcloud.py +0 -0
  165. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/test_gpu/test_price_compare.py +0 -0
  166. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/test_gpu/test_provider_base.py +0 -0
  167. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/test_gpu/test_runner.py +0 -0
  168. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/test_gpu/test_runpod.py +0 -0
  169. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/test_gpu/test_sdk_gpu_api.py +0 -0
  170. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/test_gpu/test_vastai.py +0 -0
  171. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/test_gpu/test_workspace_sync.py +0 -0
  172. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/test_gpu_modal_creds.py +0 -0
  173. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/test_init.py +0 -0
  174. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/test_init_facade.py +0 -0
  175. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/test_install_commands.py +0 -0
  176. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/test_integration_fastai.py +0 -0
  177. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/test_integration_huggingface.py +0 -0
  178. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/test_integration_keras.py +0 -0
  179. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/test_integration_langchain.py +0 -0
  180. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/test_integration_lightning.py +0 -0
  181. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/test_integration_pytorch.py +0 -0
  182. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/test_integration_setA.py +0 -0
  183. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/test_integration_setB.py +0 -0
  184. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/test_integration_setC.py +0 -0
  185. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/test_integration_sklearn.py +0 -0
  186. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/test_integration_xgboost.py +0 -0
  187. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/test_launch.py +0 -0
  188. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/test_log.py +0 -0
  189. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/test_log_code.py +0 -0
  190. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/test_machine_migrate.py +0 -0
  191. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/test_mcp_decisions.py +0 -0
  192. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/test_mcp_monitor.py +0 -0
  193. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/test_mcp_predictions.py +0 -0
  194. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/test_mcp_server.py +0 -0
  195. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/test_media.py +0 -0
  196. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/test_media_extra.py +0 -0
  197. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/test_migrate.py +0 -0
  198. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/test_offline.py +0 -0
  199. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/test_offline_sync.py +0 -0
  200. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/test_patent_scan.py +0 -0
  201. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/test_pii.py +0 -0
  202. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/test_plot.py +0 -0
  203. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/test_plot_media_extra2.py +0 -0
  204. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/test_prompt_module.py +0 -0
  205. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/test_pure_modules.py +0 -0
  206. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/test_query_api.py +0 -0
  207. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/test_redact.py +0 -0
  208. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/test_reload_module.py +0 -0
  209. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/test_research_module.py +0 -0
  210. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/test_resume.py +0 -0
  211. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/test_retry_transport.py +0 -0
  212. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/test_run_module.py +0 -0
  213. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/test_sdk_cluster_j1.py +0 -0
  214. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/test_sdk_cluster_j2.py +0 -0
  215. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/test_sdk_cluster_j3.py +0 -0
  216. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/test_sdk_cluster_j4.py +0 -0
  217. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/test_sdk_core_edges.py +0 -0
  218. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/test_sdk_features.py +0 -0
  219. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/test_sender.py +0 -0
  220. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/test_session_module.py +0 -0
  221. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/test_session_sync.py +0 -0
  222. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/test_summary.py +0 -0
  223. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/test_sweep.py +0 -0
  224. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/test_system_metrics.py +0 -0
  225. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/test_topup_hi.py +0 -0
  226. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/tests/test_trace.py +0 -0
  227. {openrunner_sdk-2.41.4 → openrunner_sdk-2.41.5}/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.5
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,32 @@ 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.word_lookup(repo, "medical,doctor", op="union"|"intersect", lang="fr") # lexical_map
100
+ ord.keyword_expand("medical terms in french", count=300) # LLM -> {keywords, csv, count}
101
+
102
+ # derive: mode = word (op union/intersect) | fts | exact | semantic; lang filter; append via target_repo_id
103
+ child = ord.derive_by_query(parent, keywords_csv, name="org/medical-fr",
104
+ mode="word", lang="fr", limit=5000)
105
+ ord.derive_by_query(parent, "more,terms", target_repo_id="org/medical-fr", mode="word") # append, de-dup
106
+ ord.derived_rows("org/medical-fr", limit=50) # member keys + inherited parent fields
107
+ ```
108
+
109
+ `word`+`op="union"` = rows matching ANY term; `op="intersect"` (via `word_lookup`)
110
+ = rows matching ALL. `semantic` needs `optimize_embedding_search` first. Slash
111
+ command: `/openrunner:derive-dataset` (query-derivation **or** computed-column).
112
+
87
113
  # OpenRunner MCP Integration
88
114
 
89
115
  When the user publishes a MODEL, or asks to write/update a model card:
@@ -101,8 +101,14 @@ 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
+ semantic_search,
111
+ word_lookup,
106
112
  set_dataset_card,
107
113
  set_storage_policy,
108
114
  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 / word union·intersect,
15
+ LLM keyword-expand, derive-by-query + derived rows).
14
16
  """
15
17
 
16
18
  from __future__ import annotations
@@ -746,13 +746,168 @@ 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 optimize_embedding_search(
798
+ self,
799
+ repo_id: str,
800
+ *,
801
+ text_column: str | None = None,
802
+ max_rows: int = 200000,
803
+ model: str | None = None,
804
+ ) -> dict:
805
+ """Embed missing rows and build the ANN index that ``semantic_search``
806
+ (and derive ``mode="semantic"``) need. Native core when available."""
807
+ ds = self._resolve(repo_id)
808
+ nat = self._native_client()
809
+ if nat is not None:
810
+ return nat.optimize_embedding_search(str(ds.id), text_column, max_rows, model)
811
+ body = {"text_column": text_column, "max_rows": max_rows, "model": model}
812
+ r = self._http.post(
813
+ f"/datasets/{ds.id}/optimize-embedding-search", json=body, timeout=1800.0
814
+ )
815
+ _check(r)
816
+ return r.json()
817
+
818
+ def word_lookup(
819
+ self, repo_id: str, terms: str | list[str], *, op: str = "union", lang: str = ""
820
+ ) -> dict:
821
+ """Word(s) -> matching-row lookup via the ``lexical_map`` table.
822
+
823
+ ``terms`` is one word, a CSV string, or a list. ``op`` combines
824
+ multi-term hits: "union" (ANY) or "intersect" (ALL). ``lang`` scopes to a
825
+ language / CSV. Returns per-term df + combined ids. Native core when
826
+ available, else httpx.
827
+ """
828
+ ds = self._resolve(repo_id)
829
+ term = ",".join(terms) if isinstance(terms, (list, tuple)) else terms
830
+ nat = self._native_client()
831
+ if nat is not None:
832
+ return nat.word_lookup(str(ds.id), term, op, lang)
833
+ params: dict[str, Any] = {"term": term, "op": op}
834
+ if lang:
835
+ params["lang"] = lang
836
+ r = self._http.get(f"/datasets/{ds.id}/word-lookup", params=params)
837
+ _check(r)
838
+ return r.json()
839
+
840
+ def keyword_expand(
841
+ self, prompt: str, *, count: int = 500, model: str | None = None
842
+ ) -> dict:
843
+ """Expand a domain prompt into many search keywords via an LLM.
844
+
845
+ Returns ``{keywords, csv, count, model, prompt}`` — feed ``csv`` into
846
+ ``word_lookup`` or ``derive_by_query(mode="word", q=csv)``. Native core
847
+ when available, else httpx.
848
+ """
849
+ nat = self._native_client()
850
+ if nat is not None:
851
+ return nat.keyword_expand(prompt, count, model)
852
+ body = {"prompt": prompt, "count": count, "model": model}
853
+ r = self._http.post("/datasets/keyword-expand", json=body, timeout=120.0)
854
+ _check(r)
855
+ return r.json()
856
+
857
+ def derive_by_query(
858
+ self,
859
+ repo_id: str,
860
+ q: str,
861
+ *,
862
+ name: str | None = None,
863
+ mode: str = "semantic",
864
+ lang: str | None = None,
865
+ limit: int = 2000,
866
+ target_repo_id: str | None = None,
867
+ project_id: str | None = None,
868
+ ) -> DatasetInfo:
869
+ """Create (or append to) a dataset **derived from a query** over ``repo_id``.
870
+
871
+ ``mode``: "word" (``q`` = term / CSV; pairs with LLM ``keyword_expand``),
872
+ "fts" (BM25), "exact" (phrase), "semantic" (vector — needs
873
+ ``optimize_embedding_search``). ``lang`` filters by language / CSV. Pass
874
+ ``name`` to create, or ``target_repo_id`` to append (must derive from the
875
+ same parent). Lineage is recorded automatically. The query runs and
876
+ member keys are recorded natively when the core wheel is installed; the
877
+ parent/target resolution + DatasetInfo wrapping stay in Python.
878
+ """
879
+ ds = self._resolve(repo_id)
880
+ body: dict[str, Any] = {"mode": mode, "q": q, "limit": limit}
881
+ if name:
882
+ body["name"] = name
883
+ if lang:
884
+ body["lang"] = lang
885
+ if project_id:
886
+ body["project_id"] = str(project_id)
887
+ if target_repo_id:
888
+ body["target_dataset_id"] = str(self._resolve(target_repo_id).id)
889
+ elif not name:
890
+ raise ValueError("derive_by_query needs either name= (create) or target_repo_id= (append)")
891
+ nat = self._native_client()
892
+ if nat is not None:
893
+ return DatasetInfo._from_json(nat.derive_dataset(str(ds.id), body))
894
+ r = self._http.post(f"/datasets/{ds.id}/derive", json=body, timeout=600.0)
895
+ _check(r)
896
+ return DatasetInfo._from_json(r.json())
897
+
898
+ def derived_rows(self, repo_id: str, *, limit: int = 50, offset: int = 0) -> dict:
899
+ """Page a query-derived dataset's rows: member keys + inherited parent
900
+ fields (lineage-namespaced) + extra columns. Native core when available."""
901
+ ds = self._resolve(repo_id)
902
+ nat = self._native_client()
903
+ if nat is not None:
904
+ return nat.derived_rows(str(ds.id), limit, offset)
905
+ r = self._http.get(
906
+ f"/datasets/{ds.id}/derived-rows", params={"limit": limit, "offset": offset}
907
+ )
908
+ _check(r)
909
+ return r.json()
910
+
756
911
  def update_dataset(self, repo_id: str, **fields: Any) -> DatasetInfo:
757
912
  ds = self._resolve(repo_id)
758
913
  if "card" in fields:
@@ -1132,6 +1287,36 @@ def search_dataset(repo_id: str, query: str, **kwargs: Any) -> list[dict]:
1132
1287
  return _c().search_dataset(repo_id, query, **kwargs)
1133
1288
 
1134
1289
 
1290
+ def semantic_search(repo_id: str, query: str, **kwargs: Any) -> list[dict]:
1291
+ """Vector (cosine ANN) search — needs ``optimize_embedding_search`` first."""
1292
+ return _c().semantic_search(repo_id, query, **kwargs)
1293
+
1294
+
1295
+ def optimize_embedding_search(repo_id: str, **kwargs: Any) -> dict:
1296
+ """Embed rows + build the ANN index for semantic search / semantic-derive."""
1297
+ return _c().optimize_embedding_search(repo_id, **kwargs)
1298
+
1299
+
1300
+ def word_lookup(repo_id: str, terms: "str | list[str]", **kwargs: Any) -> dict:
1301
+ """Word(s) -> rows via lexical_map; ``op`` union|intersect, ``lang`` filter."""
1302
+ return _c().word_lookup(repo_id, terms, **kwargs)
1303
+
1304
+
1305
+ def keyword_expand(prompt: str, **kwargs: Any) -> dict:
1306
+ """LLM-expand a domain prompt into search keywords ({keywords, csv, count})."""
1307
+ return _c().keyword_expand(prompt, **kwargs)
1308
+
1309
+
1310
+ def derive_by_query(repo_id: str, q: str, **kwargs: Any) -> "DatasetInfo":
1311
+ """Create/append a dataset derived from a word|fts|exact|semantic query."""
1312
+ return _c().derive_by_query(repo_id, q, **kwargs)
1313
+
1314
+
1315
+ def derived_rows(repo_id: str, **kwargs: Any) -> dict:
1316
+ """Page a query-derived dataset's rows (member keys + inherited parent fields)."""
1317
+ return _c().derived_rows(repo_id, **kwargs)
1318
+
1319
+
1135
1320
  def set_storage_policy(repo_id: str, tier: str) -> dict:
1136
1321
  return _c().set_storage_policy(repo_id, tier)
1137
1322
 
@@ -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 / 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 / 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), `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.5"
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,121 @@ 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_optimize_embedding_search(monkeypatch):
724
+ c = _client(monkeypatch)
725
+ c._native = None
726
+ c._resolve = MagicMock(return_value=DatasetInfo._from_json(_DS_JSON))
727
+ c._http.post.return_value = _resp(200, {"status": "running"})
728
+ assert c.optimize_embedding_search("g/n")["status"] == "running"
729
+
730
+
731
+ def test_word_lookup_union_intersect(monkeypatch):
732
+ c = _client(monkeypatch)
733
+ c._native = None
734
+ c._resolve = MagicMock(return_value=DatasetInfo._from_json(_DS_JSON))
735
+ c._http.get.return_value = _resp(200, {"ids": [1, 2]})
736
+ c.word_lookup("g/n", ["a", "b"], op="intersect", lang="fr")
737
+ params = c._http.get.call_args.kwargs["params"]
738
+ assert params["term"] == "a,b" and params["op"] == "intersect" and params["lang"] == "fr"
739
+
740
+
741
+ def test_keyword_expand(monkeypatch):
742
+ c = _client(monkeypatch)
743
+ c._native = None
744
+ c._http.post.return_value = _resp(200, {"keywords": ["a", "b"], "csv": "a, b", "count": 2})
745
+ out = c.keyword_expand("medical terms in french", count=2)
746
+ assert out["count"] == 2
747
+ assert c._http.post.call_args.args[0] == "/datasets/keyword-expand"
748
+
749
+
750
+ def test_derive_by_query_create(monkeypatch):
751
+ c = _client(monkeypatch)
752
+ c._native = None
753
+ c._resolve = MagicMock(return_value=DatasetInfo._from_json(_DS_JSON))
754
+ c._http.post.return_value = _resp(200, dict(_DS_JSON, name="medical-fr"))
755
+ out = c.derive_by_query("g/parent", "a,b", name="g/medical-fr", mode="word", lang="fr")
756
+ assert out.name == "medical-fr"
757
+ body = c._http.post.call_args.kwargs["json"]
758
+ assert body["mode"] == "word" and body["name"] == "g/medical-fr" and body["lang"] == "fr"
759
+
760
+
761
+ def test_derive_by_query_native_delegates(monkeypatch):
762
+ c = _client(monkeypatch)
763
+ c._resolve = MagicMock(return_value=DatasetInfo._from_json(_DS_JSON))
764
+ nat = MagicMock()
765
+ nat.derive_dataset.return_value = dict(_DS_JSON, name="medical-fr")
766
+ c._native = nat
767
+ out = c.derive_by_query("g/parent", "a,b", name="g/medical-fr", mode="word")
768
+ assert out.name == "medical-fr"
769
+ nat.derive_dataset.assert_called_once()
770
+ c._http.post.assert_not_called()
771
+
772
+
773
+ def test_derive_by_query_append(monkeypatch):
774
+ c = _client(monkeypatch)
775
+ c._native = None
776
+ parent = DatasetInfo._from_json(_DS_JSON)
777
+ target = DatasetInfo._from_json(dict(_DS_JSON, id="ds-2", name="medical-fr"))
778
+ c._resolve = MagicMock(side_effect=[parent, target])
779
+ c._http.post.return_value = _resp(200, dict(_DS_JSON, id="ds-2"))
780
+ c.derive_by_query("g/parent", "c,d", target_repo_id="g/medical-fr", mode="word")
781
+ body = c._http.post.call_args.kwargs["json"]
782
+ assert body["target_dataset_id"] == "ds-2" and "name" not in body
783
+
784
+
785
+ def test_derive_by_query_requires_name_or_target(monkeypatch):
786
+ c = _client(monkeypatch)
787
+ c._native = None
788
+ c._resolve = MagicMock(return_value=DatasetInfo._from_json(_DS_JSON))
789
+ with pytest.raises(ValueError, match="name= .* target_repo_id="):
790
+ c.derive_by_query("g/parent", "q", mode="word")
791
+
792
+
793
+ def test_derived_rows(monkeypatch):
794
+ c = _client(monkeypatch)
795
+ c._native = None
796
+ c._resolve = MagicMock(return_value=DatasetInfo._from_json(_DS_JSON))
797
+ c._http.get.return_value = _resp(200, {"rows": [{"k": 1}], "total": 1, "offset": 0, "limit": 50})
798
+ assert c.derived_rows("g/n")["total"] == 1
799
+ assert "/derived-rows" in c._http.get.call_args.args[0]
800
+
801
+
692
802
  # ===========================================================================
693
803
  # update / card / preview / links / derivation / delete
694
804
  # ===========================================================================
@@ -978,6 +1088,36 @@ def test_module_link_project(fake_singleton):
978
1088
  assert ds_mod.link_project("g/n", "proj-1") == "P"
979
1089
 
980
1090
 
1091
+ def test_module_semantic_search(fake_singleton):
1092
+ fake_singleton.semantic_search.return_value = [{"id": 2}]
1093
+ assert ds_mod.semantic_search("g/n", "q", lang="fr") == [{"id": 2}]
1094
+
1095
+
1096
+ def test_module_optimize_embedding_search(fake_singleton):
1097
+ fake_singleton.optimize_embedding_search.return_value = {"status": "ready"}
1098
+ assert ds_mod.optimize_embedding_search("g/n") == {"status": "ready"}
1099
+
1100
+
1101
+ def test_module_word_lookup(fake_singleton):
1102
+ fake_singleton.word_lookup.return_value = {"ids": [1]}
1103
+ assert ds_mod.word_lookup("g/n", "a,b", op="union") == {"ids": [1]}
1104
+
1105
+
1106
+ def test_module_keyword_expand(fake_singleton):
1107
+ fake_singleton.keyword_expand.return_value = {"csv": "a, b", "count": 2}
1108
+ assert ds_mod.keyword_expand("prompt", count=2)["count"] == 2
1109
+
1110
+
1111
+ def test_module_derive_by_query(fake_singleton):
1112
+ fake_singleton.derive_by_query.return_value = DatasetInfo._from_json(_DS_JSON)
1113
+ assert ds_mod.derive_by_query("g/p", "q", name="g/c").name == "wmt"
1114
+
1115
+
1116
+ def test_module_derived_rows(fake_singleton):
1117
+ fake_singleton.derived_rows.return_value = {"total": 3}
1118
+ assert ds_mod.derived_rows("g/c")["total"] == 3
1119
+
1120
+
981
1121
  def test_module_upload_file(fake_singleton):
982
1122
  fake_singleton.upload_file.return_value = {"ok": True}
983
1123
  assert ds_mod.upload_file("g/n", "f.txt") == {"ok": True}
File without changes
File without changes