Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions buf.gen.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
version: v2
plugins:
# NOTE: v26.0 is the earliest version supporting protobuf==5.
- remote: buf.build/protocolbuffers/python:v26.0
out: src/connectrpc/_gen
- remote: buf.build/protocolbuffers/pyi:v26.0
out: src/connectrpc/_gen
3 changes: 3 additions & 0 deletions buf.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
version: v2
modules:
- path: proto
3 changes: 2 additions & 1 deletion conformance/test/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ features:
- HTTP_VERSION_2
protocols:
- PROTOCOL_CONNECT
- PROTOCOL_GRPC
codecs:
- CODEC_PROTO
- CODEC_JSON
Expand All @@ -21,7 +22,7 @@ features:
supports_h2c: true
supports_tls: true
supports_tls_client_certs: true
supports_trailers: false
supports_trailers: true
supports_half_duplex_bidi_over_http1: true
supports_connect_get: true
# This currently only tests the server
Expand Down
15 changes: 15 additions & 0 deletions conformance/test/test_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,22 @@
_client_py_path = str(_current_dir / "client.py")
_config_path = str(_current_dir / "config.yaml")

_skipped_tests = [
# Not implemented yet,
"--skip",
"**/Protocol:PROTOCOL_GRPC/**",
"--skip",
"gRPC Trailers/**",
"--skip",
"gRPC Unexpected Responses/**",
"--skip",
"gRPC Empty Responses/**",
"--skip",
"gRPC Proto Sub-Format Responses/**",
]

_skipped_tests_sync = [
*_skipped_tests,
# Need to use async APIs for proper cancellation support in Python.
"--skip",
"Client Cancellation/**",
Expand Down Expand Up @@ -46,6 +60,7 @@ def test_client_sync() -> None:


_skipped_tests_async = [
*_skipped_tests,
# Cancellation currently not working for full duplex
"--skip",
"Client Cancellation/**/full-duplex/**",
Expand Down
13 changes: 7 additions & 6 deletions conformance/test/test_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,6 @@ def macos_raise_ulimit():

@pytest.mark.parametrize("server", ["gunicorn", "pyvoy"])
def test_server_sync(server: str) -> None:
if server == "pyvoy" and sys.platform == "win32":
pytest.skip("pyvoy not supported on Windows")

args = maybe_patch_args_with_debug(
[sys.executable, _server_py_path, "--mode", "sync", "--server", server]
)
Expand Down Expand Up @@ -77,9 +74,6 @@ def test_server_sync(server: str) -> None:

@pytest.mark.parametrize("server", ["daphne", "pyvoy", "uvicorn"])
def test_server_async(server: str) -> None:
if server == "pyvoy" and sys.platform == "win32":
pytest.skip("pyvoy not supported on Windows")

args = maybe_patch_args_with_debug(
[sys.executable, _server_py_path, "--mode", "async", "--server", server]
)
Expand All @@ -94,6 +88,13 @@ def test_server_async(server: str) -> None:
# it only works with websockets
"--skip",
"**/full-duplex/**",
# daphne doesn't support trailers
"--skip",
"**/Protocol:PROTOCOL_GRPC/**",
"--skip",
"gRPC Proto Sub-Format Requests/**",
"--skip",
"gRPC Unexpected Requests/**",
]
case "uvicorn":
# uvicorn doesn't support HTTP/2
Expand Down
2 changes: 2 additions & 0 deletions example/buf.gen.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ plugins:
out: .
- remote: buf.build/protocolbuffers/pyi:v26.0
out: .
- remote: buf.build/grpc/python:v1.76.0
out: .
- local:
- go
- run
Expand Down
207 changes: 207 additions & 0 deletions example/example/eliza_pb2_grpc.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,207 @@
# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT!
"""Client and server classes corresponding to protobuf-defined services."""

from __future__ import annotations

import grpc

from example import eliza_pb2 as example_dot_eliza__pb2


class ElizaServiceStub:
"""ElizaService provides a way to talk to Eliza, a port of the DOCTOR script
for Joseph Weizenbaum's original ELIZA program. Created in the mid-1960s at
the MIT Artificial Intelligence Laboratory, ELIZA demonstrates the
superficiality of human-computer communication. DOCTOR simulates a
psychotherapist, and is commonly found as an Easter egg in emacs
distributions.
"""

def __init__(self, channel):
"""Constructor.

Args:
channel: A grpc.Channel.
"""
self.Say = channel.unary_unary(
"/connectrpc.eliza.v1.ElizaService/Say",
request_serializer=example_dot_eliza__pb2.SayRequest.SerializeToString,
response_deserializer=example_dot_eliza__pb2.SayResponse.FromString,
_registered_method=True,
)
self.Converse = channel.stream_stream(
"/connectrpc.eliza.v1.ElizaService/Converse",
request_serializer=example_dot_eliza__pb2.ConverseRequest.SerializeToString,
response_deserializer=example_dot_eliza__pb2.ConverseResponse.FromString,
_registered_method=True,
)
self.Introduce = channel.unary_stream(
"/connectrpc.eliza.v1.ElizaService/Introduce",
request_serializer=example_dot_eliza__pb2.IntroduceRequest.SerializeToString,
response_deserializer=example_dot_eliza__pb2.IntroduceResponse.FromString,
_registered_method=True,
)


class ElizaServiceServicer:
"""ElizaService provides a way to talk to Eliza, a port of the DOCTOR script
for Joseph Weizenbaum's original ELIZA program. Created in the mid-1960s at
the MIT Artificial Intelligence Laboratory, ELIZA demonstrates the
superficiality of human-computer communication. DOCTOR simulates a
psychotherapist, and is commonly found as an Easter egg in emacs
distributions.
"""

def Say(self, request, context):
"""Say is a unary RPC. Eliza responds to the prompt with a single sentence."""
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details("Method not implemented!")
msg = "Method not implemented!"
raise NotImplementedError(msg)

def Converse(self, request_iterator, context):
"""Converse is a bidirectional RPC. The caller may exchange multiple
back-and-forth messages with Eliza over a long-lived connection. Eliza
responds to each ConverseRequest with a ConverseResponse.
"""
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details("Method not implemented!")
msg = "Method not implemented!"
raise NotImplementedError(msg)

def Introduce(self, request, context):
"""Introduce is a server streaming RPC. Given the caller's name, Eliza
returns a stream of sentences to introduce itself.
"""
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details("Method not implemented!")
msg = "Method not implemented!"
raise NotImplementedError(msg)


def add_ElizaServiceServicer_to_server(servicer, server):
rpc_method_handlers = {
"Say": grpc.unary_unary_rpc_method_handler(
servicer.Say,
request_deserializer=example_dot_eliza__pb2.SayRequest.FromString,
response_serializer=example_dot_eliza__pb2.SayResponse.SerializeToString,
),
"Converse": grpc.stream_stream_rpc_method_handler(
servicer.Converse,
request_deserializer=example_dot_eliza__pb2.ConverseRequest.FromString,
response_serializer=example_dot_eliza__pb2.ConverseResponse.SerializeToString,
),
"Introduce": grpc.unary_stream_rpc_method_handler(
servicer.Introduce,
request_deserializer=example_dot_eliza__pb2.IntroduceRequest.FromString,
response_serializer=example_dot_eliza__pb2.IntroduceResponse.SerializeToString,
),
}
generic_handler = grpc.method_handlers_generic_handler(
"connectrpc.eliza.v1.ElizaService", rpc_method_handlers
)
server.add_generic_rpc_handlers((generic_handler,))
server.add_registered_method_handlers(
"connectrpc.eliza.v1.ElizaService", rpc_method_handlers
)


# This class is part of an EXPERIMENTAL API.
class ElizaService:
"""ElizaService provides a way to talk to Eliza, a port of the DOCTOR script
for Joseph Weizenbaum's original ELIZA program. Created in the mid-1960s at
the MIT Artificial Intelligence Laboratory, ELIZA demonstrates the
superficiality of human-computer communication. DOCTOR simulates a
psychotherapist, and is commonly found as an Easter egg in emacs
distributions.
"""

@staticmethod
def Say(
request,
target,
options=(),
channel_credentials=None,
call_credentials=None,
insecure=False,
compression=None,
wait_for_ready=None,
timeout=None,
metadata=None,
):
return grpc.experimental.unary_unary(
request,
target,
"/connectrpc.eliza.v1.ElizaService/Say",
example_dot_eliza__pb2.SayRequest.SerializeToString,
example_dot_eliza__pb2.SayResponse.FromString,
options,
channel_credentials,
insecure,
call_credentials,
compression,
wait_for_ready,
timeout,
metadata,
_registered_method=True,
)

@staticmethod
def Converse(
request_iterator,
target,
options=(),
channel_credentials=None,
call_credentials=None,
insecure=False,
compression=None,
wait_for_ready=None,
timeout=None,
metadata=None,
):
return grpc.experimental.stream_stream(
request_iterator,
target,
"/connectrpc.eliza.v1.ElizaService/Converse",
example_dot_eliza__pb2.ConverseRequest.SerializeToString,
example_dot_eliza__pb2.ConverseResponse.FromString,
options,
channel_credentials,
insecure,
call_credentials,
compression,
wait_for_ready,
timeout,
metadata,
_registered_method=True,
)

@staticmethod
def Introduce(
request,
target,
options=(),
channel_credentials=None,
call_credentials=None,
insecure=False,
compression=None,
wait_for_ready=None,
timeout=None,
metadata=None,
):
return grpc.experimental.unary_stream(
request,
target,
"/connectrpc.eliza.v1.ElizaService/Introduce",
example_dot_eliza__pb2.IntroduceRequest.SerializeToString,
example_dot_eliza__pb2.IntroduceResponse.FromString,
options,
channel_credentials,
insecure,
call_credentials,
compression,
wait_for_ready,
timeout,
metadata,
_registered_method=True,
)
6 changes: 5 additions & 1 deletion justfile
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ docs:
docs-serve: docs
uv run python -m http.server 8000

# Generate gRPC status
generate-status:
go run github.com/bufbuild/buf/cmd/buf@{{BUF_VERSION}} generate

# Generate conformance files
[working-directory: 'conformance']
generate-conformance:
Expand All @@ -65,7 +69,7 @@ generate-test:
go run github.com/bufbuild/buf/cmd/buf@{{BUF_VERSION}} generate

# Run all generation targets, and format the generated code
generate: generate-conformance generate-example generate-test format
generate: generate-conformance generate-example generate-status generate-test format

# Used in CI to verify that `just generate` doesn't produce a diff
checkgenerate: generate
Expand Down
Loading