Skip to content

Commit 95cfbec

Browse files
committed
Merge remote-tracking branch 'origin/main' into openai/mcp
2 parents a272045 + 2a2b83b commit 95cfbec

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+3876
-1937
lines changed

.github/workflows/build-binaries.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ on:
44
branches:
55
- main
66
- "releases/*"
7+
- fix-build-binaries
78

89
jobs:
910
# Compile the binaries and upload artifacts
@@ -65,7 +66,7 @@ jobs:
6566
if [ "$RUNNER_OS" = "Windows" ]; then
6667
bindir=Scripts
6768
fi
68-
./.venv/$bindir/pip install 'protobuf>=3.20,<6' 'types-protobuf>=3.20,<6' 'typing-extensions>=4.2.0,<5' pytest pytest_asyncio grpcio 'nexus-rpc>=1.1.0' pydantic opentelemetry-api opentelemetry-sdk python-dateutil openai-agents
69+
./.venv/$bindir/pip install 'protobuf>=3.20,<6' 'types-protobuf>=3.20,<6' 'typing-extensions>=4.2.0,<5' pytest pytest_asyncio grpcio 'nexus-rpc>=1.1.0' pydantic opentelemetry-api opentelemetry-sdk python-dateutil 'openai-agents>=0.2.3,<=0.2.9'
6970
./.venv/$bindir/pip install --no-index --find-links=../dist temporalio
7071
./.venv/$bindir/python -m pytest -s -k test_workflow_hello
7172

README.md

Lines changed: 44 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1489,21 +1489,21 @@ https://github.com/temporalio/samples-python/tree/nexus/hello_nexus).
14891489
14901490
### Plugins
14911491
1492-
Plugins provide a way to extend and customize the behavior of Temporal clients and workers through a chain of
1493-
responsibility pattern. They allow you to intercept and modify client creation, service connections, worker
1492+
Plugins provide a way to extend and customize the behavior of Temporal clients and workers through a chain of
1493+
responsibility pattern. They allow you to intercept and modify client creation, service connections, worker
14941494
configuration, and worker execution. Common customizations may include but are not limited to:
14951495
14961496
1. DataConverter
14971497
2. Activities
14981498
3. Workflows
14991499
4. Interceptors
15001500
1501-
A single plugin class can implement both client and worker plugin interfaces to share common logic between both
1501+
A single plugin class can implement both client and worker plugin interfaces to share common logic between both
15021502
contexts. When used with a client, it will automatically be propagated to any workers created with that client.
15031503
15041504
#### Client Plugins
15051505
1506-
Client plugins can intercept and modify client configuration and service connections. They are useful for adding
1506+
Client plugins can intercept and modify client configuration and service connections. They are useful for adding
15071507
authentication, modifying connection parameters, or adding custom behavior during client creation.
15081508
15091509
Here's an example of a client plugin that adds custom authentication:
@@ -1515,7 +1515,7 @@ import temporalio.service
15151515
class AuthenticationPlugin(Plugin):
15161516
def __init__(self, api_key: str):
15171517
self.api_key = api_key
1518-
1518+
15191519
def init_client_plugin(self, next: Plugin) -> None:
15201520
self.next_client_plugin = next
15211521
@@ -1540,10 +1540,10 @@ client = await Client.connect(
15401540

15411541
#### Worker Plugins
15421542

1543-
Worker plugins can modify worker configuration and intercept worker execution. They are useful for adding monitoring,
1544-
custom lifecycle management, or modifying worker settings. Worker plugins can also configure replay.
1545-
They should do this in the case that they modified the worker in a way which would also need to be present
1546-
for replay to function. For instance, changing the data converter or adding workflows.
1543+
Worker plugins can modify worker configuration and intercept worker execution. They are useful for adding monitoring,
1544+
custom lifecycle management, or modifying worker settings. Worker plugins can also configure replay.
1545+
They should do this in the case that they modified the worker in a way which would also need to be present
1546+
for replay to function. For instance, changing the data converter or adding workflows.
15471547

15481548
Here's an example of a worker plugin that adds custom monitoring:
15491549

@@ -1560,7 +1560,7 @@ class MonitoringPlugin(Plugin):
15601560

15611561
def init_worker_plugin(self, next: Plugin) -> None:
15621562
self.next_worker_plugin = next
1563-
1563+
15641564
def configure_worker(self, config: WorkerConfig) -> WorkerConfig:
15651565
# Modify worker configuration
15661566
original_task_queue = config["task_queue"]
@@ -1574,22 +1574,22 @@ class MonitoringPlugin(Plugin):
15741574
await self.next_worker_plugin.run_worker(worker)
15751575
finally:
15761576
self.logger.info("Worker execution completed")
1577-
1578-
def configure_replayer(self, config: ReplayerConfig) -> ReplayerConfig:
1579-
return self.next_worker_plugin.configure_replayer(config)
1580-
1581-
@asynccontextmanager
1582-
async def run_replayer(
1583-
self,
1584-
replayer: Replayer,
1585-
histories: AsyncIterator[temporalio.client.WorkflowHistory],
1586-
) -> AsyncIterator[AsyncIterator[WorkflowReplayResult]]:
1587-
self.logger.info("Starting replay execution")
1588-
try:
1589-
async with self.next_worker_plugin.run_replayer(replayer, histories) as results:
1590-
yield results
1591-
finally:
1592-
self.logger.info("Replay execution completed")
1577+
1578+
def configure_replayer(self, config: ReplayerConfig) -> ReplayerConfig:
1579+
return self.next_worker_plugin.configure_replayer(config)
1580+
1581+
@asynccontextmanager
1582+
async def run_replayer(
1583+
self,
1584+
replayer: Replayer,
1585+
histories: AsyncIterator[temporalio.client.WorkflowHistory],
1586+
) -> AsyncIterator[AsyncIterator[WorkflowReplayResult]]:
1587+
self.logger.info("Starting replay execution")
1588+
try:
1589+
async with self.next_worker_plugin.run_replayer(replayer, histories) as results:
1590+
yield results
1591+
finally:
1592+
self.logger.info("Replay execution completed")
15931593

15941594
# Use the plugin when creating a worker
15951595
worker = Worker(
@@ -1617,38 +1617,38 @@ class UnifiedPlugin(ClientPlugin, WorkerPlugin):
16171617

16181618
def init_worker_plugin(self, next: WorkerPlugin) -> None:
16191619
self.next_worker_plugin = next
1620-
1620+
16211621
def configure_client(self, config: ClientConfig) -> ClientConfig:
16221622
# Client-side customization
16231623
config["data_converter"] = pydantic_data_converter
16241624
return self.next_client_plugin.configure_client(config)
1625-
1625+
16261626
async def connect_service_client(
16271627
self, config: temporalio.service.ConnectConfig
16281628
) -> temporalio.service.ServiceClient:
16291629
# Add authentication to the connection
16301630
config.api_key = self.api_key
16311631
return await self.next_client_plugin.connect_service_client(config)
1632-
1632+
16331633
def configure_worker(self, config: WorkerConfig) -> WorkerConfig:
16341634
# Worker-side customization
16351635
return self.next_worker_plugin.configure_worker(config)
1636-
1636+
16371637
async def run_worker(self, worker: Worker) -> None:
16381638
print("Starting unified worker")
16391639
await self.next_worker_plugin.run_worker(worker)
1640-
1640+
16411641
def configure_replayer(self, config: ReplayerConfig) -> ReplayerConfig:
16421642
config["data_converter"] = pydantic_data_converter
1643-
return config
1644-
1643+
return self.next_worker_plugin.configure_replayer(config)
1644+
16451645
async def run_replayer(
16461646
self,
16471647
replayer: Replayer,
16481648
histories: AsyncIterator[temporalio.client.WorkflowHistory],
16491649
) -> AbstractAsyncContextManager[AsyncIterator[WorkflowReplayResult]]:
16501650
return self.next_worker_plugin.run_replayer(replayer, histories)
1651-
1651+
16521652
# Create client with the unified plugin
16531653
client = await Client.connect(
16541654
"localhost:7233",
@@ -1902,20 +1902,18 @@ poe test -s --log-cli-level=DEBUG -k test_sync_activity_thread_cancel_caught
19021902

19031903
#### Proto Generation and Testing
19041904

1905-
To allow for backwards compatibility, protobuf code is generated on the 3.x series of the protobuf library. To generate
1906-
protobuf code, you must be on Python <= 3.10, and then run `uv add "protobuf<4"` + `uv sync --all-extras`. Then the
1907-
protobuf files can be generated via `poe gen-protos`. Tests can be run for protobuf version 3 by setting the
1908-
`TEMPORAL_TEST_PROTO3` env var to `1` prior to running tests.
1909-
1910-
Do not commit `uv.lock` or `pyproject.toml` changes. To go back from this downgrade, restore both of those files and run
1911-
`uv sync --all-extras`. Make sure you `poe format` the results.
1905+
If you have docker available, run
19121906

1913-
For a less system-intrusive approach, you can:
1914-
```shell
1915-
docker build -f scripts/_proto/Dockerfile .
1916-
docker run --rm -v "${PWD}/temporalio/api:/api_new" -v "${PWD}/temporalio/bridge/proto:/bridge_new" <just built image sha>
1917-
poe format
19181907
```
1908+
poe gen-protos-docker
1909+
```
1910+
1911+
Alternatively: to generate protobuf code, you must be on Python <= 3.10, and then run `uv add
1912+
"protobuf<4"` + `uv sync --all-extras`. Then the protobuf files can be generated via `poe
1913+
gen-protos` followed by `poe format`. Do not commit `uv.lock` or `pyproject.toml` changes. To go
1914+
back from this downgrade, restore both of those files and run `uv sync --all-extras`. Tests can be
1915+
run for protobuf version 3 by setting the `TEMPORAL_TEST_PROTO3` env var to `1` prior to running
1916+
tests.
19191917

19201918
### Style
19211919

pyproject.toml

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "temporalio"
3-
version = "1.16.0"
3+
version = "1.17.0"
44
description = "Temporal.io Python SDK"
55
authors = [{ name = "Temporal Technologies Inc", email = "[email protected]" }]
66
requires-python = ">=3.9"
@@ -12,7 +12,7 @@ keywords = [
1212
]
1313
dependencies = [
1414
"nexus-rpc==1.1.0",
15-
"protobuf>=3.20,<6",
15+
"protobuf>=3.20,<7.0.0",
1616
"python-dateutil>=2.8.2,<3 ; python_version < '3.11'",
1717
"types-protobuf>=3.20",
1818
"typing-extensions>=4.2.0,<5",
@@ -26,7 +26,7 @@ opentelemetry = [
2626
]
2727
pydantic = ["pydantic>=2.0.0,<3"]
2828
openai-agents = [
29-
"openai-agents >= 0.2.3,<0.3",
29+
"openai-agents>=0.3,<0.4",
3030
"eval-type-backport>=0.2.2; python_version < '3.10'",
3131
"mcp>=1.9.4, <2; python_version >= '3.10'",
3232
]
@@ -58,15 +58,16 @@ dev = [
5858
"pytest-cov>=6.1.1",
5959
"httpx>=0.28.1",
6060
"pytest-pretty>=1.3.0",
61-
"openai-agents[litellm] >= 0.2.3,<0.3"
61+
"openai-agents[litellm]>=0.3,<0.4"
6262
]
6363

6464
[tool.poe.tasks]
6565
build-develop = "uv run maturin develop --uv"
6666
build-develop-with-release = { cmd = "uv run maturin develop --release --uv" }
6767
format = [{cmd = "uv run ruff check --select I --fix"}, {cmd = "uv run ruff format"}, ]
68-
gen-docs = "uv run python scripts/gen_docs.py"
69-
gen-protos = "uv run python scripts/gen_protos.py"
68+
gen-docs = "uv run scripts/gen_docs.py"
69+
gen-protos = "uv run scripts/gen_protos.py"
70+
gen-protos-docker = "uv run scripts/gen_protos_docker.py"
7071
lint = [
7172
{cmd = "uv run ruff check --select I"},
7273
{cmd = "uv run ruff format --check"},

scripts/_proto/Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,4 @@ RUN uv add "protobuf<4"
1212
RUN uv sync --all-extras
1313
RUN poe gen-protos
1414

15-
CMD cp -r ./temporalio/api/* /api_new && cp -r ./temporalio/bridge/proto/* /bridge_new
15+
CMD ["sh", "-c", "cp -r ./temporalio/api/* /api_new && cp -r ./temporalio/bridge/proto/* /bridge_new"]

0 commit comments

Comments
 (0)