Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Automated pass over on python cleanup & deduplication
  • Loading branch information
donald-pinckney committed Feb 27, 2026
commit 8a74de8f6d0bffc358c2452152e8cbd088c12271
19 changes: 2 additions & 17 deletions references/python/determinism.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ The Python SDK runs workflows in a sandbox that provides automatic protection ag

## Why Determinism Matters: History Replay

Temporal achieves durability through **history replay**. Understanding this mechanism is key to writing correct Workflow code.
Temporal provides durable execution through **History Replay**. When a Worker needs to restore workflow state (after a crash, cache eviction, or to continue after a long timer), it re-executes the workflow code from the beginning, which requires the workflow code to be **deterministic**.

## Forbidden Operations

Expand All @@ -29,22 +29,7 @@ Temporal achieves durability through **history replay**. Understanding this mech

## Testing Replay Compatibility

Use the `Replayer` class to verify your code changes are compatible with existing histories:

```python
from temporalio.worker import Replayer
from temporalio.client import WorkflowHistory

async def test_replay_compatibility():
replayer = Replayer(workflows=[MyWorkflow])

# Test against a saved history
with open("workflow_history.json") as f:
history = WorkflowHistory.from_json("my-workflow-id", f.read())

# This will raise NondeterminismError if incompatible
await replayer.replay_workflow(history)
```
Use the `Replayer` class to verify your code changes are compatible with existing histories. See the Workflow Replay Testing section of `references/python/testing.md`.

## Sandbox Behavior

Expand Down
31 changes: 31 additions & 0 deletions references/python/gotchas.md
Original file line number Diff line number Diff line change
Expand Up @@ -170,3 +170,34 @@ It is important to make sure workflows work as expected under failure paths in a
### Not Testing Replay

Replay tests help you test that you do not have hidden sources of non-determinism bugs in your workflow code, and should be considered in addition to standard testing. Please see `references/python/testing.md` for more info.

## Timers and Sleep

### Using asyncio.sleep

```python
# BAD: asyncio.sleep is not deterministic during replay
import asyncio

@workflow.defn
class BadWorkflow:
@workflow.run
async def run(self) -> None:
await asyncio.sleep(60) # Non-deterministic!
```

```python
# GOOD: Use workflow.sleep for deterministic timers
from temporalio import workflow
from datetime import timedelta

@workflow.defn
class GoodWorkflow:
@workflow.run
async def run(self) -> None:
await workflow.sleep(timedelta(seconds=60)) # Deterministic
# Or with string duration:
await workflow.sleep("1 minute")
```

**Why this matters:** `asyncio.sleep` uses the system clock, which differs between original execution and replay. `workflow.sleep` creates a durable timer in the event history, ensuring consistent behavior during replay.
4 changes: 2 additions & 2 deletions references/python/python.md
Original file line number Diff line number Diff line change
Expand Up @@ -160,14 +160,14 @@ See `references/python/testing.md` for info on writing tests.
## Additional Resources

### Reference Files
- **`references/python/patterns.md`** - Signals, queries, child workflows, saga pattern
- **`references/python/patterns.md`** - Signals, queries, child workflows, saga pattern, etc.
- **`references/python/determinism.md`** - Sandbox behavior, safe alternatives, pass-through pattern, history replay
- **`references/python/gotchas.md`** - Python-specific mistakes and anti-patterns
- **`references/python/error-handling.md`** - ApplicationError, retry policies, non-retryable errors, idempotency
- **`references/python/observability.md`** - Logging, metrics, tracing, Search Attributes
- **`references/python/testing.md`** - WorkflowEnvironment, time-skipping, activity mocking
- **`references/python/sync-vs-async.md`** - Sync vs async activities, event loop blocking, executor configuration
- **`references/python/advanced-features.md`** - Continue-as-new, updates, schedules, and more
- **`references/python/advanced-features.md`** - Schedules, worker tuning, and more
- **`references/python/data-handling.md`** - Data converters, Pydantic, payload encryption
- **`references/python/versioning.md`** - Patching API, workflow type versioning, Worker Versioning
- **`references/python/determinism-protection.md`** - Python sandbox specifics, forbidden operations, pass-through imports
Expand Down
10 changes: 2 additions & 8 deletions references/python/versioning.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,8 @@
# Python SDK Versioning

## Overview
For conceptual overview and guidance on choosing an approach, see `references/core/versioning.md`.

Workflow versioning allows you to safely deploy changes to Workflow code without causing non-deterministic errors in running Workflow Executions. The Python SDK provides multiple approaches: the Patching API for code-level version management, Workflow Type versioning for incompatible changes, and Worker Versioning for deployment-level control.

## Why Versioning is Needed

When Workers restart after a deployment, they resume open Workflow Executions through History Replay. If the updated Workflow Definition produces a different sequence of Commands than the original code, it causes a non-deterministic error. Versioning ensures backward compatibility by preserving the original execution path for existing workflows while allowing new workflows to use updated code.

## Workflow Versioning with Patching API
## Patching API

### The patched() Function

Expand Down