Modernize X-Plane Web API client - #2
Conversation
There was a problem hiding this comment.
Pull request overview
Modernizes the xpwebapi Python client by adding async REST support, typed caches, structured logging configuration, retry/backoff helpers, and expanded quality tooling/docs, while migrating the WebSocket/REST clients to newer dependencies and type annotations.
Changes:
- Introduces retry/backoff utilities, typed exception hierarchy, and structured logging configuration helpers.
- Reworks REST/WebSocket/UDP clients for updated transport libraries (httpx/websockets), connection pooling, and context-managed cleanup.
- Adds extensive
unittestcoverage plus repo-local quality gates, CI updates, and expanded docs/examples.
Reviewed changes
Copilot reviewed 53 out of 55 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| xpwebapi/ws.py | WebSocket client migrated to websockets, retry support, batching, cleanup helpers |
| xpwebapi/udp.py | UDP client cleanup/context manager, packet validation, typed errors |
| xpwebapi/retry.py | New retry config + sync/async backoff helpers |
| xpwebapi/rest.py | Switch to httpx, retry handling, optional client pooling, typed caches |
| xpwebapi/logging_config.py | New validated logging config + JSON formatter + helper APIs |
| xpwebapi/exceptions.py | New typed exception hierarchy with context |
| xpwebapi/beacon.py | Beacon monitor retries + typed errors + socket option tweaks |
| xpwebapi/async_rest.py | New async REST client built on httpx.AsyncClient |
| xpwebapi/api.py | Core typing modernization, typed caches, protocol-based API surface |
| xpwebapi/init.py | Package exports expanded (async REST, logging, exceptions) |
| tools/quality.py | New local quality-gate runner orchestrating lint/test/security/docs |
| tests/test_ws.py | WebSocket behavior tests (send/connect/retry/listener/batching) |
| tests/test_udp.py | UDP behavior tests (packets, monitoring, typed errors, lifecycle) |
| tests/test_type_annotations.py | Enforces typing modernization and Self returns for context managers |
| tests/test_rest.py | REST tests for pooling/retries/meta/value/command behaviors |
| tests/test_quality_tool.py | Tests the quality tool step registry and execution behavior |
| tests/test_logging_config.py | Tests logging config validation, handler management, JSON formatting |
| tests/test_exceptions.py | Tests exception hierarchy + backward-compat types |
| tests/test_documentation.py | Validates docs/examples conventions and mkdocs navigation |
| tests/test_beacon.py | Beacon decoding/retry/version/host logic tests |
| tests/test_async_rest.py | Async REST lifecycle/retry/meta/value/write/command tests |
| tests/test_api.py | Tests core entities (Dataref/Command), caches, ValueCache, protocol shape |
| tests/helpers.py | Shared test helpers, dummy API, packet generators |
| tests/init.py | Silences package loggers during test runs |
| pyproject.toml | Dependency updates (httpx/websockets/pydantic), tooling config, build backend |
| mkdocs.yml | MkDocs nav expanded; git revision date plugin configured |
| docs/usage/index.md | Expanded usage guide with lifecycle/monitoring/commands examples |
| docs/reference/websocket.md | New mkdocstrings reference stub |
| docs/reference/udp.md | New mkdocstrings reference stub |
| docs/reference/rest.md | New mkdocstrings reference stub |
| docs/reference/package.md | New mkdocstrings reference stub |
| docs/reference/logging.md | New mkdocstrings reference stub |
| docs/reference/index.md | Reference landing page updated with links |
| docs/reference/exceptions.md | New mkdocstrings reference stub |
| docs/reference/core-api.md | New mkdocstrings reference stub |
| docs/reference/beacon.md | New mkdocstrings reference stub |
| docs/reference/async-rest.md | New mkdocstrings reference stub |
| .secrets.baseline | Adds detect-secrets baseline |
| .python-version | Pins Python 3.12 |
| .pre-commit-config.yaml | Adds pre-commit hooks for quality gates and reports |
| .gitignore | Updates ignores for new tooling caches/worktrees |
| .github/workflows/ci.yml | CI split into quality + docs deploy, uv-based installs |
| examples/xpwsapp.py | Adds missing annotations/return types in example base app |
| examples/xgs.py | Typing/return annotations and minor API typing fixes in example |
| examples/unitutil.py | Adds typing to helpers |
| examples/template.py | Adds return annotation for loop |
| examples/simple_ws.py | Adds return annotations for callbacks |
| examples/simple_upd.py | Adds return annotations for callbacks |
| examples/simple_monitor.py | Adds return annotations for callbacks |
| examples/simple_beacon.py | Adds return annotation for callback |
| examples/posreport.py | Tightens typing for example class init/loop |
| examples/oooi.py | Tightens typing across example manager methods |
| examples/geoutil.py | Adds return annotations for helpers |
| examples/fdr.py | Tightens typing for example class and helpers |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| @@ -405,13 +445,20 @@ | |||
| payload[REST_KW.REQID.value] = req_id | |||
| self._requests[req_id] = Request(r_id=req_id, body=payload, ts=now()) | |||
| self.inc("send") | |||
| self.ws.send(json.dumps(payload)) | |||
| if self.ws is not None: | |||
| if self.ws is None: | ||
| continue |
| sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) | ||
| sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1) # SO_REUSEPORT? | ||
| sock.setsockopt(socket.SOL_SOCKET, getattr(socket, "SO_REUSEPORT"), 1) # SO_REUSEPORT? |
| else: | ||
| sock.setsockopt(socket.SOL_SOCKET, getattr(socket, "SO_REUSEPORT"), 1) | ||
| sock.bind((self.MCAST_GRP, self.MCAST_PORT)) |
|
I wasn't sure if any updates/prs were welcome, but I took a chance. The library is very useful and I appreciate an opportunity to suggest these improvements. |
|
Thank you for creating and sharing xplane-webapi; it gave this work a I’m leaving this PR open for you to disposition as you prefer, but I’ll be |
Summary
unittestcoverage across REST, async REST, WebSocket, UDP, beacon, logging, docs, and quality tooling.auto_saveusage, aligning README development setup withuv sync, preventing WebSocket ghost requests when the socket disappears before send, avoiding WebSocket listener busy-waiting while disconnected, and guarding UDP/beacon multicast socket options on platforms withoutSO_REUSEPORT.Validation
uv run python -m unittest discover -v- 229 tests passed.uv run python tools\quality.py check- passed: ruff, format check, ty, unittest, coverage, bandit, detect-secrets, interrogate, vulture, and xenon.Notes
devleaks/main.