Dx 2777 - Add Python SDK#185
Merged
Merged
Conversation
There was a problem hiding this comment.
Pull request overview
Adds a first-party Python SDK (packages/python-sdk) for Upstash Box, including async + generated sync clients, typed models, tests, tooling, and CI workflows to keep the Python surface in parity with the existing TypeScript SDK.
Changes:
- Introduces
upstash_boxpackage (async source-of-truth + generated sync client), shared types/helpers, and custom harness helper. - Adds comprehensive unit + integration test suites, plus JS↔Python public-surface parity enforcement tooling.
- Adds Python SDK packaging/docs and CI/publish workflows (ruff/mypy/pytest/parity, PyPI publish via tag).
Reviewed changes
Copilot reviewed 68 out of 69 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/python-sdk/upstash_box/types.py | Shared enums, TypedDict inputs, chunk dataclasses, and Pydantic response models. |
| packages/python-sdk/upstash_box/py.typed | Marks package as typed for type checkers. |
| packages/python-sdk/upstash_box/errors.py | Defines BoxError with optional HTTP status code. |
| packages/python-sdk/upstash_box/custom_harness.py | Helper to implement the box-sse-v1 custom harness protocol. |
| packages/python-sdk/upstash_box/_sync/client.py | Generated synchronous client implementation. |
| packages/python-sdk/upstash_box/_sync/_sse.py | Generated sync SSE parsers for run-stream and exec/code-stream. |
| packages/python-sdk/upstash_box/_sync/_fallbacks.py | Handwritten sync escape hatch for non-generatable constructs (currently empty). |
| packages/python-sdk/upstash_box/_sync/init.py | Exposes generated sync public symbols. |
| packages/python-sdk/upstash_box/_common.py | Transport-agnostic helpers (schema conversion, agent config, files, network policy). |
| packages/python-sdk/upstash_box/_async/_sse.py | Async SSE parsers (source-of-truth for sync generation). |
| packages/python-sdk/upstash_box/_async/init.py | Exposes async public symbols. |
| packages/python-sdk/upstash_box/init.py | Top-level package exports, version, and public surface. |
| packages/python-sdk/tests/integration/test_sync_subset.py | Real-API smoke test for sync client. |
| packages/python-sdk/tests/integration/test_snapshot_async.py | Real-API snapshot lifecycle test (async). |
| packages/python-sdk/tests/integration/test_schedule_async.py | Real-API schedule lifecycle test (async). |
| packages/python-sdk/tests/integration/test_public_url_async.py | Real-API public URL CRUD test (async). |
| packages/python-sdk/tests/integration/test_lifecycle_async.py | Real-API lifecycle/config/status/logs/runs tests (async). |
| packages/python-sdk/tests/integration/test_git_async.py | Real-API git operations test (async, no push/PR). |
| packages/python-sdk/tests/integration/test_files_async.py | Real-API files/code/cwd/download test (async). |
| packages/python-sdk/tests/integration/test_ephemeral_async.py | Real-API ephemeral box smoke test (async). |
| packages/python-sdk/tests/integration/test_env_async.py | Real-API env var management test (async). |
| packages/python-sdk/tests/integration/test_agent_async.py | Real-API agent run/stream smoke test (async). |
| packages/python-sdk/tests/integration/conftest.py | Integration gating via env + opts fixture. |
| packages/python-sdk/tests/helpers.py | Shared respx/httpx mocking helpers + SSE stream builders. |
| packages/python-sdk/tests/conftest.py | Ensures test helpers are importable across modules. |
| packages/python-sdk/tests/_sync/test_sync_client.py | Handwritten sync unit suite focusing on streaming/multipart/polling edge cases. |
| packages/python-sdk/tests/_sync/test_sse_golden.py | Golden parity test between async and generated sync SSE parsers. |
| packages/python-sdk/tests/_async/test_run.py | Async run behaviors (cancel, logs filtering/format). |
| packages/python-sdk/tests/_async/test_models.py | Field-level assertions for key response models/chunks. |
| packages/python-sdk/tests/_async/test_infer_provider.py | Tests provider inference helper. |
| packages/python-sdk/tests/_async/test_errors.py | Tests BoxError behavior. |
| packages/python-sdk/tests/_async/test_ephemeral_box.py | Async ephemeral box unit tests. |
| packages/python-sdk/tests/_async/test_custom_harness.py | Tests harness arg parsing + SSE emission contract. |
| packages/python-sdk/tests/_async/test_common.py | Unit tests for _common helpers (schema, files, policies, etc.). |
| packages/python-sdk/tests/_async/test_box_statics.py | Async static methods tests (list/delete/env management). |
| packages/python-sdk/tests/_async/test_box_snapshot.py | Async snapshot/from_snapshot unit tests. |
| packages/python-sdk/tests/_async/test_box_schedule.py | Async schedule namespace unit tests. |
| packages/python-sdk/tests/_async/test_box_prompt_files.py | Async prompt file attachment tests (JSON/multipart/webhook). |
| packages/python-sdk/tests/_async/test_box_misc.py | Async misc namespaces (skills, init command, lifecycle, public URLs). |
| packages/python-sdk/tests/_async/test_box_instance.py | Async instance property/cwd/context manager/close tests. |
| packages/python-sdk/tests/_async/test_box_git.py | Async git namespace unit tests. |
| packages/python-sdk/tests/_async/test_box_files.py | Async files namespace unit tests. |
| packages/python-sdk/tests/_async/test_box_exec.py | Async exec/code/exec-stream unit tests. |
| packages/python-sdk/tests/_async/test_box_create.py | Async create/polling/error handling unit tests. |
| packages/python-sdk/tests/_async/test_box_agent_run.py | Async agent run/stream behaviors, structured output, callbacks. |
| packages/python-sdk/scripts/generate_sync.py | unasync-based generator for _sync/ from _async/. |
| packages/python-sdk/scripts/extract_js_surface.mjs | TypeScript-compiler-based JS SDK public surface extractor. |
| packages/python-sdk/scripts/check_parity.py | CI parity enforcement between JS and Python public surfaces. |
| packages/python-sdk/RELEASE.md | Python SDK release process and versioning policy. |
| packages/python-sdk/README.md | Package documentation + examples. |
| packages/python-sdk/pyproject.toml | Packaging metadata, deps, ruff/mypy/pytest config. |
| packages/python-sdk/PARITY.md | Parity checklist and tracked drift notes. |
| packages/python-sdk/LICENSE | MIT license for the Python SDK package. |
| packages/python-sdk/examples/webhook.py | Webhook (fire-and-forget) async example. |
| packages/python-sdk/examples/sync_basic.py | Basic sync usage example. |
| packages/python-sdk/examples/streaming_structured.py | Streaming + Pydantic structured output example. |
| packages/python-sdk/examples/snapshot_restore.py | Snapshot + restore example. |
| packages/python-sdk/examples/git_pr.py | Git + agent + PR creation flow example. |
| packages/python-sdk/examples/file_upload.py | File upload example (ephemeral box). |
| packages/python-sdk/examples/custom_harness.py | Custom harness process example. |
| packages/python-sdk/examples/basic.py | Basic async quickstart example. |
| packages/python-sdk/CONTRIBUTING.md | Contribution guide emphasizing async source-of-truth + sync generation. |
| packages/python-sdk/CHANGELOG.md | Initial release changelog entry. |
| packages/python-sdk/.gitignore | Python SDK local build/test/env ignores. |
| AGENTS.md | Adds Python SDK workflow guidance to repo agent instructions. |
| .pre-commit-config.yaml | Optional pre-commit hooks for Python SDK generation + ruff. |
| .github/workflows/python-sdk-publish.yml | Tagged/manual gated PyPI publish workflow. |
| .github/workflows/python-sdk-ci.yml | Python SDK CI workflow (ruff, generation check, mypy, pytest, parity). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+876
to
+881
| for f in files: | ||
| resolved = self._resolve_path(f["destination"]) | ||
| with open(f["path"], "rb") as fh: | ||
| content = fh.read() | ||
| data_paths.append(resolved) | ||
| upload_files.append(("files", (f["destination"], content))) |
Comment on lines
+1566
to
+1572
| def _build_multipart_files(file_paths: List[str]) -> List[Any]: | ||
| out = [] | ||
| for path in file_paths: | ||
| with open(path, "rb") as fh: | ||
| content = fh.read() | ||
| out.append(("files", (os.path.basename(path), content, common.mime_for_path(path)))) | ||
| return out |
Collaborator
mdumandag
reviewed
Jun 23, 2026
mdumandag
approved these changes
Jun 24, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

No description provided.