Skip to content

Commit 2e5ab92

Browse files
committed
Fix sync server version API
Add ConfigClient.get_server_version() to match the async client, deprecate the sync server_version property, and update docs, tests, and the quickstart example. Assisted-by: OpenAI Codex
1 parent d3d3085 commit 2e5ab92

5 files changed

Lines changed: 80 additions & 9 deletions

File tree

examples/quickstart/main.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ def main() -> None:
2020

2121
# Context manager closes the gRPC channel automatically.
2222
with ConfigClient("localhost:9090", subject="quickstart-example") as client:
23+
server_version = client.get_server_version()
24+
print(f"server.version: {server_version.version}")
25+
2326
# get() returns str by default.
2427
name = client.get(tenant_id, "app.name")
2528
print(f"app.name: {name}")

sdk/docs/async.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ The SDK provides async equivalents for all sync APIs, built on `grpc.aio`.
88
from opendecree import AsyncConfigClient
99

1010
async with AsyncConfigClient("localhost:9090", subject="myapp") as client:
11+
# Server version
12+
version = await client.get_server_version()
13+
1114
# Typed gets (same overload pattern as sync)
1215
fee = await client.get("tenant-id", "payments.fee") # → str
1316
retries = await client.get("tenant-id", "payments.retries", int) # → int

sdk/docs/configuration.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,28 @@ client = ConfigClient("localhost:9090", timeout=30.0)
156156

157157
Default: 10 seconds.
158158

159+
## Server version
160+
161+
Fetch the server version explicitly with `get_server_version()`. The value is cached after the
162+
first call.
163+
164+
```python
165+
with ConfigClient("localhost:9090", subject="myapp") as client:
166+
version = client.get_server_version()
167+
print(version.version)
168+
```
169+
170+
For async clients, await the same method:
171+
172+
```python
173+
async with AsyncConfigClient("localhost:9090", subject="myapp") as client:
174+
version = await client.get_server_version()
175+
print(version.version)
176+
```
177+
178+
The sync-only `server_version` property is deprecated for one release. Use
179+
`get_server_version()` for both sync and async clients.
180+
159181
## Error types
160182

161183
All exceptions inherit from `DecreeError`:

sdk/src/opendecree/client.py

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
from __future__ import annotations
1313

14+
import warnings
1415
from datetime import timedelta
1516
from typing import TYPE_CHECKING, overload
1617

@@ -108,9 +109,8 @@ def __enter__(self) -> ConfigClient:
108109
def __exit__(self, *exc: object) -> None:
109110
self.close()
110111

111-
@property
112-
def server_version(self) -> ServerVersion:
113-
"""The server's version, fetched once and cached.
112+
def get_server_version(self) -> ServerVersion:
113+
"""Fetch the server's version, cached after first call.
114114
115115
Returns:
116116
ServerVersion with version and commit strings.
@@ -124,6 +124,20 @@ def server_version(self) -> ServerVersion:
124124
)
125125
return self._server_version
126126

127+
@property
128+
def server_version(self) -> ServerVersion:
129+
"""The server's version, fetched once and cached.
130+
131+
Deprecated:
132+
Use ``get_server_version()`` instead.
133+
"""
134+
warnings.warn(
135+
"ConfigClient.server_version is deprecated; use get_server_version() instead.",
136+
DeprecationWarning,
137+
stacklevel=2,
138+
)
139+
return self.get_server_version()
140+
127141
def check_compatibility(self) -> None:
128142
"""Check that the server version is compatible with this SDK.
129143
@@ -135,7 +149,7 @@ def check_compatibility(self) -> None:
135149
supported range.
136150
UnavailableError: If the server is unreachable.
137151
"""
138-
check_version_compatible(self.server_version.version)
152+
check_version_compatible(self.get_server_version().version)
139153

140154
# --- get() with @overload for type safety ---
141155

sdk/tests/test_compat.py

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -126,11 +126,11 @@ async def test_async_fetch_server_version():
126126
assert sv == ServerVersion(version="0.3.1", commit="abc123")
127127

128128

129-
# --- ConfigClient.server_version + check_compatibility ---
129+
# --- ConfigClient.get_server_version + check_compatibility ---
130130

131131

132-
def test_client_server_version_cached():
133-
"""server_version property fetches once, returns cached."""
132+
def test_client_get_server_version_cached():
133+
"""get_server_version() fetches once, returns cached."""
134134
with patch("opendecree.client.create_channel"):
135135
from opendecree import ConfigClient
136136

@@ -147,12 +147,41 @@ def test_client_server_version_cached():
147147
client._server_version = None
148148

149149
# First call fetches
150-
v1 = client.server_version
150+
v1 = client.get_server_version()
151151
assert v1.version == "0.3.1"
152152
assert mock_stub.GetServerInfo.call_count == 1
153153

154154
# Second call returns cached
155-
v2 = client.server_version
155+
v2 = client.get_server_version()
156+
assert v2 is v1
157+
assert mock_stub.GetServerInfo.call_count == 1
158+
159+
160+
def test_client_server_version_property_deprecated():
161+
with patch("opendecree.client.create_channel"):
162+
from opendecree import ConfigClient
163+
164+
client = ConfigClient.__new__(ConfigClient)
165+
client._timeout = 5.0
166+
167+
mock_stub = MagicMock()
168+
resp = MagicMock()
169+
resp.version = "0.3.1"
170+
resp.commit = "abc123"
171+
mock_stub.GetServerInfo.return_value = resp
172+
client._version_stub = mock_stub
173+
client._version_pb2 = MagicMock()
174+
client._server_version = None
175+
176+
with pytest.warns(DeprecationWarning, match="get_server_version"):
177+
v1 = client.server_version
178+
179+
assert v1.version == "0.3.1"
180+
assert mock_stub.GetServerInfo.call_count == 1
181+
182+
with pytest.warns(DeprecationWarning, match="get_server_version"):
183+
v2 = client.server_version
184+
156185
assert v2 is v1
157186
assert mock_stub.GetServerInfo.call_count == 1
158187

0 commit comments

Comments
 (0)