# Python Client The Python client package contains generated MXAccess Gateway protobuf bindings, the async `mxgateway` package, and the `mxgw-py` test CLI. The package uses the shared proto inputs documented in `../../docs/client-proto-generation.md` so gateway and client contracts stay in sync. ## Layout ```text clients/python/ pyproject.toml generate-proto.ps1 src/mxgateway/ src/mxgateway/generated/ src/mxgateway_cli/ tests/ ``` `src/mxgateway/generated` contains code produced by `grpc_tools.protoc`. Do not edit generated files by hand. ## Regenerating Protobuf Bindings Run generation after the shared `.proto` files or the Python output path changes: ```powershell ./generate-proto.ps1 ``` The script uses the Python tool path recorded in `../../docs/toolchain-links.md`. ## Build And Test Run the Python checks from `clients/python`: ```powershell python -m pip install -e ".[dev]" python -m pytest python -m pip wheel . --no-deps --wheel-dir "$env:TEMP\mxgateway-python-wheel" ``` The tests import the generated gateway and worker stubs, run fake async gateway stubs, verify API key metadata, exercise stream cancellation, load shared value and command fixtures, and check deterministic CLI output. ## Library Usage The library is async-first: ```python from mxgateway import GatewayClient async with await GatewayClient.connect( endpoint="localhost:5000", api_key="mxgw_example", plaintext=True, ) as client: session = await client.open_session(client_session_name="python-client") try: server_handle = await session.register("python-client") item_handle = await session.add_item(server_handle, "Object.Attribute") await session.advise(server_handle, item_handle) finally: await session.close() ``` `GatewayClient.open_session_raw`, `GatewayClient.invoke_raw`, and `GatewayClient.stream_events_raw` keep the generated protobuf replies and events available for parity tests. `Session` helpers call the method-specific MXAccess commands and preserve raw replies on typed command exceptions. Canceling a Python task cancels the client-side gRPC call or stream wait. It does not abort an in-flight MXAccess COM call inside the worker process. ## Authentication And TLS `ClientOptions.api_key` adds this metadata to unary calls and streams: ```text authorization: Bearer ``` The client supports plaintext channels for local development, TLS with system roots, TLS with a custom `ca_file`, and an optional test server name override. API keys are redacted from option repr output and CLI error output. ## CLI The CLI emits deterministic JSON for automation: ```powershell mxgw-py version --json mxgw-py open-session --endpoint localhost:5000 --plaintext --json mxgw-py register --session-id --client-name python-client --json mxgw-py add-item --session-id --server-handle 1 --item Object.Attribute --json mxgw-py advise --session-id --server-handle 1 --item-handle 2 --json mxgw-py stream-events --session-id --max-events 1 --json mxgw-py write --session-id --server-handle 1 --item-handle 2 --type int32 --value 123 --json ``` Use `--api-key` or `--api-key-env MXGATEWAY_API_KEY` to attach API key metadata. `smoke` opens a session, registers, adds an item, advises, streams a bounded event count, and closes the session in a `finally` block.