This repository provides the Temporal Python SDK, including Python packages, tests, optional integrations, and the Rust bridge used by the SDK. Use this document as a quick reference when submitting pull requests.
- Prefer the repo's Poe tasks over invoking underlying tools directly. Use
poe test,poe lint,poe format,poe build-develop, andpoe bridge-lintunless there is a specific reason to run a lower-level command. - If you are about to run tests, you do not need to run a build separately first
unless Rust bridge changes need a fresh editable extension. For bridge changes,
run
poe build-developbefore Python tests that importtemporalio. - Use targeted tests while iterating.
poe test -s -k <pattern>is preferred for a small behavioral change; run broader tests only when the change affects shared behavior. - Do not use
--log-cli-levelby default. The pytest configuration shows logs for failed tests at the end without streaming all logs for passing tests. - Tests that use the workflow environment may start a local Temporal dev server and may download a test server binary on first run. Unit tests that do not use the workflow environment do not start a server.
- Time-skipping V1 tests are run with
poe test -s --workflow-environment time-skipping-v1. Time-skipping V1 does not work on Linux ARM or Windows ARM. - Time-skipping V2 tests are run with
poe test -s --workflow-environment time-skipping-v2. Time-skipping V2 works on both Linux ARM and Windows ARM. - It is extremely important that comments explain why something is necessary, not what the code already says. Avoid comments unless they clarify nonobvious behavior.
- Avoid broad refactors, style churn, or unrelated cleanups in behavior changes.
- Avoid unqualified imports from
temporaliopackages excepttemporalio.types. Relative imports are acceptable for private packages. - Do not commit
uv.lockorpyproject.tomlchanges created only for temporary protobuf downgrade workflows. Prefer to use poe gen-protos-docker when possible.
- Poe tasks are defined in
pyproject.toml:poe build-develop- build the Rust extension in editable debug mode.poe test- run pytest in parallel with the default workflow environment.poe lint- run import checks, formatting checks, type checks, and docstyle.poe lint-types- run pyright, mypy, and basedpyright.poe bridge-lint- run clippy for the Rust bridge.poe update-core- update the Core pin and import its changelog fragments.poe format- run Ruff import sorting, Ruff formatting, andcargo fmtfor the bridge.poe gen-protos-docker- regenerate protobuf-related files using Docker.poe gen-protos- regenerate protobuf-related files without Docker, with the Python/protobuf constraints documented inREADME.md.
The common local commands are:
uv sync --all-extras
poe build-develop
poe lint
poe test
poe test -s --workflow-environment time-skippingFor focused iteration, prefer:
poe test -s -k <test_or_pattern>
uv run pytest tests/path/test_file.py::test_nameFor release artifacts, use uv build. Documentation can be generated with
poe gen-docs.
- Format and lint code before submitting.
- Include tests for behavior changes.
- Update public API documentation or doc comments for public behavior changes.
- For user-facing changes, add a Markdown fragment under
changelog/<category>/for each applicable category. Usestabilized/for features that are no longer experimental. Use fun, whimsical, unique lowercase kebab-case filenames, such asgiggling-teapot.md. The folder supplies the category; write only the release-note body, without a leading list marker (-). Keep entries concise, ideally one or two sentences. Write each entry entirely on one line: release tooling turns each nonempty line into a separate list item. A fragment may contain multiple entries. Seechangelog/README.mdfor the convention.CHANGELOG.mdcontains completed releases and is assembled by release tooling. - Keep commit messages short and in the imperative mood.
- Provide a clear PR description outlining what changed, why it changed, and what validation was run.
Reviewers will look for:
- CI passing, including build, lint, type checks, unit tests, and workflow environment tests.
- Tests covering behavior changes.
- Clear and concise code following existing style.
- Public API documentation updates when behavior changes.
- No unrelated generated files, lockfile churn, or broad rewrites.
temporalio/- Python SDK source.temporalio/worker/- worker implementation.temporalio/converter/- payload and failure conversion.temporalio/testing/- testing utilities.temporalio/nexus/- Nexus support.temporalio/contrib/- optional integrations.temporalio/bridge/- Rust bridge and generated bridge bindings.
tests/- pytest suites mirroring SDK areas.scripts/- generation, documentation, and helper scripts.changelog/- pending per-PR release notes in category folders.build/apidocs/- generated API documentation.dist/- built wheels and source distributions.temporalio/bridge/target/- Rust build output. You should not need to inspect this directory.
- The SDK supports Python 3.10 and newer.
- Generated protobuf and bridge files have specific regeneration workflows; see
README.mdbefore changing them. - The Rust bridge uses SDK Core from
temporalio/bridge/sdk-core. - Update Core with
poe update-core, which invokes the shared command documented inCONTRIBUTING.mdunder "Updating SDK Core". It updates the submodule and imports Core's user-facing changelog entries into category fragments. Review and commit the new Core pin and generated fragments together; do not update the pin and defer its notes until release time. The Python task copies Core path dependency versions from the new checkout and refreshes the bridge lockfile; review both and check Rust API compatibility as needed. If Core protobuf definitions changed, runpoe gen-protos-dockerand commit the regenerated bindings with the pin update. __pycache__,build,dist, and Rusttargetoutputs are generated artifacts and should not be reviewed as source changes.
