Add idiomatic documentation to Go, Java, Python, and Rust clients
This commit is contained in:
@@ -14,13 +14,16 @@ class ApiKey:
|
||||
value: str
|
||||
|
||||
def __post_init__(self) -> None:
|
||||
"""Validate that the API key value is non-empty."""
|
||||
if not self.value:
|
||||
raise ValueError("api_key must not be empty")
|
||||
|
||||
def __repr__(self) -> str:
|
||||
"""Return a repr that redacts the secret value."""
|
||||
return f"{type(self).__name__}({REDACTED!r})"
|
||||
|
||||
def bearer_value(self) -> str:
|
||||
"""Return the value formatted as an HTTP `Bearer` token."""
|
||||
return f"Bearer {self.value}"
|
||||
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ class GatewayClient:
|
||||
stub: Any,
|
||||
channel: grpc.aio.Channel | None = None,
|
||||
) -> None:
|
||||
"""Initialize the client with resolved options and a gRPC stub."""
|
||||
self.options = options
|
||||
self.raw_stub = stub
|
||||
self._channel = channel
|
||||
@@ -63,9 +64,11 @@ class GatewayClient:
|
||||
)
|
||||
|
||||
async def __aenter__(self) -> "GatewayClient":
|
||||
"""Return self to support ``async with`` usage."""
|
||||
return self
|
||||
|
||||
async def __aexit__(self, *_exc_info: object) -> None:
|
||||
"""Close the client when leaving an ``async with`` block."""
|
||||
await self.close()
|
||||
|
||||
async def close(self) -> None:
|
||||
@@ -99,6 +102,7 @@ class GatewayClient:
|
||||
return Session(client=self, session_id=reply.session_id, open_reply=reply)
|
||||
|
||||
async def open_session_raw(self, request: pb.OpenSessionRequest) -> pb.OpenSessionReply:
|
||||
"""Send an `OpenSession` RPC and return the raw reply."""
|
||||
reply = await self._unary("open session", self.raw_stub.OpenSession, request)
|
||||
ensure_protocol_success("open session", reply.protocol_status, reply)
|
||||
return reply
|
||||
@@ -107,11 +111,13 @@ class GatewayClient:
|
||||
self,
|
||||
request: pb.CloseSessionRequest,
|
||||
) -> pb.CloseSessionReply:
|
||||
"""Send a `CloseSession` RPC and return the raw reply."""
|
||||
reply = await self._unary("close session", self.raw_stub.CloseSession, request)
|
||||
ensure_protocol_success("close session", reply.protocol_status, reply)
|
||||
return reply
|
||||
|
||||
async def invoke_raw(self, request: pb.MxCommandRequest) -> pb.MxCommandReply:
|
||||
"""Send an `Invoke` RPC and return the raw reply."""
|
||||
reply = await self._unary("invoke", self.raw_stub.Invoke, request)
|
||||
ensure_protocol_success("invoke", reply.protocol_status, reply)
|
||||
return reply
|
||||
|
||||
@@ -19,6 +19,7 @@ class MxGatewayError(Exception):
|
||||
protocol_status: pb.ProtocolStatus | None = None,
|
||||
raw_reply: Any | None = None,
|
||||
) -> None:
|
||||
"""Initialize with a message and the optional raw protocol context."""
|
||||
super().__init__(message)
|
||||
self.protocol_status = protocol_status
|
||||
self.raw_reply = raw_reply
|
||||
|
||||
@@ -34,6 +34,7 @@ class GalaxyRepositoryClient:
|
||||
stub: Any,
|
||||
channel: grpc.aio.Channel | None = None,
|
||||
) -> None:
|
||||
"""Initialize the client with resolved options and a gRPC stub."""
|
||||
self.options = options
|
||||
self.raw_stub = stub
|
||||
self._channel = channel
|
||||
@@ -72,9 +73,11 @@ class GalaxyRepositoryClient:
|
||||
)
|
||||
|
||||
async def __aenter__(self) -> "GalaxyRepositoryClient":
|
||||
"""Return self to support ``async with`` usage."""
|
||||
return self
|
||||
|
||||
async def __aexit__(self, *_exc_info: object) -> None:
|
||||
"""Close the client when leaving an ``async with`` block."""
|
||||
await self.close()
|
||||
|
||||
async def close(self) -> None:
|
||||
|
||||
@@ -23,6 +23,7 @@ class ClientOptions:
|
||||
stream_timeout: float | None = None
|
||||
|
||||
def __post_init__(self) -> None:
|
||||
"""Validate options; raise `ValueError` for invalid combinations."""
|
||||
if not self.endpoint:
|
||||
raise ValueError("endpoint must not be empty")
|
||||
|
||||
@@ -34,6 +35,7 @@ class ClientOptions:
|
||||
raise ValueError("stream_timeout must be greater than zero")
|
||||
|
||||
def __repr__(self) -> str:
|
||||
"""Return a repr that redacts the API key value."""
|
||||
api_key = REDACTED if self.api_key else None
|
||||
return (
|
||||
f"{type(self).__name__}(endpoint={self.endpoint!r}, "
|
||||
|
||||
@@ -21,15 +21,18 @@ class Session:
|
||||
session_id: str,
|
||||
open_reply: pb.OpenSessionReply | None = None,
|
||||
) -> None:
|
||||
"""Initialize a session bound to a client and gateway session id."""
|
||||
self.client = client
|
||||
self.session_id = session_id
|
||||
self.open_reply = open_reply
|
||||
self._closed = False
|
||||
|
||||
async def __aenter__(self) -> "Session":
|
||||
"""Return self to support ``async with`` usage."""
|
||||
return self
|
||||
|
||||
async def __aexit__(self, *_exc_info: object) -> None:
|
||||
"""Close the session when leaving an ``async with`` block."""
|
||||
await self.close()
|
||||
|
||||
async def close(self, *, client_correlation_id: str = "") -> pb.CloseSessionReply:
|
||||
@@ -74,6 +77,7 @@ class Session:
|
||||
)
|
||||
|
||||
async def register(self, client_name: str, *, correlation_id: str = "") -> int:
|
||||
"""Invoke MXAccess `Register` and return the new `ServerHandle`."""
|
||||
reply = await self.invoke(
|
||||
pb.MxCommand(
|
||||
kind=pb.MX_COMMAND_KIND_REGISTER,
|
||||
@@ -84,6 +88,7 @@ class Session:
|
||||
return reply.register.server_handle
|
||||
|
||||
async def unregister(self, server_handle: int, *, correlation_id: str = "") -> None:
|
||||
"""Invoke MXAccess `Unregister` for a previously registered `ServerHandle`."""
|
||||
await self.invoke(
|
||||
pb.MxCommand(
|
||||
kind=pb.MX_COMMAND_KIND_UNREGISTER,
|
||||
@@ -99,6 +104,7 @@ class Session:
|
||||
*,
|
||||
correlation_id: str = "",
|
||||
) -> None:
|
||||
"""Invoke MXAccess `RemoveItem` for the given `ItemHandle`."""
|
||||
await self.invoke(
|
||||
pb.MxCommand(
|
||||
kind=pb.MX_COMMAND_KIND_REMOVE_ITEM,
|
||||
@@ -117,6 +123,7 @@ class Session:
|
||||
*,
|
||||
correlation_id: str = "",
|
||||
) -> int:
|
||||
"""Invoke MXAccess `AddItem` and return the new `ItemHandle`."""
|
||||
reply = await self.invoke(
|
||||
pb.MxCommand(
|
||||
kind=pb.MX_COMMAND_KIND_ADD_ITEM,
|
||||
@@ -137,6 +144,7 @@ class Session:
|
||||
*,
|
||||
correlation_id: str = "",
|
||||
) -> int:
|
||||
"""Invoke MXAccess `AddItem2` with item context and return the new `ItemHandle`."""
|
||||
reply = await self.invoke(
|
||||
pb.MxCommand(
|
||||
kind=pb.MX_COMMAND_KIND_ADD_ITEM2,
|
||||
@@ -157,6 +165,7 @@ class Session:
|
||||
*,
|
||||
correlation_id: str = "",
|
||||
) -> None:
|
||||
"""Invoke MXAccess `Advise` to subscribe an existing `ItemHandle` to events."""
|
||||
await self.invoke(
|
||||
pb.MxCommand(
|
||||
kind=pb.MX_COMMAND_KIND_ADVISE,
|
||||
@@ -175,6 +184,7 @@ class Session:
|
||||
*,
|
||||
correlation_id: str = "",
|
||||
) -> None:
|
||||
"""Invoke MXAccess `UnAdvise` to stop event delivery for an `ItemHandle`."""
|
||||
await self.invoke(
|
||||
pb.MxCommand(
|
||||
kind=pb.MX_COMMAND_KIND_UN_ADVISE,
|
||||
@@ -193,6 +203,7 @@ class Session:
|
||||
*,
|
||||
correlation_id: str = "",
|
||||
) -> list[pb.SubscribeResult]:
|
||||
"""Invoke MXAccess `AddItemBulk` and return one result per tag address."""
|
||||
if tag_addresses is None:
|
||||
raise TypeError("tag_addresses is required")
|
||||
_ensure_bulk_size("tag_addresses", len(tag_addresses))
|
||||
@@ -215,6 +226,7 @@ class Session:
|
||||
*,
|
||||
correlation_id: str = "",
|
||||
) -> list[pb.SubscribeResult]:
|
||||
"""Invoke MXAccess `AdviseItemBulk` and return one result per item handle."""
|
||||
if item_handles is None:
|
||||
raise TypeError("item_handles is required")
|
||||
_ensure_bulk_size("item_handles", len(item_handles))
|
||||
@@ -237,6 +249,7 @@ class Session:
|
||||
*,
|
||||
correlation_id: str = "",
|
||||
) -> list[pb.SubscribeResult]:
|
||||
"""Invoke MXAccess `RemoveItemBulk` and return one result per item handle."""
|
||||
if item_handles is None:
|
||||
raise TypeError("item_handles is required")
|
||||
_ensure_bulk_size("item_handles", len(item_handles))
|
||||
@@ -259,6 +272,7 @@ class Session:
|
||||
*,
|
||||
correlation_id: str = "",
|
||||
) -> list[pb.SubscribeResult]:
|
||||
"""Invoke MXAccess `UnAdviseItemBulk` and return one result per item handle."""
|
||||
if item_handles is None:
|
||||
raise TypeError("item_handles is required")
|
||||
_ensure_bulk_size("item_handles", len(item_handles))
|
||||
@@ -281,6 +295,7 @@ class Session:
|
||||
*,
|
||||
correlation_id: str = "",
|
||||
) -> list[pb.SubscribeResult]:
|
||||
"""Invoke MXAccess `SubscribeBulk` and return one result per tag address."""
|
||||
if tag_addresses is None:
|
||||
raise TypeError("tag_addresses is required")
|
||||
_ensure_bulk_size("tag_addresses", len(tag_addresses))
|
||||
@@ -303,6 +318,7 @@ class Session:
|
||||
*,
|
||||
correlation_id: str = "",
|
||||
) -> list[pb.SubscribeResult]:
|
||||
"""Invoke MXAccess `UnsubscribeBulk` and return one result per item handle."""
|
||||
if item_handles is None:
|
||||
raise TypeError("item_handles is required")
|
||||
_ensure_bulk_size("item_handles", len(item_handles))
|
||||
@@ -327,6 +343,7 @@ class Session:
|
||||
user_id: int = 0,
|
||||
correlation_id: str = "",
|
||||
) -> None:
|
||||
"""Invoke MXAccess `Write` for an `ItemHandle` with the converted value."""
|
||||
await self.invoke(
|
||||
pb.MxCommand(
|
||||
kind=pb.MX_COMMAND_KIND_WRITE,
|
||||
@@ -350,6 +367,7 @@ class Session:
|
||||
user_id: int = 0,
|
||||
correlation_id: str = "",
|
||||
) -> None:
|
||||
"""Invoke MXAccess `Write2` with both a value and a client-supplied timestamp."""
|
||||
await self.invoke(
|
||||
pb.MxCommand(
|
||||
kind=pb.MX_COMMAND_KIND_WRITE2,
|
||||
@@ -369,6 +387,7 @@ class Session:
|
||||
*,
|
||||
after_worker_sequence: int = 0,
|
||||
) -> AsyncIterator[pb.MxEvent]:
|
||||
"""Return an async iterator of `MxEvent` messages for this session."""
|
||||
return self.client.stream_events_raw(
|
||||
pb.StreamEventsRequest(
|
||||
session_id=self.session_id,
|
||||
|
||||
@@ -42,6 +42,7 @@ def version(output_json: bool) -> None:
|
||||
|
||||
|
||||
def gateway_options(command: Callable[..., Any]) -> Callable[..., Any]:
|
||||
"""Apply the shared gateway connection options to a Click command."""
|
||||
command = click.option("--endpoint", default="localhost:5000", show_default=True)(command)
|
||||
command = click.option("--api-key", default=None, help="Gateway API key.")(command)
|
||||
command = click.option(
|
||||
|
||||
Reference in New Issue
Block a user