Skip to content

Commit ce0f2c4

Browse files
fix: derive worker sdk_version from installed package metadata
Removes the hard-coded "durable-workflow-python/0.1.0" default in Client.register_worker() so workers advertise the version of the SDK they were actually built against. The default now uses importlib.metadata so it tracks the next published bump automatically. Also exports __version__ on the package for callers that need to inspect it directly. Closes TD-P011. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 39a903e commit ce0f2c4

3 files changed

Lines changed: 49 additions & 1 deletion

File tree

src/durable_workflow/__init__.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1+
from importlib.metadata import PackageNotFoundError
2+
from importlib.metadata import version as _pkg_version
3+
4+
try:
5+
__version__ = _pkg_version("durable-workflow")
6+
except PackageNotFoundError: # source checkout without installed metadata
7+
__version__ = "0.0.0+unknown"
8+
19
from . import activity, sync, workflow
210
from .activity import ActivityContext, ActivityInfo
311
from .client import (
@@ -36,6 +44,7 @@
3644
from .workflow import ContinueAsNew, StartChildWorkflow
3745

3846
__all__ = [
47+
"__version__",
3948
"ActivityCancelled",
4049
"ActivityContext",
4150
"ActivityInfo",

src/durable_workflow/client.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
import asyncio
44
from dataclasses import dataclass
5+
from importlib.metadata import PackageNotFoundError
6+
from importlib.metadata import version as _pkg_version
57
from typing import Any
68

79
import httpx
@@ -19,6 +21,16 @@
1921
CONTROL_PLANE_VERSION = "2"
2022

2123

24+
def _default_sdk_version() -> str:
25+
try:
26+
return f"durable-workflow-python/{_pkg_version('durable-workflow')}"
27+
except PackageNotFoundError:
28+
return "durable-workflow-python/0.0.0+unknown"
29+
30+
31+
DEFAULT_SDK_VERSION = _default_sdk_version()
32+
33+
2234
@dataclass
2335
class WorkflowExecution:
2436
workflow_id: str
@@ -703,8 +715,10 @@ async def register_worker(
703715
supported_workflow_types: list[str] | None = None,
704716
supported_activity_types: list[str] | None = None,
705717
runtime: str = "python",
706-
sdk_version: str = "durable-workflow-python/0.1.0",
718+
sdk_version: str | None = None,
707719
) -> Any:
720+
if sdk_version is None:
721+
sdk_version = DEFAULT_SDK_VERSION
708722
body: dict[str, Any] = {
709723
"worker_id": worker_id,
710724
"task_queue": task_queue,

tests/test_client.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,3 +348,28 @@ async def test_register(self, client: Client) -> None:
348348
assert result["registered"] is True
349349
body = mock.call_args.kwargs.get("json") or mock.call_args[1].get("json")
350350
assert body["runtime"] == "python"
351+
352+
@pytest.mark.asyncio
353+
async def test_register_advertises_installed_package_version(self, client: Client) -> None:
354+
from importlib.metadata import version as _pkg_version
355+
356+
import durable_workflow
357+
358+
installed = _pkg_version("durable-workflow")
359+
assert durable_workflow.__version__ == installed
360+
361+
resp = _mock_response(201, {"worker_id": "w1", "registered": True})
362+
with patch.object(client._http, "request", new_callable=AsyncMock, return_value=resp) as mock:
363+
await client.register_worker(worker_id="w1", task_queue="q1")
364+
body = mock.call_args.kwargs.get("json") or mock.call_args[1].get("json")
365+
assert body["sdk_version"] == f"durable-workflow-python/{installed}"
366+
367+
@pytest.mark.asyncio
368+
async def test_register_honors_explicit_sdk_version_override(self, client: Client) -> None:
369+
resp = _mock_response(201, {"worker_id": "w1", "registered": True})
370+
with patch.object(client._http, "request", new_callable=AsyncMock, return_value=resp) as mock:
371+
await client.register_worker(
372+
worker_id="w1", task_queue="q1", sdk_version="custom-runtime/9.9.9"
373+
)
374+
body = mock.call_args.kwargs.get("json") or mock.call_args[1].get("json")
375+
assert body["sdk_version"] == "custom-runtime/9.9.9"

0 commit comments

Comments
 (0)