Skip to content

Commit 4fba45f

Browse files
rustyconoverclaude
andcommitted
Add --describe flag to run_server for introspection support
Add a --describe CLI flag to run_server() that passes enable_describe=True to RpcServer, allowing non-Python clients to use __describe__ introspection over pipe and HTTP transports. Simplify serve_conformance_http.py to use run_server instead of manual waitress setup. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 4193bb0 commit 4fba45f

2 files changed

Lines changed: 15 additions & 33 deletions

File tree

tests/serve_conformance_http.py

Lines changed: 4 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -5,38 +5,16 @@
55
66
Can be run directly: ``python -m tests.serve_conformance_http``
77
8-
Starts a waitress HTTP server exposing the conformance RPC service, prints
9-
``PORT:<n>`` to stdout so the parent process can discover the port.
8+
Starts an HTTP server exposing the conformance RPC service via ``run_server --http``.
109
"""
1110

12-
import socket
13-
import sys
14-
15-
import waitress
16-
1711
from vgi_rpc.conformance import ConformanceService, ConformanceServiceImpl
18-
from vgi_rpc.http import make_wsgi_app
19-
from vgi_rpc.rpc import RpcServer
20-
21-
22-
def _find_free_port() -> int:
23-
"""Find a free TCP port on localhost."""
24-
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
25-
s.bind(("127.0.0.1", 0))
26-
return int(s.getsockname()[1])
12+
from vgi_rpc.rpc import run_server
2713

2814

2915
def main() -> None:
30-
"""Start a waitress HTTP server for the conformance service."""
31-
port = int(sys.argv[1]) if len(sys.argv) > 1 else _find_free_port()
32-
33-
server = RpcServer(ConformanceService, ConformanceServiceImpl())
34-
app = make_wsgi_app(server)
35-
36-
# Signal the port to the parent process
37-
print(f"PORT:{port}", flush=True)
38-
39-
waitress.serve(app, host="127.0.0.1", port=port, _quiet=True)
16+
"""Start an HTTP server for the conformance service."""
17+
run_server(ConformanceService, ConformanceServiceImpl())
4018

4119

4220
if __name__ == "__main__":

vgi_rpc/rpc/__init__.py

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,7 @@ def run_server(protocol_or_server: type | RpcServer, implementation: object | No
284284
``vgi-rpc[http]``).
285285
- ``--host HOST`` — HTTP bind address (default ``127.0.0.1``).
286286
- ``--port PORT`` — HTTP port (default ``0``, auto-select).
287+
- ``--describe`` — Enable the ``__describe__`` introspection method.
287288
288289
Without ``--http`` the server runs over stdin/stdout pipes (the
289290
default, suitable for ``SubprocessTransport``).
@@ -299,23 +300,26 @@ def run_server(protocol_or_server: type | RpcServer, implementation: object | No
299300
TypeError: On invalid argument combinations.
300301
301302
"""
303+
parser = argparse.ArgumentParser(description="vgi-rpc server")
304+
parser.add_argument("--http", action="store_true", default=False, help="Serve over HTTP instead of stdin/stdout")
305+
parser.add_argument("--host", default="127.0.0.1", help="HTTP bind address (default: 127.0.0.1)")
306+
parser.add_argument("--port", type=int, default=0, help="HTTP port (default: auto-select)")
307+
parser.add_argument(
308+
"--describe", action="store_true", default=False, help="Enable __describe__ introspection method"
309+
)
310+
args = parser.parse_args()
311+
302312
if isinstance(protocol_or_server, RpcServer):
303313
if implementation is not None:
304314
raise TypeError("implementation must be None when passing an RpcServer")
305315
server = protocol_or_server
306316
elif isinstance(protocol_or_server, type):
307317
if implementation is None:
308318
raise TypeError("implementation is required when passing a Protocol class")
309-
server = RpcServer(protocol_or_server, implementation)
319+
server = RpcServer(protocol_or_server, implementation, enable_describe=args.describe)
310320
else:
311321
raise TypeError(f"Expected a Protocol class or RpcServer, got {type(protocol_or_server).__name__}")
312322

313-
parser = argparse.ArgumentParser(description="vgi-rpc server")
314-
parser.add_argument("--http", action="store_true", default=False, help="Serve over HTTP instead of stdin/stdout")
315-
parser.add_argument("--host", default="127.0.0.1", help="HTTP bind address (default: 127.0.0.1)")
316-
parser.add_argument("--port", type=int, default=0, help="HTTP port (default: auto-select)")
317-
args = parser.parse_args()
318-
319323
if args.http:
320324
try:
321325
from vgi_rpc.http import serve_http

0 commit comments

Comments
 (0)