runloop_api_client 1.0.0__tar.gz → 1.1.0__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 (351) hide show
  1. runloop_api_client-1.1.0/.release-please-manifest.json +3 -0
  2. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/CHANGELOG.md +14 -0
  3. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/CONTRIBUTING.md +38 -2
  4. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/PKG-INFO +1 -1
  5. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/README-SDK.md +63 -5
  6. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/pyproject.toml +1 -1
  7. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/_version.py +1 -1
  8. runloop_api_client-1.1.0/src/runloop_api_client/lib/__init__.py +3 -0
  9. runloop_api_client-1.1.0/src/runloop_api_client/lib/_ignore.py +496 -0
  10. runloop_api_client-1.1.0/src/runloop_api_client/lib/context_loader.py +78 -0
  11. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/sdk/__init__.py +19 -1
  12. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/sdk/_types.py +29 -0
  13. runloop_api_client-1.1.0/src/runloop_api_client/sdk/agent.py +72 -0
  14. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/sdk/async_.py +288 -12
  15. runloop_api_client-1.1.0/src/runloop_api_client/sdk/async_agent.py +76 -0
  16. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/sdk/async_devbox.py +1 -3
  17. runloop_api_client-1.1.0/src/runloop_api_client/sdk/async_scenario.py +118 -0
  18. runloop_api_client-1.1.0/src/runloop_api_client/sdk/async_scenario_run.py +242 -0
  19. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/sdk/async_storage_object.py +19 -2
  20. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/sdk/devbox.py +1 -3
  21. runloop_api_client-1.1.0/src/runloop_api_client/sdk/scenario.py +118 -0
  22. runloop_api_client-1.1.0/src/runloop_api_client/sdk/scenario_run.py +242 -0
  23. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/sdk/storage_object.py +19 -2
  24. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/sdk/sync.py +313 -11
  25. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/scenario_start_run_params.py +6 -4
  26. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/scoring_function.py +1 -1
  27. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/scoring_function_param.py +1 -1
  28. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/sdk/conftest.py +55 -5
  29. runloop_api_client-1.1.0/tests/sdk/test_agent.py +43 -0
  30. runloop_api_client-1.1.0/tests/sdk/test_async_agent.py +46 -0
  31. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/sdk/test_async_ops.py +474 -1
  32. runloop_api_client-1.1.0/tests/sdk/test_async_scenario.py +121 -0
  33. runloop_api_client-1.1.0/tests/sdk/test_async_scenario_run.py +162 -0
  34. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/sdk/test_ops.py +423 -3
  35. runloop_api_client-1.1.0/tests/sdk/test_scenario.py +121 -0
  36. runloop_api_client-1.1.0/tests/sdk/test_scenario_run.py +157 -0
  37. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/smoketests/sdk/README.md +25 -7
  38. runloop_api_client-1.1.0/tests/smoketests/sdk/test_agent.py +197 -0
  39. runloop_api_client-1.1.0/tests/smoketests/sdk/test_async_agent.py +203 -0
  40. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/smoketests/sdk/test_async_devbox.py +0 -28
  41. runloop_api_client-1.1.0/tests/smoketests/sdk/test_async_scenario.py +126 -0
  42. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/smoketests/sdk/test_async_storage_object.py +2 -1
  43. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/smoketests/sdk/test_devbox.py +0 -28
  44. runloop_api_client-1.1.0/tests/smoketests/sdk/test_scenario.py +126 -0
  45. runloop_api_client-1.1.0/tests/test_utils/test_context_loader.py +207 -0
  46. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/uv.lock +212 -113
  47. runloop_api_client-1.0.0/.release-please-manifest.json +0 -3
  48. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/.gitignore +0 -0
  49. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/LICENSE +0 -0
  50. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/README.md +0 -0
  51. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/SECURITY.md +0 -0
  52. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/api.md +0 -0
  53. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/bin/check-release-environment +0 -0
  54. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/bin/publish-pypi +0 -0
  55. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/examples/.keep +0 -0
  56. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/release-please-config.json +0 -0
  57. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/requirements-dev.lock +0 -0
  58. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop/lib/.keep +0 -0
  59. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/__init__.py +0 -0
  60. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/_base_client.py +0 -0
  61. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/_client.py +0 -0
  62. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/_compat.py +0 -0
  63. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/_constants.py +0 -0
  64. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/_exceptions.py +0 -0
  65. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/_files.py +0 -0
  66. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/_models.py +0 -0
  67. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/_qs.py +0 -0
  68. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/_resource.py +0 -0
  69. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/_response.py +0 -0
  70. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/_streaming.py +0 -0
  71. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/_types.py +0 -0
  72. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/_utils/__init__.py +0 -0
  73. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/_utils/_compat.py +0 -0
  74. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/_utils/_datetime_parse.py +0 -0
  75. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/_utils/_logs.py +0 -0
  76. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/_utils/_proxy.py +0 -0
  77. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/_utils/_reflection.py +0 -0
  78. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/_utils/_resources_proxy.py +0 -0
  79. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/_utils/_streams.py +0 -0
  80. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/_utils/_sync.py +0 -0
  81. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/_utils/_transform.py +0 -0
  82. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/_utils/_typing.py +0 -0
  83. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/_utils/_utils.py +0 -0
  84. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/_utils/_validation.py +0 -0
  85. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/lib/.keep +0 -0
  86. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/lib/polling.py +0 -0
  87. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/lib/polling_async.py +0 -0
  88. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/pagination.py +0 -0
  89. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/py.typed +0 -0
  90. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/resources/__init__.py +0 -0
  91. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/resources/agents.py +0 -0
  92. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/resources/benchmarks/__init__.py +0 -0
  93. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/resources/benchmarks/benchmarks.py +0 -0
  94. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/resources/benchmarks/runs.py +0 -0
  95. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/resources/blueprints.py +0 -0
  96. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/resources/devboxes/__init__.py +0 -0
  97. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/resources/devboxes/browsers.py +0 -0
  98. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/resources/devboxes/computers.py +0 -0
  99. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/resources/devboxes/devboxes.py +0 -0
  100. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/resources/devboxes/disk_snapshots.py +0 -0
  101. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/resources/devboxes/executions.py +0 -0
  102. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/resources/devboxes/logs.py +0 -0
  103. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/resources/objects.py +0 -0
  104. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/resources/repositories.py +0 -0
  105. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/resources/scenarios/__init__.py +0 -0
  106. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/resources/scenarios/runs.py +0 -0
  107. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/resources/scenarios/scenarios.py +0 -0
  108. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/resources/scenarios/scorers.py +0 -0
  109. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/resources/secrets.py +0 -0
  110. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/sdk/_helpers.py +0 -0
  111. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/sdk/async_blueprint.py +0 -0
  112. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/sdk/async_execution.py +0 -0
  113. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/sdk/async_execution_result.py +0 -0
  114. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/sdk/async_scorer.py +0 -0
  115. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/sdk/async_snapshot.py +0 -0
  116. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/sdk/blueprint.py +0 -0
  117. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/sdk/execution.py +0 -0
  118. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/sdk/execution_result.py +0 -0
  119. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/sdk/scorer.py +0 -0
  120. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/sdk/snapshot.py +0 -0
  121. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/__init__.py +0 -0
  122. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/agent_create_params.py +0 -0
  123. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/agent_list_params.py +0 -0
  124. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/agent_list_view.py +0 -0
  125. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/agent_view.py +0 -0
  126. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/benchmark_create_params.py +0 -0
  127. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/benchmark_definitions_params.py +0 -0
  128. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/benchmark_list_params.py +0 -0
  129. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/benchmark_list_public_params.py +0 -0
  130. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/benchmark_run_list_view.py +0 -0
  131. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/benchmark_run_view.py +0 -0
  132. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/benchmark_start_run_params.py +0 -0
  133. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/benchmark_update_params.py +0 -0
  134. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/benchmark_view.py +0 -0
  135. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/benchmarks/__init__.py +0 -0
  136. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/benchmarks/run_list_params.py +0 -0
  137. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/benchmarks/run_list_scenario_runs_params.py +0 -0
  138. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/blueprint_build_log.py +0 -0
  139. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/blueprint_build_logs_list_view.py +0 -0
  140. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/blueprint_build_parameters.py +0 -0
  141. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/blueprint_create_from_inspection_params.py +0 -0
  142. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/blueprint_create_params.py +0 -0
  143. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/blueprint_list_params.py +0 -0
  144. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/blueprint_list_public_params.py +0 -0
  145. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/blueprint_list_view.py +0 -0
  146. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/blueprint_preview_params.py +0 -0
  147. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/blueprint_preview_view.py +0 -0
  148. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/blueprint_view.py +0 -0
  149. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/devbox_async_execution_detail_view.py +0 -0
  150. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/devbox_create_params.py +0 -0
  151. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/devbox_create_ssh_key_response.py +0 -0
  152. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/devbox_create_tunnel_params.py +0 -0
  153. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/devbox_download_file_params.py +0 -0
  154. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/devbox_execute_async_params.py +0 -0
  155. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/devbox_execute_params.py +0 -0
  156. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/devbox_execute_sync_params.py +0 -0
  157. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/devbox_execution_detail_view.py +0 -0
  158. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/devbox_list_disk_snapshots_params.py +0 -0
  159. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/devbox_list_params.py +0 -0
  160. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/devbox_list_view.py +0 -0
  161. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/devbox_read_file_contents_params.py +0 -0
  162. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/devbox_read_file_contents_response.py +0 -0
  163. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/devbox_remove_tunnel_params.py +0 -0
  164. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/devbox_send_std_in_result.py +0 -0
  165. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/devbox_snapshot_disk_async_params.py +0 -0
  166. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/devbox_snapshot_disk_params.py +0 -0
  167. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/devbox_snapshot_list_view.py +0 -0
  168. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/devbox_snapshot_view.py +0 -0
  169. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/devbox_tunnel_view.py +0 -0
  170. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/devbox_update_params.py +0 -0
  171. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/devbox_upload_file_params.py +0 -0
  172. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/devbox_view.py +0 -0
  173. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/devbox_wait_for_command_params.py +0 -0
  174. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/devbox_write_file_contents_params.py +0 -0
  175. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/devboxes/__init__.py +0 -0
  176. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/devboxes/browser_create_params.py +0 -0
  177. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/devboxes/browser_view.py +0 -0
  178. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/devboxes/computer_create_params.py +0 -0
  179. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/devboxes/computer_keyboard_interaction_params.py +0 -0
  180. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/devboxes/computer_keyboard_interaction_response.py +0 -0
  181. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/devboxes/computer_mouse_interaction_params.py +0 -0
  182. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/devboxes/computer_mouse_interaction_response.py +0 -0
  183. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/devboxes/computer_screen_interaction_params.py +0 -0
  184. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/devboxes/computer_screen_interaction_response.py +0 -0
  185. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/devboxes/computer_view.py +0 -0
  186. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/devboxes/devbox_logs_list_view.py +0 -0
  187. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/devboxes/devbox_snapshot_async_status_view.py +0 -0
  188. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/devboxes/disk_snapshot_list_params.py +0 -0
  189. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/devboxes/disk_snapshot_update_params.py +0 -0
  190. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/devboxes/execution_execute_async_params.py +0 -0
  191. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/devboxes/execution_execute_sync_params.py +0 -0
  192. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/devboxes/execution_kill_params.py +0 -0
  193. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/devboxes/execution_retrieve_params.py +0 -0
  194. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/devboxes/execution_send_std_in_params.py +0 -0
  195. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/devboxes/execution_stream_stderr_updates_params.py +0 -0
  196. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/devboxes/execution_stream_stdout_updates_params.py +0 -0
  197. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/devboxes/execution_update_chunk.py +0 -0
  198. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/devboxes/log_list_params.py +0 -0
  199. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/input_context.py +0 -0
  200. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/input_context_param.py +0 -0
  201. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/input_context_update_param.py +0 -0
  202. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/inspection_source_param.py +0 -0
  203. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/object_create_params.py +0 -0
  204. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/object_download_params.py +0 -0
  205. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/object_download_url_view.py +0 -0
  206. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/object_list_params.py +0 -0
  207. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/object_list_public_params.py +0 -0
  208. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/object_list_view.py +0 -0
  209. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/object_view.py +0 -0
  210. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/repository_connection_list_view.py +0 -0
  211. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/repository_connection_view.py +0 -0
  212. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/repository_create_params.py +0 -0
  213. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/repository_inspect_params.py +0 -0
  214. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/repository_inspection_details.py +0 -0
  215. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/repository_inspection_list_view.py +0 -0
  216. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/repository_list_params.py +0 -0
  217. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/repository_manifest_view.py +0 -0
  218. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/repository_refresh_params.py +0 -0
  219. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/scenario_create_params.py +0 -0
  220. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/scenario_definition_list_view.py +0 -0
  221. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/scenario_environment.py +0 -0
  222. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/scenario_environment_param.py +0 -0
  223. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/scenario_list_params.py +0 -0
  224. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/scenario_list_public_params.py +0 -0
  225. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/scenario_run_list_view.py +0 -0
  226. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/scenario_run_view.py +0 -0
  227. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/scenario_update_params.py +0 -0
  228. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/scenario_view.py +0 -0
  229. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/scenarios/__init__.py +0 -0
  230. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/scenarios/run_list_params.py +0 -0
  231. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/scenarios/scorer_create_params.py +0 -0
  232. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/scenarios/scorer_create_response.py +0 -0
  233. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/scenarios/scorer_list_params.py +0 -0
  234. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/scenarios/scorer_list_response.py +0 -0
  235. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/scenarios/scorer_retrieve_response.py +0 -0
  236. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/scenarios/scorer_update_params.py +0 -0
  237. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/scenarios/scorer_update_response.py +0 -0
  238. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/scenarios/scorer_validate_params.py +0 -0
  239. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/scenarios/scorer_validate_response.py +0 -0
  240. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/scoring_contract.py +0 -0
  241. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/scoring_contract_param.py +0 -0
  242. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/scoring_contract_result_view.py +0 -0
  243. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/scoring_contract_update_param.py +0 -0
  244. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/scoring_function_result_view.py +0 -0
  245. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/secret_create_params.py +0 -0
  246. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/secret_list_params.py +0 -0
  247. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/secret_list_view.py +0 -0
  248. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/secret_update_params.py +0 -0
  249. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/secret_view.py +0 -0
  250. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/shared/__init__.py +0 -0
  251. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/shared/after_idle.py +0 -0
  252. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/shared/agent_mount_parameters.py +0 -0
  253. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/shared/agent_source.py +0 -0
  254. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/shared/code_mount_parameters.py +0 -0
  255. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/shared/launch_parameters.py +0 -0
  256. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/shared/mount.py +0 -0
  257. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/shared/object_mount_parameters.py +0 -0
  258. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/shared/run_profile.py +0 -0
  259. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/shared_params/__init__.py +0 -0
  260. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/shared_params/after_idle.py +0 -0
  261. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/shared_params/agent_mount_parameters.py +0 -0
  262. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/shared_params/agent_source.py +0 -0
  263. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/shared_params/code_mount_parameters.py +0 -0
  264. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/shared_params/launch_parameters.py +0 -0
  265. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/shared_params/mount.py +0 -0
  266. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/shared_params/object_mount_parameters.py +0 -0
  267. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/shared_params/run_profile.py +0 -0
  268. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/__init__.py +0 -0
  269. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/api_resources/__init__.py +0 -0
  270. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/api_resources/benchmarks/__init__.py +0 -0
  271. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/api_resources/benchmarks/test_runs.py +0 -0
  272. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/api_resources/devboxes/__init__.py +0 -0
  273. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/api_resources/devboxes/test_browsers.py +0 -0
  274. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/api_resources/devboxes/test_computers.py +0 -0
  275. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/api_resources/devboxes/test_disk_snapshots.py +0 -0
  276. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/api_resources/devboxes/test_executions.py +0 -0
  277. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/api_resources/devboxes/test_logs.py +0 -0
  278. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/api_resources/scenarios/__init__.py +0 -0
  279. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/api_resources/scenarios/test_runs.py +0 -0
  280. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/api_resources/scenarios/test_scorers.py +0 -0
  281. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/api_resources/test_agents.py +0 -0
  282. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/api_resources/test_benchmarks.py +0 -0
  283. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/api_resources/test_blueprints.py +0 -0
  284. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/api_resources/test_devboxes.py +0 -0
  285. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/api_resources/test_objects.py +0 -0
  286. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/api_resources/test_repositories.py +0 -0
  287. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/api_resources/test_scenarios.py +0 -0
  288. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/api_resources/test_secrets.py +0 -0
  289. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/conftest.py +0 -0
  290. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/sample_file.txt +0 -0
  291. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/sdk/__init__.py +0 -0
  292. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/sdk/async_devbox/__init__.py +0 -0
  293. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/sdk/async_devbox/conftest.py +0 -0
  294. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/sdk/async_devbox/test_core.py +0 -0
  295. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/sdk/async_devbox/test_edge_cases.py +0 -0
  296. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/sdk/async_devbox/test_interfaces.py +0 -0
  297. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/sdk/async_devbox/test_streaming.py +0 -0
  298. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/sdk/devbox/__init__.py +0 -0
  299. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/sdk/devbox/conftest.py +0 -0
  300. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/sdk/devbox/test_core.py +0 -0
  301. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/sdk/devbox/test_edge_cases.py +0 -0
  302. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/sdk/devbox/test_interfaces.py +0 -0
  303. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/sdk/devbox/test_streaming.py +0 -0
  304. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/sdk/test_async_blueprint.py +0 -0
  305. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/sdk/test_async_execution.py +0 -0
  306. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/sdk/test_async_execution_result.py +0 -0
  307. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/sdk/test_async_scorer.py +0 -0
  308. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/sdk/test_async_snapshot.py +0 -0
  309. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/sdk/test_async_storage_object.py +0 -0
  310. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/sdk/test_blueprint.py +0 -0
  311. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/sdk/test_execution.py +0 -0
  312. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/sdk/test_execution_result.py +0 -0
  313. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/sdk/test_helpers.py +0 -0
  314. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/sdk/test_scorer.py +0 -0
  315. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/sdk/test_snapshot.py +0 -0
  316. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/sdk/test_storage_object.py +0 -0
  317. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/smoketests/README.md +0 -0
  318. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/smoketests/__init__.py +0 -0
  319. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/smoketests/conftest.py +0 -0
  320. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/smoketests/sdk/__init__.py +0 -0
  321. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/smoketests/sdk/conftest.py +0 -0
  322. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/smoketests/sdk/test_async_blueprint.py +0 -0
  323. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/smoketests/sdk/test_async_scorer.py +0 -0
  324. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/smoketests/sdk/test_async_sdk.py +0 -0
  325. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/smoketests/sdk/test_async_snapshot.py +0 -0
  326. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/smoketests/sdk/test_blueprint.py +0 -0
  327. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/smoketests/sdk/test_scorer.py +0 -0
  328. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/smoketests/sdk/test_sdk.py +0 -0
  329. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/smoketests/sdk/test_snapshot.py +0 -0
  330. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/smoketests/sdk/test_storage_object.py +0 -0
  331. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/smoketests/test_blueprints.py +0 -0
  332. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/smoketests/test_devboxes.py +0 -0
  333. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/smoketests/test_executions.py +0 -0
  334. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/smoketests/test_scenarios_benchmarks.py +0 -0
  335. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/smoketests/test_snapshots.py +0 -0
  336. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/smoketests/utils.py +0 -0
  337. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/test_client.py +0 -0
  338. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/test_deepcopy.py +0 -0
  339. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/test_extract_files.py +0 -0
  340. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/test_files.py +0 -0
  341. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/test_models.py +0 -0
  342. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/test_polling.py +0 -0
  343. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/test_qs.py +0 -0
  344. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/test_required_args.py +0 -0
  345. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/test_response.py +0 -0
  346. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/test_streaming.py +0 -0
  347. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/test_transform.py +0 -0
  348. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/test_utils/test_datetime_parse.py +0 -0
  349. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/test_utils/test_proxy.py +0 -0
  350. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/test_utils/test_typing.py +0 -0
  351. {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/utils.py +0 -0
@@ -0,0 +1,3 @@
1
+ {
2
+ ".": "1.1.0"
3
+ }
@@ -1,5 +1,19 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.1.0 (2025-12-06)
4
+
5
+ Full Changelog: [v1.0.0...v1.1.0](https://github.com/runloopai/api-client-python/compare/v1.0.0...v1.1.0)
6
+
7
+ ### Features
8
+
9
+ * **scenarios:** added scenario class to sdk ([#701](https://github.com/runloopai/api-client-python/issues/701)) ([121f0fc](https://github.com/runloopai/api-client-python/commit/121f0fc6efa779979f664a75e91d60c068358e21))
10
+ * **SDK:** Build context helpers for the python clients and SDKs ([#684](https://github.com/runloopai/api-client-python/issues/684)) ([42849d6](https://github.com/runloopai/api-client-python/commit/42849d6834098d00234e5ab345ed0d91bac00435))
11
+
12
+
13
+ ### Chores
14
+
15
+ * **smoketests:** fixed smoketests and cleaned up typing/formatting ([#699](https://github.com/runloopai/api-client-python/issues/699)) ([f57aae7](https://github.com/runloopai/api-client-python/commit/f57aae71be8eb801214c012b2ec66b9414f0365e))
16
+
3
17
  ## 1.0.0 (2025-12-02)
4
18
 
5
19
  Full Changelog: [v0.69.0...v1.0.0](https://github.com/runloopai/api-client-python/compare/v0.69.0...v1.0.0)
@@ -89,13 +89,49 @@ Most tests require you to [set up a mock server](https://github.com/stoplightio/
89
89
 
90
90
  ```sh
91
91
  # you will need npm installed
92
- $ npx prism mock path/to/your/openapi.yml
92
+ npx prism mock path/to/your/openapi.yml
93
93
  ```
94
94
 
95
95
  ```sh
96
- $ ./scripts/test
96
+ # run all tests
97
+ ./scripts/test
98
+
99
+ # pass in pytest args, eg to show info on skipped tests:
100
+ ./scripts/test -rs
101
+
102
+ # Run tests for only one python version
103
+ UV_PYTHON=3.13 ./scripts/test
104
+ ```
105
+
106
+ ### Running pytets
107
+
108
+ Assuming you have a uv virtual env set up in .venv, the following are helpful for more granular test running:
109
+
110
+ ```sh
111
+ # Run all tests pytests
112
+ .venv/bin/pytest tests/
113
+
114
+ # Run all SDK tests with verbose info
115
+ .venv/bin/pytest tests/sdk/ -v
116
+
117
+ # Run specific test class
118
+ .venv/bin/pytest tests/sdk/test_clients.py::TestAgentClient -v
119
+
120
+ # Run specific test method
121
+ .venv/bin/pytest tests/sdk/test_clients.py::TestAgentClient::test_create_from_npm -v
122
+
123
+ # Run agent smoketests (requires RUNLOOP_API_KEY)
124
+ export RUNLOOP_API_KEY=your_key_here
125
+ .venv/bin/pytest tests/smoketests/sdk/test_agent.py -v
126
+
127
+ # Run tests matching a pattern
128
+ .venv/bin/pytest tests/sdk/ -k "agent" -v
129
+
130
+ # Run with coverage
131
+ .venv/bin/pytest tests/sdk/ --cov=src/runloop_api_client/sdk --cov-report=html
97
132
  ```
98
133
 
134
+
99
135
  ## Linting and formatting
100
136
 
101
137
  This repository uses [ruff](https://github.com/astral-sh/ruff) and
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: runloop_api_client
3
- Version: 1.0.0
3
+ Version: 1.1.0
4
4
  Summary: The official Python library for the runloop API
5
5
  Project-URL: Homepage, https://github.com/runloopai/api-client-python
6
6
  Project-URL: Repository, https://github.com/runloopai/api-client-python
@@ -8,11 +8,23 @@ The `RunloopSDK` builds on top of the underlying REST client and provides a Pyth
8
8
  - [Quickstart (synchronous)](#quickstart-synchronous)
9
9
  - [Quickstart (asynchronous)](#quickstart-asynchronous)
10
10
  - [Core Concepts](#core-concepts)
11
- - [Devbox](#devbox)
12
- - [Blueprint](#blueprint)
13
- - [Snapshot](#snapshot)
14
- - [StorageObject](#storageobject)
15
- - [Mounting Storage Objects to Devboxes](#mounting-storage-objects-to-devboxes)
11
+ - [RunloopSDK](#runloopsdk)
12
+ - [Available Resources](#available-resources)
13
+ - [Devbox](#devbox)
14
+ - [Command Execution](#command-execution)
15
+ - [Execution Management](#execution-management)
16
+ - [Execution Results](#execution-results)
17
+ - [Streaming Command Output](#streaming-command-output)
18
+ - [File Operations](#file-operations)
19
+ - [Network Operations](#network-operations)
20
+ - [Snapshot Operations](#snapshot-operations)
21
+ - [Devbox Lifecycle Management](#devbox-lifecycle-management)
22
+ - [Context Manager Support](#context-manager-support)
23
+ - [Blueprint](#blueprint)
24
+ - [Snapshot](#snapshot)
25
+ - [StorageObject](#storageobject)
26
+ - [Storage Object Upload Helpers](#storage-object-upload-helpers)
27
+ - [Mounting Storage Objects to Devboxes](#mounting-storage-objects-to-devboxes)
16
28
  - [Accessing the Underlying REST Client](#accessing-the-underlying-rest-client)
17
29
  - [Error Handling](#error-handling)
18
30
  - [Advanced Configuration](#advanced-configuration)
@@ -409,6 +421,52 @@ blueprint = runloop.blueprint.create(
409
421
  system_setup_commands=["pip install numpy pandas"],
410
422
  )
411
423
 
424
+ # Or create a blueprint with a Docker build context from a local directory
425
+ from pathlib import Path
426
+ from runloop_api_client.lib.context_loader import build_docker_context_tar
427
+
428
+ context_root = Path("./my-app")
429
+ tar_bytes = build_docker_context_tar(context_root)
430
+
431
+ build_ctx_obj = runloop.storage_object.upload_from_bytes(
432
+ data=tar_bytes,
433
+ name="my-app-context.tar.gz",
434
+ content_type="tgz",
435
+ )
436
+
437
+ shared_root = Path("./shared-lib")
438
+ shared_tar = build_docker_context_tar(shared_root)
439
+
440
+ shared_ctx_obj = runloop.storage_object.upload_from_bytes(
441
+ data=shared_tar,
442
+ name="shared-lib-context.tar.gz",
443
+ content_type="tgz",
444
+ )
445
+
446
+ blueprint_with_context = runloop.blueprint.create(
447
+ name="my-blueprint-with-context",
448
+ dockerfile="""\
449
+ FROM node:22
450
+ WORKDIR /usr/src/app
451
+
452
+ # copy using the build context from the object
453
+ COPY package.json package.json
454
+ COPY src src
455
+
456
+ # copy from named context
457
+ COPY --from=shared / ./libs
458
+
459
+ RUN npm install --only=production
460
+ CMD ["node", "src/app.js"]
461
+ """,
462
+ # Primary build context
463
+ build_context=build_ctx_obj.as_build_context(),
464
+ # Additional named build contexts (for Docker buildx-style usage)
465
+ named_build_contexts={
466
+ "shared": shared_ctx_obj.as_build_context(),
467
+ },
468
+ )
469
+
412
470
  # Or get an existing one
413
471
  blueprint = runloop.blueprint.from_id(blueprint_id="bpt_123")
414
472
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "runloop_api_client"
3
- version = "1.0.0"
3
+ version = "1.1.0"
4
4
  description = "The official Python library for the runloop API"
5
5
  dynamic = ["readme"]
6
6
  license = "MIT"
@@ -1,4 +1,4 @@
1
1
  # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2
2
 
3
3
  __title__ = "runloop_api_client"
4
- __version__ = "1.0.0" # x-release-please-version
4
+ __version__ = "1.1.0" # x-release-please-version
@@ -0,0 +1,3 @@
1
+ """
2
+ Helpers for `runloop_api_client`.
3
+ """
@@ -0,0 +1,496 @@
1
+ from __future__ import annotations
2
+
3
+ import os
4
+ from abc import ABC, abstractmethod
5
+ from typing import Iterable, Optional, Sequence
6
+ from pathlib import Path, PurePosixPath
7
+ from dataclasses import dataclass
8
+ from typing_extensions import override
9
+
10
+ __all__ = [
11
+ "IgnorePattern",
12
+ "IgnoreMatcher",
13
+ "DockerIgnoreMatcher",
14
+ "FilePatternMatcher",
15
+ "read_ignorefile",
16
+ "compile_ignore",
17
+ "path_match",
18
+ "is_ignored",
19
+ "iter_included_files",
20
+ ]
21
+
22
+
23
+ @dataclass(frozen=True)
24
+ class IgnorePattern:
25
+ """Single parsed ignore pattern.
26
+
27
+ Follows Docker-style ``.dockerignore`` semantics and supports other ignore
28
+ use cases following the same approach.
29
+ """
30
+
31
+ pattern: str
32
+ """The normalized pattern text with leading and trailing ``/`` removed.
33
+
34
+ Always uses POSIX ``'/'`` separators.
35
+ """
36
+
37
+ negated: bool
38
+ """Whether this is a negation pattern starting with ``!``."""
39
+
40
+ directory_only: bool
41
+ """Whether the original pattern ended with ``/`` and should apply only to
42
+ directories and their descendants.
43
+ """
44
+
45
+ anchored: bool
46
+ """Whether the pattern contains a path separator and should be matched
47
+ relative to the root path rather than at any depth.
48
+ """
49
+
50
+
51
+ def _normalize_pattern_string(raw: str) -> str:
52
+ """Normalize a single ignore pattern string.
53
+
54
+ Shared helper for patterns coming from both ignorefiles and inline pattern
55
+ lists. Handles:
56
+
57
+ - Optional leading ``!`` negation marker (with surrounding whitespace
58
+ trimmed).
59
+ - ``os.path.normpath`` cleanup.
60
+ - Normalising path separators to POSIX ``'/'``.
61
+ - Stripping a single leading ``/`` so absolute-style patterns behave like
62
+ relative ones.
63
+
64
+ Comment / blank-line handling is deliberately *not* included here; callers
65
+ are responsible for that.
66
+ """
67
+
68
+ if not raw:
69
+ return raw
70
+
71
+ invert = raw[0] == "!"
72
+ pattern = raw[1:].strip() if invert else raw.strip()
73
+
74
+ if pattern:
75
+ # filepath.Clean equivalent
76
+ pattern = os.path.normpath(pattern)
77
+ # filepath.ToSlash equivalent
78
+ pattern = pattern.replace(os.sep, "/")
79
+ # Leading forward-slashes are removed so "/some/path" and "some/path"
80
+ # are considered equivalent.
81
+ if len(pattern) > 1 and pattern[0] == "/":
82
+ pattern = pattern[1:]
83
+
84
+ if invert:
85
+ pattern = "!" + pattern
86
+
87
+ return pattern
88
+
89
+
90
+ def _normalize_pattern_line(raw: bytes, *, is_first_line: bool) -> Optional[str]:
91
+ """Normalize a single ignorefile line, mirroring moby's ignorefile.ReadAll.
92
+
93
+ Behavior is based on:
94
+ https://github.com/moby/patternmatcher/blob/main/ignorefile/ignorefile.go
95
+
96
+ :param raw: Raw line bytes from the ignore file, including any newline
97
+ characters.
98
+ :type raw: bytes
99
+ :param is_first_line: Whether this is the first line in the file (used to
100
+ detect and strip a UTF-8 BOM).
101
+ :type is_first_line: bool
102
+ :return: Normalized pattern string, or ``None`` if the line should be
103
+ ignored (empty or comment).
104
+ :rtype: Optional[str]
105
+ """
106
+
107
+ # Strip UTF-8 BOM from the first line if present
108
+ if is_first_line and raw.startswith(b"\xef\xbb\xbf"):
109
+ raw = raw[len(b"\xef\xbb\xbf") :]
110
+
111
+ # Decode as UTF-8; we are strict here to surface bad encodings
112
+ text = raw.decode("utf-8", errors="strict")
113
+ text = text.rstrip("\r\n")
114
+
115
+ # Lines starting with '#' are comments and are ignored before processing,
116
+ # i.e. we do *not* treat leading spaces as part of the comment detection.
117
+ if text.startswith("#"):
118
+ return None
119
+
120
+ # Trim leading and trailing whitespace
121
+ pattern = text.strip()
122
+ if not pattern:
123
+ return None
124
+
125
+ normalized = _normalize_pattern_string(pattern)
126
+ return normalized or None
127
+
128
+
129
+ def read_ignorefile(path: Path) -> list[str]:
130
+ """Read an ignore file and return a list of normalized pattern strings.
131
+
132
+ This mirrors the behavior of moby's ``ignorefile.ReadAll``:
133
+
134
+ - UTF-8 BOM on the first line is stripped.
135
+ - Lines starting with ``#`` are treated as comments and skipped.
136
+ - Remaining lines are trimmed, optionally negated with ``!``, cleaned,
137
+ have path separators normalized to ``/``, and leading and trailing ``/`` removed.
138
+
139
+ :param path: Filesystem path to the ignore file to read.
140
+ :type path: Path
141
+ :return: List of normalized pattern strings in the order they appear in
142
+ the ignore file.
143
+ :rtype: list[str]
144
+ """
145
+
146
+ if not path.exists():
147
+ return []
148
+
149
+ patterns: list[str] = []
150
+ with path.open("rb") as f:
151
+ first = True
152
+ for raw in f:
153
+ normalized = _normalize_pattern_line(raw, is_first_line=first)
154
+ first = False
155
+ if normalized is None:
156
+ continue
157
+ patterns.append(normalized)
158
+
159
+ return patterns
160
+
161
+
162
+ def compile_ignore(patterns: Sequence[str]) -> list[IgnorePattern]:
163
+ """Compile raw pattern strings into :class:`IgnorePattern` objects.
164
+
165
+ :param patterns: Raw pattern strings following Docker-style semantics.
166
+ :type patterns: Sequence[str]
167
+ :return: Compiled ignore patterns.
168
+ :rtype: list[IgnorePattern]
169
+ """
170
+
171
+ compiled: list[IgnorePattern] = []
172
+
173
+ for raw in patterns:
174
+ if not raw:
175
+ continue
176
+
177
+ negated = raw[0] == "!"
178
+ pattern_text = raw[1:] if negated else raw
179
+
180
+ if not pattern_text:
181
+ # Bare "!" is ignored, matching Docker / moby behavior.
182
+ continue
183
+
184
+ directory_only = pattern_text.endswith("/")
185
+ if directory_only:
186
+ pattern_text = pattern_text.rstrip("/")
187
+
188
+ if not pattern_text:
189
+ continue
190
+
191
+ # Treat patterns containing a path separator as anchored to the root
192
+ anchored = "/" in pattern_text
193
+
194
+ compiled.append(
195
+ IgnorePattern(
196
+ pattern=PurePosixPath(pattern_text).as_posix(),
197
+ negated=negated,
198
+ directory_only=directory_only,
199
+ anchored=anchored,
200
+ )
201
+ )
202
+
203
+ return compiled
204
+
205
+
206
+ def _segment_match(pattern_segment: str, path_segment: str) -> bool:
207
+ """Match a single path segment against a glob pattern segment.
208
+
209
+ Supports:
210
+
211
+ - ``*``: any sequence of characters except ``/``.
212
+ - ``?``: any single character except ``/``.
213
+ - ``[]``: character classes, excluding ``/``.
214
+
215
+ :param pattern_segment: Glob-style pattern segment.
216
+ :type pattern_segment: str
217
+ :param path_segment: Path segment (no ``/``) to match against.
218
+ :type path_segment: str
219
+ :return: ``True`` if the path segment matches the pattern segment.
220
+ :rtype: bool
221
+ """
222
+
223
+ import re
224
+
225
+ escaped = ""
226
+ i = 0
227
+ while i < len(pattern_segment):
228
+ ch = pattern_segment[i]
229
+ if ch == "*":
230
+ escaped += "[^/]*"
231
+ elif ch == "?":
232
+ escaped += "[^/]"
233
+ elif ch == "[":
234
+ # Copy character class as-is until closing ']'.
235
+ j = i + 1
236
+ while j < len(pattern_segment) and pattern_segment[j] != "]":
237
+ j += 1
238
+ if j < len(pattern_segment):
239
+ escaped += pattern_segment[i : j + 1]
240
+ i = j
241
+ else:
242
+ # Unterminated '['; treat it literally.
243
+ escaped += re.escape(ch)
244
+ else:
245
+ escaped += re.escape(ch)
246
+ i += 1
247
+
248
+ regex = re.compile(rf"^{escaped}$")
249
+ return regex.match(path_segment) is not None
250
+
251
+
252
+ def _match_parts_recursive(pattern_parts: list[str], path_parts: list[str]) -> bool:
253
+ """Recursive helper implementing ``**`` segment semantics.
254
+
255
+ :param pattern_parts: Pattern split into POSIX path segments.
256
+ :type pattern_parts: list[str]
257
+ :param path_parts: Path split into POSIX path segments.
258
+ :type path_parts: list[str]
259
+ :return: ``True`` if the pattern parts match the path parts.
260
+ :rtype: bool
261
+ """
262
+
263
+ if not pattern_parts:
264
+ return not path_parts
265
+
266
+ if pattern_parts[0] == "**":
267
+ # '**' matches zero or more segments.
268
+ for i in range(len(path_parts) + 1):
269
+ if _match_parts_recursive(pattern_parts[1:], path_parts[i:]):
270
+ return True
271
+ return False
272
+
273
+ if not path_parts:
274
+ return False
275
+
276
+ if not _segment_match(pattern_parts[0], path_parts[0]):
277
+ return False
278
+
279
+ return _match_parts_recursive(pattern_parts[1:], path_parts[1:])
280
+
281
+
282
+ def path_match(pattern: IgnorePattern, relpath: str, *, is_dir: bool) -> bool:
283
+ """Return ``True`` if ``relpath`` matches a compiled ignore pattern.
284
+
285
+ :param pattern: Compiled ignore pattern to test.
286
+ :type pattern: IgnorePattern
287
+ :param relpath: Path to test, relative to the ignore root.
288
+ :type relpath: str
289
+ :param is_dir: Whether ``relpath`` refers to a directory.
290
+ :type is_dir: bool
291
+ :return: ``True`` if the path is matched by the pattern.
292
+ :rtype: bool
293
+ """
294
+
295
+ relpath_posix = PurePosixPath(relpath).as_posix()
296
+ path_parts = PurePosixPath(relpath_posix).parts
297
+ pattern_parts = PurePosixPath(pattern.pattern).parts
298
+
299
+ # Directory-only patterns never directly match files here; the effect on
300
+ # descendants is enforced by directory pruning in the traversal.
301
+ if pattern.directory_only and not is_dir:
302
+ return False
303
+
304
+ if pattern.anchored:
305
+ return _match_parts_recursive(list(pattern_parts), list(path_parts))
306
+
307
+ for start in range(len(path_parts)):
308
+ if _match_parts_recursive(list(pattern_parts), list(path_parts[start:])):
309
+ return True
310
+ return False
311
+
312
+
313
+ def is_ignored(relpath: str, *, is_dir: bool, patterns: Sequence[IgnorePattern]) -> bool:
314
+ """Apply ignore patterns with 'last match wins' semantics.
315
+
316
+ Examples::
317
+
318
+ *.log
319
+ !important.log
320
+
321
+ excludes all ``.log`` files except ``important.log``. Patterns are applied
322
+ in order, and the last matching pattern determines inclusion.
323
+
324
+ :param relpath: Path to evaluate, relative to the ignore root.
325
+ :type relpath: str
326
+ :param is_dir: Whether ``relpath`` refers to a directory.
327
+ :type is_dir: bool
328
+ :param patterns: Compiled ignore patterns to apply in order.
329
+ :type patterns: Sequence[IgnorePattern]
330
+ :return: ``True`` if the path should be treated as ignored.
331
+ :rtype: bool
332
+ """
333
+
334
+ included = True # include by default
335
+ for pat in patterns:
336
+ if path_match(pat, relpath, is_dir=is_dir):
337
+ included = pat.negated
338
+ return not included
339
+
340
+
341
+ def iter_included_files(
342
+ root: Path,
343
+ *,
344
+ patterns: Sequence[IgnorePattern],
345
+ ) -> Iterable[Path]:
346
+ """Yield all files under ``root`` that are not ignored.
347
+
348
+ This performs directory pruning so that ignored directories are never
349
+ traversed, mirroring Docker's behavior for ``.dockerignore``.
350
+
351
+ :param root: Root directory to walk.
352
+ :type root: Path
353
+ :param patterns: Compiled ignore patterns controlling which files and
354
+ directories are included.
355
+ :type patterns: Sequence[IgnorePattern]
356
+ :return: Iterator over non-ignored file paths under ``root``.
357
+ :rtype: Iterable[Path]
358
+ """
359
+
360
+ if not root.is_dir():
361
+ raise ValueError(f"root must be a directory, got: {root}")
362
+
363
+ for dirpath, dirs, files in os.walk(root):
364
+ dir_path = Path(dirpath)
365
+
366
+ # Prune ignored directories
367
+ for name in list(dirs):
368
+ subdir = dir_path / name
369
+ rel_dir = subdir.relative_to(root).as_posix()
370
+ if is_ignored(rel_dir, is_dir=True, patterns=patterns):
371
+ dirs.remove(name)
372
+
373
+ # Yield non-ignored files
374
+ for name in files:
375
+ file_path = dir_path / name
376
+ rel_file = file_path.relative_to(root).as_posix()
377
+ if is_ignored(rel_file, is_dir=False, patterns=patterns):
378
+ continue
379
+ yield file_path
380
+
381
+
382
+ class IgnoreMatcher(ABC):
383
+ """Abstract interface for ignore matchers like .dockerignore and .gitignore.
384
+
385
+ There is considerable variation for each ignore file format, so this interface
386
+ provides a minimal contract for supporting each format. Implementations are
387
+ responsible for interpreting any underlying ignore configuration (files, inline
388
+ patterns, etc.) and returning all files that should be included under a given
389
+ root directory.
390
+ """
391
+
392
+ @abstractmethod
393
+ def iter_paths(self, root: Path) -> Iterable[Path]:
394
+ """Yield filesystem paths to include under ``root``.
395
+
396
+ :param root: Root directory to scan for files.
397
+ :type root: Path
398
+ :return: Iterator over filesystem paths that should be included.
399
+ :rtype: Iterable[Path]
400
+ """
401
+
402
+
403
+ @dataclass(frozen=True)
404
+ class DockerIgnoreMatcher(IgnoreMatcher):
405
+ """Ignore matcher that mirrors Docker's .dockerignore semantics.
406
+
407
+ This matcher:
408
+
409
+ - Closely follows Docker's ``.dockerignore`` semantics.
410
+ - Always loads patterns from ``.dockerignore`` in the provided context
411
+ root, if present.
412
+ - Optionally loads additional patterns from an extra ignorefile.
413
+ - Optionally appends inline pattern strings.
414
+
415
+ Note: Patterns follow Docker-style semantics (``!`` negation, ``**`` support).
416
+ """
417
+
418
+ extra_ignorefile: str | Path | None = None
419
+ """Optional path to an additional ignorefile whose patterns are appended
420
+ after the default ``.dockerignore``.
421
+ """
422
+
423
+ patterns: Sequence[str] | None = None
424
+ """Optional inline pattern strings appended after any ignorefiles."""
425
+
426
+ @override
427
+ def iter_paths(self, root: Path) -> Iterable[Path]:
428
+ """Yield non-ignored files under ``root`` honoring Docker-style patterns.
429
+
430
+ :param root: Context directory whose contents should be filtered.
431
+ :type root: Path
432
+ :return: Iterator over non-ignored file paths under ``root``.
433
+ :rtype: Iterable[Path]
434
+ """
435
+ root = root.resolve()
436
+
437
+ all_patterns: list[str] = []
438
+
439
+ # 1) Always consider .dockerignore under the context root, if present.
440
+ default_ignorefile = root / ".dockerignore"
441
+ all_patterns.extend(read_ignorefile(default_ignorefile))
442
+
443
+ # 2) Optional additional ignorefile.
444
+ if self.extra_ignorefile is not None:
445
+ ignore_path = Path(self.extra_ignorefile)
446
+ if not ignore_path.exists():
447
+ raise FileNotFoundError(f"Ignore file does not exist: {ignore_path}")
448
+ all_patterns.extend(read_ignorefile(ignore_path))
449
+
450
+ # 3) Optional inline patterns appended last using same rules as .dockerignore
451
+ # Some extra handling here for trailing slashes that is different from .gitignore.
452
+ if self.patterns:
453
+ for raw in self.patterns:
454
+ if not raw:
455
+ continue
456
+ normalized = _normalize_pattern_string(raw)
457
+ if normalized:
458
+ all_patterns.append(normalized)
459
+
460
+ compiled: list[IgnorePattern] = compile_ignore(all_patterns)
461
+ return iter_included_files(root, patterns=compiled)
462
+
463
+
464
+ @dataclass(frozen=True)
465
+ class FilePatternMatcher(IgnoreMatcher):
466
+ """Ignore matcher that applies only inline patterns, without .dockerignore.
467
+
468
+ Patterns follow the same semantics as :func:`compile_ignore` / Docker-style
469
+ ignore files and are treated as *ignore* rules (``!`` negation for
470
+ re-inclusion, ``**`` support, etc.).
471
+
472
+ The constructor accepts either a single pattern string or a sequence of
473
+ pattern strings; a single string is automatically wrapped into a list.
474
+ """
475
+
476
+ patterns: Sequence[str] | str
477
+ """Pattern or patterns to apply as ignore rules when matching files."""
478
+
479
+ def __post_init__(self) -> None:
480
+ # Normalise a single pattern string into a list for downstream helpers.
481
+ if isinstance(self.patterns, str):
482
+ object.__setattr__(self, "patterns", [self.patterns])
483
+
484
+ @override
485
+ def iter_paths(self, root: Path) -> Iterable[Path]:
486
+ """Yield non-ignored files under ``root`` based only on ``patterns``.
487
+
488
+ :param root: Root directory whose contents should be filtered.
489
+ :type root: Path
490
+ :return: Iterator over non-ignored file paths under ``root``.
491
+ :rtype: Iterable[Path]
492
+ """
493
+
494
+ root = root.resolve()
495
+ compiled: list[IgnorePattern] = compile_ignore(self.patterns) # type: ignore[arg-type]
496
+ return iter_included_files(root, patterns=compiled)