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.
- runloop_api_client-1.1.0/.release-please-manifest.json +3 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/CHANGELOG.md +14 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/CONTRIBUTING.md +38 -2
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/PKG-INFO +1 -1
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/README-SDK.md +63 -5
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/pyproject.toml +1 -1
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/_version.py +1 -1
- runloop_api_client-1.1.0/src/runloop_api_client/lib/__init__.py +3 -0
- runloop_api_client-1.1.0/src/runloop_api_client/lib/_ignore.py +496 -0
- runloop_api_client-1.1.0/src/runloop_api_client/lib/context_loader.py +78 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/sdk/__init__.py +19 -1
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/sdk/_types.py +29 -0
- runloop_api_client-1.1.0/src/runloop_api_client/sdk/agent.py +72 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/sdk/async_.py +288 -12
- runloop_api_client-1.1.0/src/runloop_api_client/sdk/async_agent.py +76 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/sdk/async_devbox.py +1 -3
- runloop_api_client-1.1.0/src/runloop_api_client/sdk/async_scenario.py +118 -0
- runloop_api_client-1.1.0/src/runloop_api_client/sdk/async_scenario_run.py +242 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/sdk/async_storage_object.py +19 -2
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/sdk/devbox.py +1 -3
- runloop_api_client-1.1.0/src/runloop_api_client/sdk/scenario.py +118 -0
- runloop_api_client-1.1.0/src/runloop_api_client/sdk/scenario_run.py +242 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/sdk/storage_object.py +19 -2
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/sdk/sync.py +313 -11
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/scenario_start_run_params.py +6 -4
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/scoring_function.py +1 -1
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/scoring_function_param.py +1 -1
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/sdk/conftest.py +55 -5
- runloop_api_client-1.1.0/tests/sdk/test_agent.py +43 -0
- runloop_api_client-1.1.0/tests/sdk/test_async_agent.py +46 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/sdk/test_async_ops.py +474 -1
- runloop_api_client-1.1.0/tests/sdk/test_async_scenario.py +121 -0
- runloop_api_client-1.1.0/tests/sdk/test_async_scenario_run.py +162 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/sdk/test_ops.py +423 -3
- runloop_api_client-1.1.0/tests/sdk/test_scenario.py +121 -0
- runloop_api_client-1.1.0/tests/sdk/test_scenario_run.py +157 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/smoketests/sdk/README.md +25 -7
- runloop_api_client-1.1.0/tests/smoketests/sdk/test_agent.py +197 -0
- runloop_api_client-1.1.0/tests/smoketests/sdk/test_async_agent.py +203 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/smoketests/sdk/test_async_devbox.py +0 -28
- runloop_api_client-1.1.0/tests/smoketests/sdk/test_async_scenario.py +126 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/smoketests/sdk/test_async_storage_object.py +2 -1
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/smoketests/sdk/test_devbox.py +0 -28
- runloop_api_client-1.1.0/tests/smoketests/sdk/test_scenario.py +126 -0
- runloop_api_client-1.1.0/tests/test_utils/test_context_loader.py +207 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/uv.lock +212 -113
- runloop_api_client-1.0.0/.release-please-manifest.json +0 -3
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/.gitignore +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/LICENSE +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/README.md +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/SECURITY.md +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/api.md +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/bin/check-release-environment +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/bin/publish-pypi +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/examples/.keep +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/release-please-config.json +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/requirements-dev.lock +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop/lib/.keep +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/__init__.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/_base_client.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/_client.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/_compat.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/_constants.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/_exceptions.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/_files.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/_models.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/_qs.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/_resource.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/_response.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/_streaming.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/_types.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/_utils/__init__.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/_utils/_compat.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/_utils/_datetime_parse.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/_utils/_logs.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/_utils/_proxy.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/_utils/_reflection.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/_utils/_resources_proxy.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/_utils/_streams.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/_utils/_sync.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/_utils/_transform.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/_utils/_typing.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/_utils/_utils.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/_utils/_validation.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/lib/.keep +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/lib/polling.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/lib/polling_async.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/pagination.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/py.typed +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/resources/__init__.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/resources/agents.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/resources/benchmarks/__init__.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/resources/benchmarks/benchmarks.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/resources/benchmarks/runs.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/resources/blueprints.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/resources/devboxes/__init__.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/resources/devboxes/browsers.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/resources/devboxes/computers.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/resources/devboxes/devboxes.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/resources/devboxes/disk_snapshots.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/resources/devboxes/executions.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/resources/devboxes/logs.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/resources/objects.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/resources/repositories.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/resources/scenarios/__init__.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/resources/scenarios/runs.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/resources/scenarios/scenarios.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/resources/scenarios/scorers.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/resources/secrets.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/sdk/_helpers.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/sdk/async_blueprint.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/sdk/async_execution.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/sdk/async_execution_result.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/sdk/async_scorer.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/sdk/async_snapshot.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/sdk/blueprint.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/sdk/execution.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/sdk/execution_result.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/sdk/scorer.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/sdk/snapshot.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/__init__.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/agent_create_params.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/agent_list_params.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/agent_list_view.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/agent_view.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/benchmark_create_params.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/benchmark_definitions_params.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/benchmark_list_params.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/benchmark_list_public_params.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/benchmark_run_list_view.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/benchmark_run_view.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/benchmark_start_run_params.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/benchmark_update_params.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/benchmark_view.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/benchmarks/__init__.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/benchmarks/run_list_params.py +0 -0
- {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
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/blueprint_build_log.py +0 -0
- {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
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/blueprint_build_parameters.py +0 -0
- {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
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/blueprint_create_params.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/blueprint_list_params.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/blueprint_list_public_params.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/blueprint_list_view.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/blueprint_preview_params.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/blueprint_preview_view.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/blueprint_view.py +0 -0
- {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
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/devbox_create_params.py +0 -0
- {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
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/devbox_create_tunnel_params.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/devbox_download_file_params.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/devbox_execute_async_params.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/devbox_execute_params.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/devbox_execute_sync_params.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/devbox_execution_detail_view.py +0 -0
- {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
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/devbox_list_params.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/devbox_list_view.py +0 -0
- {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
- {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
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/devbox_remove_tunnel_params.py +0 -0
- {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
- {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
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/devbox_snapshot_disk_params.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/devbox_snapshot_list_view.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/devbox_snapshot_view.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/devbox_tunnel_view.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/devbox_update_params.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/devbox_upload_file_params.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/devbox_view.py +0 -0
- {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
- {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
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/devboxes/__init__.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/devboxes/browser_create_params.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/devboxes/browser_view.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/devboxes/computer_create_params.py +0 -0
- {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
- {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
- {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
- {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
- {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
- {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
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/devboxes/computer_view.py +0 -0
- {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
- {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
- {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
- {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
- {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
- {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
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/devboxes/execution_kill_params.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/devboxes/execution_retrieve_params.py +0 -0
- {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
- {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
- {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
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/devboxes/execution_update_chunk.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/devboxes/log_list_params.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/input_context.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/input_context_param.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/input_context_update_param.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/inspection_source_param.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/object_create_params.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/object_download_params.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/object_download_url_view.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/object_list_params.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/object_list_public_params.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/object_list_view.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/object_view.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/repository_connection_list_view.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/repository_connection_view.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/repository_create_params.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/repository_inspect_params.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/repository_inspection_details.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/repository_inspection_list_view.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/repository_list_params.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/repository_manifest_view.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/repository_refresh_params.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/scenario_create_params.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/scenario_definition_list_view.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/scenario_environment.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/scenario_environment_param.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/scenario_list_params.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/scenario_list_public_params.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/scenario_run_list_view.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/scenario_run_view.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/scenario_update_params.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/scenario_view.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/scenarios/__init__.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/scenarios/run_list_params.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/scenarios/scorer_create_params.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/scenarios/scorer_create_response.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/scenarios/scorer_list_params.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/scenarios/scorer_list_response.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/scenarios/scorer_retrieve_response.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/scenarios/scorer_update_params.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/scenarios/scorer_update_response.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/scenarios/scorer_validate_params.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/scenarios/scorer_validate_response.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/scoring_contract.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/scoring_contract_param.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/scoring_contract_result_view.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/scoring_contract_update_param.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/scoring_function_result_view.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/secret_create_params.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/secret_list_params.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/secret_list_view.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/secret_update_params.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/secret_view.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/shared/__init__.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/shared/after_idle.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/shared/agent_mount_parameters.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/shared/agent_source.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/shared/code_mount_parameters.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/shared/launch_parameters.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/shared/mount.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/shared/object_mount_parameters.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/shared/run_profile.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/shared_params/__init__.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/shared_params/after_idle.py +0 -0
- {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
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/shared_params/agent_source.py +0 -0
- {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
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/shared_params/launch_parameters.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/shared_params/mount.py +0 -0
- {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
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/src/runloop_api_client/types/shared_params/run_profile.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/__init__.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/api_resources/__init__.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/api_resources/benchmarks/__init__.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/api_resources/benchmarks/test_runs.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/api_resources/devboxes/__init__.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/api_resources/devboxes/test_browsers.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/api_resources/devboxes/test_computers.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/api_resources/devboxes/test_disk_snapshots.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/api_resources/devboxes/test_executions.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/api_resources/devboxes/test_logs.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/api_resources/scenarios/__init__.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/api_resources/scenarios/test_runs.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/api_resources/scenarios/test_scorers.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/api_resources/test_agents.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/api_resources/test_benchmarks.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/api_resources/test_blueprints.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/api_resources/test_devboxes.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/api_resources/test_objects.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/api_resources/test_repositories.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/api_resources/test_scenarios.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/api_resources/test_secrets.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/conftest.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/sample_file.txt +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/sdk/__init__.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/sdk/async_devbox/__init__.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/sdk/async_devbox/conftest.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/sdk/async_devbox/test_core.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/sdk/async_devbox/test_edge_cases.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/sdk/async_devbox/test_interfaces.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/sdk/async_devbox/test_streaming.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/sdk/devbox/__init__.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/sdk/devbox/conftest.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/sdk/devbox/test_core.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/sdk/devbox/test_edge_cases.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/sdk/devbox/test_interfaces.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/sdk/devbox/test_streaming.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/sdk/test_async_blueprint.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/sdk/test_async_execution.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/sdk/test_async_execution_result.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/sdk/test_async_scorer.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/sdk/test_async_snapshot.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/sdk/test_async_storage_object.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/sdk/test_blueprint.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/sdk/test_execution.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/sdk/test_execution_result.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/sdk/test_helpers.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/sdk/test_scorer.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/sdk/test_snapshot.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/sdk/test_storage_object.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/smoketests/README.md +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/smoketests/__init__.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/smoketests/conftest.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/smoketests/sdk/__init__.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/smoketests/sdk/conftest.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/smoketests/sdk/test_async_blueprint.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/smoketests/sdk/test_async_scorer.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/smoketests/sdk/test_async_sdk.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/smoketests/sdk/test_async_snapshot.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/smoketests/sdk/test_blueprint.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/smoketests/sdk/test_scorer.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/smoketests/sdk/test_sdk.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/smoketests/sdk/test_snapshot.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/smoketests/sdk/test_storage_object.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/smoketests/test_blueprints.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/smoketests/test_devboxes.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/smoketests/test_executions.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/smoketests/test_scenarios_benchmarks.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/smoketests/test_snapshots.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/smoketests/utils.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/test_client.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/test_deepcopy.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/test_extract_files.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/test_files.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/test_models.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/test_polling.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/test_qs.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/test_required_args.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/test_response.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/test_streaming.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/test_transform.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/test_utils/test_datetime_parse.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/test_utils/test_proxy.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/test_utils/test_typing.py +0 -0
- {runloop_api_client-1.0.0 → runloop_api_client-1.1.0}/tests/utils.py +0 -0
|
@@ -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
|
-
|
|
92
|
+
npx prism mock path/to/your/openapi.yml
|
|
93
93
|
```
|
|
94
94
|
|
|
95
95
|
```sh
|
|
96
|
-
|
|
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.
|
|
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
|
-
- [
|
|
12
|
-
- [
|
|
13
|
-
- [
|
|
14
|
-
- [
|
|
15
|
-
- [
|
|
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
|
|
|
@@ -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)
|