aboutsummaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
authorXuan Wang <xuanwn@google.com>2023-02-03 14:11:27 -0800
committerGitHub <noreply@github.com>2023-02-03 14:11:27 -0800
commita190831789b514e9f740a78b0dcd03fe79bfdd50 (patch)
treee02423b2072ead564e7ba88d3ee51de3d88d8a10 /examples
parent1f960697c5020db85743a68b3533b8ef45a9629e (diff)
downloadgrpc-grpc-a190831789b514e9f740a78b0dcd03fe79bfdd50.tar.gz
Add examples for timeout, kepp_alive, reflection and health_checking (#32243)
* Add timeout example * Add pb2 file to example * Remove .proto file * Add keep_alive example * Add refelction client * fixes * Add example for health_check * Changes based on comments * Fix pylint
Diffstat (limited to 'examples')
-rw-r--r--examples/python/Makefile21
-rw-r--r--examples/python/health_checking/greeter_client.py56
-rw-r--r--examples/python/health_checking/greeter_server.py74
-rw-r--r--examples/python/health_checking/helloworld_pb2.py30
-rw-r--r--examples/python/health_checking/helloworld_pb2.pyi17
-rw-r--r--examples/python/health_checking/helloworld_pb2_grpc.py70
-rw-r--r--examples/python/helloworld/greeter_client_reflection.py46
-rw-r--r--examples/python/keep_alive/greeter_client.py67
-rw-r--r--examples/python/keep_alive/greeter_server.py74
-rw-r--r--examples/python/keep_alive/helloworld_pb2.py30
-rw-r--r--examples/python/keep_alive/helloworld_pb2.pyi17
-rw-r--r--examples/python/keep_alive/helloworld_pb2_grpc.py70
-rw-r--r--examples/python/timeout/greeter_client.py45
-rw-r--r--examples/python/timeout/greeter_server.py46
-rw-r--r--examples/python/timeout/helloworld_pb2.py30
-rw-r--r--examples/python/timeout/helloworld_pb2.pyi17
-rw-r--r--examples/python/timeout/helloworld_pb2_grpc.py70
17 files changed, 780 insertions, 0 deletions
diff --git a/examples/python/Makefile b/examples/python/Makefile
index 8f41590ffd..323e6b6bfb 100644
--- a/examples/python/Makefile
+++ b/examples/python/Makefile
@@ -20,6 +20,18 @@ ARTIFACTS += helloworld/helloworld_pb2.py
ARTIFACTS += helloworld/helloworld_pb2_grpc.py
ARTIFACTS += helloworld/helloworld_pb2.pyi
+ARTIFACTS += timeout/helloworld_pb2.py
+ARTIFACTS += timeout/helloworld_pb2_grpc.py
+ARTIFACTS += timeout/helloworld_pb2.pyi
+
+ARTIFACTS += keep_alive/helloworld_pb2.py
+ARTIFACTS += keep_alive/helloworld_pb2_grpc.py
+ARTIFACTS += keep_alive/helloworld_pb2.pyi
+
+ARTIFACTS += health_checking/helloworld_pb2.py
+ARTIFACTS += health_checking/helloworld_pb2_grpc.py
+ARTIFACTS += health_checking/helloworld_pb2.pyi
+
ARTIFACTS += async_streaming/phone_pb2.py
ARTIFACTS += async_streaming/phone_pb2_grpc.py
ARTIFACTS += async_streaming/phone_pb2.pyi
@@ -74,6 +86,15 @@ all: ${ARTIFACTS}
helloworld/helloworld_pb2.py helloworld/helloworld_pb2_grpc.py helloworld/helloworld_pb2.pyi: ../protos/helloworld.proto
python3 -m grpc_tools.protoc --python_out=helloworld --grpc_python_out=helloworld --pyi_out=helloworld -I ../protos ../protos/helloworld.proto
+timeout/helloworld_pb2.py timeout/helloworld_pb2_grpc.py timeout/helloworld_pb2.pyi: ../protos/helloworld.proto
+ python3 -m grpc_tools.protoc --python_out=timeout --grpc_python_out=timeout --pyi_out=timeout -I ../protos ../protos/helloworld.proto
+
+keep_alive/helloworld_pb2.py keep_alive/helloworld_pb2_grpc.py keep_alive/helloworld_pb2.pyi: ../protos/helloworld.proto
+ python3 -m grpc_tools.protoc --python_out=keep_alive --grpc_python_out=keep_alive --pyi_out=keep_alive -I ../protos ../protos/helloworld.proto
+
+health_checking/helloworld_pb2.py health_checking/helloworld_pb2_grpc.py health_checking/helloworld_pb2.pyi: ../protos/helloworld.proto
+ python3 -m grpc_tools.protoc --python_out=health_checking --grpc_python_out=health_checking --pyi_out=health_checking -I ../protos ../protos/helloworld.proto
+
async_streaming/phone_pb2.py async_streaming/phone_pb2_grpc.py async_streaming/phone_pb2.pyi: async_streaming/phone.proto
python3 -m grpc_tools.protoc --python_out=async_streaming --grpc_python_out=async_streaming --pyi_out=async_streaming -I async_streaming async_streaming/phone.proto
diff --git a/examples/python/health_checking/greeter_client.py b/examples/python/health_checking/greeter_client.py
new file mode 100644
index 0000000000..9405c1ef5b
--- /dev/null
+++ b/examples/python/health_checking/greeter_client.py
@@ -0,0 +1,56 @@
+# Copyright 2023 gRPC authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""gRPC Python helloworld.Greeter client with health checking."""
+
+import logging
+from time import sleep
+
+import grpc
+from grpc_health.v1 import health_pb2
+from grpc_health.v1 import health_pb2_grpc
+import helloworld_pb2
+import helloworld_pb2_grpc
+
+
+def unary_call(stub: helloworld_pb2_grpc.GreeterStub, message: str):
+ response = stub.SayHello(helloworld_pb2.HelloRequest(name=message),
+ timeout=3)
+ print(f"Greeter client received: {response.message}")
+
+
+def health_check_call(stub: health_pb2_grpc.HealthStub):
+ request = health_pb2.HealthCheckRequest(service="helloworld.Greeter")
+ resp = stub.Check(request)
+ if resp.status == health_pb2.HealthCheckResponse.SERVING:
+ print("server is serving")
+ elif resp.status == health_pb2.HealthCheckResponse.NOT_SERVING:
+ print("server stopped serving")
+
+
+def run():
+ with grpc.insecure_channel('localhost:50051') as channel:
+ stub = helloworld_pb2_grpc.GreeterStub(channel)
+ health_stub = health_pb2_grpc.HealthStub(channel)
+ # Should succeed
+ unary_call(stub, 'you')
+
+ # Check health status every 1 second for 30 seconds
+ for _ in range(30):
+ health_check_call(health_stub)
+ sleep(1)
+
+
+if __name__ == '__main__':
+ logging.basicConfig()
+ run()
diff --git a/examples/python/health_checking/greeter_server.py b/examples/python/health_checking/greeter_server.py
new file mode 100644
index 0000000000..d10fd87adc
--- /dev/null
+++ b/examples/python/health_checking/greeter_server.py
@@ -0,0 +1,74 @@
+# Copyright 2023 gRPC authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""The Python implementation of the GRPC helloworld.Greeter server with health checking."""
+
+from concurrent import futures
+import logging
+import threading
+from time import sleep
+
+import grpc
+from grpc_health.v1 import health
+from grpc_health.v1 import health_pb2
+from grpc_health.v1 import health_pb2_grpc
+import helloworld_pb2
+import helloworld_pb2_grpc
+
+
+class Greeter(helloworld_pb2_grpc.GreeterServicer):
+
+ def SayHello(self, request, context):
+ return helloworld_pb2.HelloReply(message=request.name)
+
+
+def _toggle_health(health_servicer: health.HealthServicer, service: str):
+ next_status = health_pb2.HealthCheckResponse.SERVING
+ while True:
+ if next_status == health_pb2.HealthCheckResponse.SERVING:
+ next_status = health_pb2.HealthCheckResponse.NOT_SERVING
+ else:
+ next_status = health_pb2.HealthCheckResponse.SERVING
+
+ health_servicer.set(service, next_status)
+ sleep(5)
+
+
+def _configure_health_server(server: grpc.Server):
+ health_servicer = health.HealthServicer(
+ experimental_non_blocking=True,
+ experimental_thread_pool=futures.ThreadPoolExecutor(max_workers=10))
+ health_pb2_grpc.add_HealthServicer_to_server(health_servicer, server)
+
+ # Use a daemon thread to toggle health status
+ toggle_health_status_thread = threading.Thread(target=_toggle_health,
+ args=(health_servicer,
+ "helloworld.Greeter"),
+ daemon=True)
+ toggle_health_status_thread.start()
+
+
+def serve():
+ port = '50051'
+ server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
+ helloworld_pb2_grpc.add_GreeterServicer_to_server(Greeter(), server)
+ server.add_insecure_port('[::]:' + port)
+ _configure_health_server(server)
+ server.start()
+ print("Server started, listening on " + port)
+ server.wait_for_termination()
+
+
+if __name__ == '__main__':
+ logging.basicConfig()
+ serve()
diff --git a/examples/python/health_checking/helloworld_pb2.py b/examples/python/health_checking/helloworld_pb2.py
new file mode 100644
index 0000000000..f5b4f2d27d
--- /dev/null
+++ b/examples/python/health_checking/helloworld_pb2.py
@@ -0,0 +1,30 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# source: helloworld.proto
+"""Generated protocol buffer code."""
+from google.protobuf.internal import builder as _builder
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import symbol_database as _symbol_database
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x10helloworld.proto\x12\nhelloworld\"\x1c\n\x0cHelloRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\"\x1d\n\nHelloReply\x12\x0f\n\x07message\x18\x01 \x01(\t2I\n\x07Greeter\x12>\n\x08SayHello\x12\x18.helloworld.HelloRequest\x1a\x16.helloworld.HelloReply\"\x00\x42\x36\n\x1bio.grpc.examples.helloworldB\x0fHelloWorldProtoP\x01\xa2\x02\x03HLWb\x06proto3')
+
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals())
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'helloworld_pb2', globals())
+if _descriptor._USE_C_DESCRIPTORS == False:
+
+ DESCRIPTOR._options = None
+ DESCRIPTOR._serialized_options = b'\n\033io.grpc.examples.helloworldB\017HelloWorldProtoP\001\242\002\003HLW'
+ _HELLOREQUEST._serialized_start=32
+ _HELLOREQUEST._serialized_end=60
+ _HELLOREPLY._serialized_start=62
+ _HELLOREPLY._serialized_end=91
+ _GREETER._serialized_start=93
+ _GREETER._serialized_end=166
+# @@protoc_insertion_point(module_scope)
diff --git a/examples/python/health_checking/helloworld_pb2.pyi b/examples/python/health_checking/helloworld_pb2.pyi
new file mode 100644
index 0000000000..8c4b5b2280
--- /dev/null
+++ b/examples/python/health_checking/helloworld_pb2.pyi
@@ -0,0 +1,17 @@
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import message as _message
+from typing import ClassVar as _ClassVar, Optional as _Optional
+
+DESCRIPTOR: _descriptor.FileDescriptor
+
+class HelloReply(_message.Message):
+ __slots__ = ["message"]
+ MESSAGE_FIELD_NUMBER: _ClassVar[int]
+ message: str
+ def __init__(self, message: _Optional[str] = ...) -> None: ...
+
+class HelloRequest(_message.Message):
+ __slots__ = ["name"]
+ NAME_FIELD_NUMBER: _ClassVar[int]
+ name: str
+ def __init__(self, name: _Optional[str] = ...) -> None: ...
diff --git a/examples/python/health_checking/helloworld_pb2_grpc.py b/examples/python/health_checking/helloworld_pb2_grpc.py
new file mode 100644
index 0000000000..47c186976e
--- /dev/null
+++ b/examples/python/health_checking/helloworld_pb2_grpc.py
@@ -0,0 +1,70 @@
+# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT!
+"""Client and server classes corresponding to protobuf-defined services."""
+import grpc
+
+import helloworld_pb2 as helloworld__pb2
+
+
+class GreeterStub(object):
+ """The greeting service definition.
+ """
+
+ def __init__(self, channel):
+ """Constructor.
+
+ Args:
+ channel: A grpc.Channel.
+ """
+ self.SayHello = channel.unary_unary(
+ '/helloworld.Greeter/SayHello',
+ request_serializer=helloworld__pb2.HelloRequest.SerializeToString,
+ response_deserializer=helloworld__pb2.HelloReply.FromString,
+ )
+
+
+class GreeterServicer(object):
+ """The greeting service definition.
+ """
+
+ def SayHello(self, request, context):
+ """Sends a greeting
+ """
+ context.set_code(grpc.StatusCode.UNIMPLEMENTED)
+ context.set_details('Method not implemented!')
+ raise NotImplementedError('Method not implemented!')
+
+
+def add_GreeterServicer_to_server(servicer, server):
+ rpc_method_handlers = {
+ 'SayHello': grpc.unary_unary_rpc_method_handler(
+ servicer.SayHello,
+ request_deserializer=helloworld__pb2.HelloRequest.FromString,
+ response_serializer=helloworld__pb2.HelloReply.SerializeToString,
+ ),
+ }
+ generic_handler = grpc.method_handlers_generic_handler(
+ 'helloworld.Greeter', rpc_method_handlers)
+ server.add_generic_rpc_handlers((generic_handler,))
+
+
+ # This class is part of an EXPERIMENTAL API.
+class Greeter(object):
+ """The greeting service definition.
+ """
+
+ @staticmethod
+ def SayHello(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, '/helloworld.Greeter/SayHello',
+ helloworld__pb2.HelloRequest.SerializeToString,
+ helloworld__pb2.HelloReply.FromString,
+ options, channel_credentials,
+ insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
diff --git a/examples/python/helloworld/greeter_client_reflection.py b/examples/python/helloworld/greeter_client_reflection.py
new file mode 100644
index 0000000000..77e32930b7
--- /dev/null
+++ b/examples/python/helloworld/greeter_client_reflection.py
@@ -0,0 +1,46 @@
+# Copyright 2023 gRPC authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""The Python implementation of the GRPC helloworld.Greeter client with reflection."""
+
+import logging
+
+from google.protobuf.descriptor_pool import DescriptorPool
+import grpc
+from grpc_reflection.v1alpha.proto_reflection_descriptor_database import \
+ ProtoReflectionDescriptorDatabase
+
+
+def run():
+ print("Will try to greet world ...")
+ with grpc.insecure_channel('localhost:50051') as channel:
+ reflection_db = ProtoReflectionDescriptorDatabase(channel)
+ services = reflection_db.get_services()
+ print(f"found services: {services}")
+
+ desc_pool = DescriptorPool(reflection_db)
+ service_desc = desc_pool.FindServiceByName("helloworld.Greeter")
+ print(f"found Greeter service with name: {service_desc.full_name}")
+ for methods in service_desc.methods:
+ print(f"found method name: {methods.full_name}")
+ input_type = methods.input_type
+ print(f"input type for this method: {input_type.full_name}")
+
+ request_desc = desc_pool.FindMessageTypeByName(
+ "helloworld.HelloRequest")
+ print(f"found request name: {request_desc.full_name}")
+
+
+if __name__ == '__main__':
+ logging.basicConfig()
+ run()
diff --git a/examples/python/keep_alive/greeter_client.py b/examples/python/keep_alive/greeter_client.py
new file mode 100644
index 0000000000..c5d03cb0d7
--- /dev/null
+++ b/examples/python/keep_alive/greeter_client.py
@@ -0,0 +1,67 @@
+# Copyright 2023 gRPC authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""gRPC Python helloworld.Greeter client with keepAlive channel options."""
+
+import logging
+from time import sleep
+
+import grpc
+import helloworld_pb2
+import helloworld_pb2_grpc
+
+
+def unary_call(stub: helloworld_pb2_grpc.GreeterStub, request_id: int,
+ message: str):
+ print("call:", request_id)
+ try:
+ response = stub.SayHello(helloworld_pb2.HelloRequest(name=message))
+ print(f"Greeter client received: {response.message}")
+ except grpc.RpcError as rpc_error:
+ print('Call failed with code: ', rpc_error.code())
+
+
+def run():
+ """
+ grpc.keepalive_time_ms: The period (in milliseconds) after which a keepalive ping is
+ sent on the transport.
+ grpc.keepalive_timeout_ms: The amount of time (in milliseconds) the sender of the keepalive
+ ping waits for an acknowledgement. If it does not receive an acknowledgment within this
+ time, it will close the connection.
+ grpc.keepalive_permit_without_calls: If set to 1 (0 : false; 1 : true), allows keepalive
+ pings to be sent even if there are no calls in flight.
+ grpc.http2.max_pings_without_data: How many pings can the client send before needing to
+ send a data/header frame.
+ For more details, check: https://github.com/grpc/grpc/blob/master/doc/keepalive.md
+ """
+ channel_options = [('grpc.keepalive_time_ms', 8000),
+ ('grpc.keepalive_timeout_ms', 5000),
+ ('grpc.http2.max_pings_without_data', 5),
+ ('grpc.keepalive_permit_without_calls', 1)]
+
+ with grpc.insecure_channel(target='localhost:50051',
+ options=channel_options) as channel:
+ stub = helloworld_pb2_grpc.GreeterStub(channel)
+ # Should succeed
+ unary_call(stub, 1, 'you')
+
+ # Run 30s, run this with GRPC_VERBOSITY=DEBUG GRPC_TRACE=http_keepalive to observe logs.
+ # Client will be closed after receveing GOAWAY from server.
+ for i in range(30):
+ print(f"{i} seconds paased.")
+ sleep(1)
+
+
+if __name__ == '__main__':
+ logging.basicConfig()
+ run()
diff --git a/examples/python/keep_alive/greeter_server.py b/examples/python/keep_alive/greeter_server.py
new file mode 100644
index 0000000000..db01ab3f5e
--- /dev/null
+++ b/examples/python/keep_alive/greeter_server.py
@@ -0,0 +1,74 @@
+# Copyright 2023 gRPC authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""The Python implementation of the GRPC helloworld.Greeter server with keepAlive options."""
+
+from concurrent import futures
+import logging
+from time import sleep
+
+import grpc
+import helloworld_pb2
+import helloworld_pb2_grpc
+
+
+class Greeter(helloworld_pb2_grpc.GreeterServicer):
+
+ def SayHello(self, request, context):
+ message = request.name
+ if message.startswith("[delay]"):
+ sleep(5)
+ return helloworld_pb2.HelloReply(message=message)
+
+
+def serve():
+ """
+ grpc.keepalive_time_ms: The period (in milliseconds) after which a keepalive ping is
+ sent on the transport.
+ grpc.keepalive_timeout_ms: The amount of time (in milliseconds) the sender of the keepalive
+ ping waits for an acknowledgement. If it does not receive an acknowledgment within
+ this time, it will close the connection.
+ grpc.http2.min_ping_interval_without_data_ms: Minimum allowed time (in milliseconds)
+ between a server receiving successive ping frames without sending any data/header frame.
+ grpc.max_connection_idle_ms: Maximum time (in milliseconds) that a channel may have no
+ outstanding rpcs, after which the server will close the connection.
+ grpc.max_connection_age_ms: Maximum time (in milliseconds) that a channel may exist.
+ grpc.max_connection_age_grace_ms: Grace period (in milliseconds) after the channel
+ reaches its max age.
+ grpc.http2.max_pings_without_data: How many pings can the client send before needing to
+ send a data/header frame.
+ grpc.keepalive_permit_without_calls: If set to 1 (0 : false; 1 : true), allows keepalive
+ pings to be sent even if there are no calls in flight.
+ For more details, check: https://github.com/grpc/grpc/blob/master/doc/keepalive.md
+ """
+ server_options = [('grpc.keepalive_time_ms', 20000),
+ ('grpc.keepalive_timeout_ms', 10000),
+ ('grpc.http2.min_ping_interval_without_data_ms', 5000),
+ ('grpc.max_connection_idle_ms', 10000),
+ ('grpc.max_connection_age_ms', 30000),
+ ('grpc.max_connection_age_grace_ms', 5000),
+ ('grpc.http2.max_pings_without_data', 5),
+ ('grpc.keepalive_permit_without_calls', 1)]
+ port = '50051'
+ server = grpc.server(thread_pool=futures.ThreadPoolExecutor(max_workers=10),
+ options=server_options)
+ helloworld_pb2_grpc.add_GreeterServicer_to_server(Greeter(), server)
+ server.add_insecure_port('[::]:' + port)
+ server.start()
+ print("Server started, listening on " + port)
+ server.wait_for_termination()
+
+
+if __name__ == '__main__':
+ logging.basicConfig()
+ serve()
diff --git a/examples/python/keep_alive/helloworld_pb2.py b/examples/python/keep_alive/helloworld_pb2.py
new file mode 100644
index 0000000000..f5b4f2d27d
--- /dev/null
+++ b/examples/python/keep_alive/helloworld_pb2.py
@@ -0,0 +1,30 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# source: helloworld.proto
+"""Generated protocol buffer code."""
+from google.protobuf.internal import builder as _builder
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import symbol_database as _symbol_database
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x10helloworld.proto\x12\nhelloworld\"\x1c\n\x0cHelloRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\"\x1d\n\nHelloReply\x12\x0f\n\x07message\x18\x01 \x01(\t2I\n\x07Greeter\x12>\n\x08SayHello\x12\x18.helloworld.HelloRequest\x1a\x16.helloworld.HelloReply\"\x00\x42\x36\n\x1bio.grpc.examples.helloworldB\x0fHelloWorldProtoP\x01\xa2\x02\x03HLWb\x06proto3')
+
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals())
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'helloworld_pb2', globals())
+if _descriptor._USE_C_DESCRIPTORS == False:
+
+ DESCRIPTOR._options = None
+ DESCRIPTOR._serialized_options = b'\n\033io.grpc.examples.helloworldB\017HelloWorldProtoP\001\242\002\003HLW'
+ _HELLOREQUEST._serialized_start=32
+ _HELLOREQUEST._serialized_end=60
+ _HELLOREPLY._serialized_start=62
+ _HELLOREPLY._serialized_end=91
+ _GREETER._serialized_start=93
+ _GREETER._serialized_end=166
+# @@protoc_insertion_point(module_scope)
diff --git a/examples/python/keep_alive/helloworld_pb2.pyi b/examples/python/keep_alive/helloworld_pb2.pyi
new file mode 100644
index 0000000000..8c4b5b2280
--- /dev/null
+++ b/examples/python/keep_alive/helloworld_pb2.pyi
@@ -0,0 +1,17 @@
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import message as _message
+from typing import ClassVar as _ClassVar, Optional as _Optional
+
+DESCRIPTOR: _descriptor.FileDescriptor
+
+class HelloReply(_message.Message):
+ __slots__ = ["message"]
+ MESSAGE_FIELD_NUMBER: _ClassVar[int]
+ message: str
+ def __init__(self, message: _Optional[str] = ...) -> None: ...
+
+class HelloRequest(_message.Message):
+ __slots__ = ["name"]
+ NAME_FIELD_NUMBER: _ClassVar[int]
+ name: str
+ def __init__(self, name: _Optional[str] = ...) -> None: ...
diff --git a/examples/python/keep_alive/helloworld_pb2_grpc.py b/examples/python/keep_alive/helloworld_pb2_grpc.py
new file mode 100644
index 0000000000..47c186976e
--- /dev/null
+++ b/examples/python/keep_alive/helloworld_pb2_grpc.py
@@ -0,0 +1,70 @@
+# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT!
+"""Client and server classes corresponding to protobuf-defined services."""
+import grpc
+
+import helloworld_pb2 as helloworld__pb2
+
+
+class GreeterStub(object):
+ """The greeting service definition.
+ """
+
+ def __init__(self, channel):
+ """Constructor.
+
+ Args:
+ channel: A grpc.Channel.
+ """
+ self.SayHello = channel.unary_unary(
+ '/helloworld.Greeter/SayHello',
+ request_serializer=helloworld__pb2.HelloRequest.SerializeToString,
+ response_deserializer=helloworld__pb2.HelloReply.FromString,
+ )
+
+
+class GreeterServicer(object):
+ """The greeting service definition.
+ """
+
+ def SayHello(self, request, context):
+ """Sends a greeting
+ """
+ context.set_code(grpc.StatusCode.UNIMPLEMENTED)
+ context.set_details('Method not implemented!')
+ raise NotImplementedError('Method not implemented!')
+
+
+def add_GreeterServicer_to_server(servicer, server):
+ rpc_method_handlers = {
+ 'SayHello': grpc.unary_unary_rpc_method_handler(
+ servicer.SayHello,
+ request_deserializer=helloworld__pb2.HelloRequest.FromString,
+ response_serializer=helloworld__pb2.HelloReply.SerializeToString,
+ ),
+ }
+ generic_handler = grpc.method_handlers_generic_handler(
+ 'helloworld.Greeter', rpc_method_handlers)
+ server.add_generic_rpc_handlers((generic_handler,))
+
+
+ # This class is part of an EXPERIMENTAL API.
+class Greeter(object):
+ """The greeting service definition.
+ """
+
+ @staticmethod
+ def SayHello(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, '/helloworld.Greeter/SayHello',
+ helloworld__pb2.HelloRequest.SerializeToString,
+ helloworld__pb2.HelloReply.FromString,
+ options, channel_credentials,
+ insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
diff --git a/examples/python/timeout/greeter_client.py b/examples/python/timeout/greeter_client.py
new file mode 100644
index 0000000000..d1487994ac
--- /dev/null
+++ b/examples/python/timeout/greeter_client.py
@@ -0,0 +1,45 @@
+# Copyright 2023 gRPC authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""gRPC Python helloworld.Greeter client with call timeout parameters."""
+
+import logging
+
+import grpc
+import helloworld_pb2
+import helloworld_pb2_grpc
+
+
+def unary_call(stub: helloworld_pb2_grpc.GreeterStub, request_id: int,
+ message: str):
+ print("call:", request_id)
+ try:
+ response = stub.SayHello(helloworld_pb2.HelloRequest(name=message),
+ timeout=3)
+ print(f"Greeter client received: {response.message}")
+ except grpc.RpcError as rpc_error:
+ print(f"Call failed with code: {rpc_error.code()}")
+
+
+def run():
+ with grpc.insecure_channel('localhost:50051') as channel:
+ stub = helloworld_pb2_grpc.GreeterStub(channel)
+ # Should success
+ unary_call(stub, 1, 'you')
+ # Should fail with DEADLINE_EXCEEDED
+ unary_call(stub, 2, '[delay] you')
+
+
+if __name__ == '__main__':
+ logging.basicConfig()
+ run()
diff --git a/examples/python/timeout/greeter_server.py b/examples/python/timeout/greeter_server.py
new file mode 100644
index 0000000000..14b050b926
--- /dev/null
+++ b/examples/python/timeout/greeter_server.py
@@ -0,0 +1,46 @@
+# Copyright 2023 gRPC authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""The Python implementation of the GRPC helloworld.Greeter server."""
+
+from concurrent import futures
+import logging
+from time import sleep
+
+import grpc
+import helloworld_pb2
+import helloworld_pb2_grpc
+
+
+class Greeter(helloworld_pb2_grpc.GreeterServicer):
+
+ def SayHello(self, request, context):
+ message = request.name
+ if message.startswith("[delay]"):
+ sleep(5)
+ return helloworld_pb2.HelloReply(message=message)
+
+
+def serve():
+ port = '50051'
+ server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
+ helloworld_pb2_grpc.add_GreeterServicer_to_server(Greeter(), server)
+ server.add_insecure_port('[::]:' + port)
+ server.start()
+ print("Server started, listening on " + port)
+ server.wait_for_termination()
+
+
+if __name__ == '__main__':
+ logging.basicConfig()
+ serve()
diff --git a/examples/python/timeout/helloworld_pb2.py b/examples/python/timeout/helloworld_pb2.py
new file mode 100644
index 0000000000..f5b4f2d27d
--- /dev/null
+++ b/examples/python/timeout/helloworld_pb2.py
@@ -0,0 +1,30 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# source: helloworld.proto
+"""Generated protocol buffer code."""
+from google.protobuf.internal import builder as _builder
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import symbol_database as _symbol_database
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x10helloworld.proto\x12\nhelloworld\"\x1c\n\x0cHelloRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\"\x1d\n\nHelloReply\x12\x0f\n\x07message\x18\x01 \x01(\t2I\n\x07Greeter\x12>\n\x08SayHello\x12\x18.helloworld.HelloRequest\x1a\x16.helloworld.HelloReply\"\x00\x42\x36\n\x1bio.grpc.examples.helloworldB\x0fHelloWorldProtoP\x01\xa2\x02\x03HLWb\x06proto3')
+
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals())
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'helloworld_pb2', globals())
+if _descriptor._USE_C_DESCRIPTORS == False:
+
+ DESCRIPTOR._options = None
+ DESCRIPTOR._serialized_options = b'\n\033io.grpc.examples.helloworldB\017HelloWorldProtoP\001\242\002\003HLW'
+ _HELLOREQUEST._serialized_start=32
+ _HELLOREQUEST._serialized_end=60
+ _HELLOREPLY._serialized_start=62
+ _HELLOREPLY._serialized_end=91
+ _GREETER._serialized_start=93
+ _GREETER._serialized_end=166
+# @@protoc_insertion_point(module_scope)
diff --git a/examples/python/timeout/helloworld_pb2.pyi b/examples/python/timeout/helloworld_pb2.pyi
new file mode 100644
index 0000000000..8c4b5b2280
--- /dev/null
+++ b/examples/python/timeout/helloworld_pb2.pyi
@@ -0,0 +1,17 @@
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import message as _message
+from typing import ClassVar as _ClassVar, Optional as _Optional
+
+DESCRIPTOR: _descriptor.FileDescriptor
+
+class HelloReply(_message.Message):
+ __slots__ = ["message"]
+ MESSAGE_FIELD_NUMBER: _ClassVar[int]
+ message: str
+ def __init__(self, message: _Optional[str] = ...) -> None: ...
+
+class HelloRequest(_message.Message):
+ __slots__ = ["name"]
+ NAME_FIELD_NUMBER: _ClassVar[int]
+ name: str
+ def __init__(self, name: _Optional[str] = ...) -> None: ...
diff --git a/examples/python/timeout/helloworld_pb2_grpc.py b/examples/python/timeout/helloworld_pb2_grpc.py
new file mode 100644
index 0000000000..47c186976e
--- /dev/null
+++ b/examples/python/timeout/helloworld_pb2_grpc.py
@@ -0,0 +1,70 @@
+# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT!
+"""Client and server classes corresponding to protobuf-defined services."""
+import grpc
+
+import helloworld_pb2 as helloworld__pb2
+
+
+class GreeterStub(object):
+ """The greeting service definition.
+ """
+
+ def __init__(self, channel):
+ """Constructor.
+
+ Args:
+ channel: A grpc.Channel.
+ """
+ self.SayHello = channel.unary_unary(
+ '/helloworld.Greeter/SayHello',
+ request_serializer=helloworld__pb2.HelloRequest.SerializeToString,
+ response_deserializer=helloworld__pb2.HelloReply.FromString,
+ )
+
+
+class GreeterServicer(object):
+ """The greeting service definition.
+ """
+
+ def SayHello(self, request, context):
+ """Sends a greeting
+ """
+ context.set_code(grpc.StatusCode.UNIMPLEMENTED)
+ context.set_details('Method not implemented!')
+ raise NotImplementedError('Method not implemented!')
+
+
+def add_GreeterServicer_to_server(servicer, server):
+ rpc_method_handlers = {
+ 'SayHello': grpc.unary_unary_rpc_method_handler(
+ servicer.SayHello,
+ request_deserializer=helloworld__pb2.HelloRequest.FromString,
+ response_serializer=helloworld__pb2.HelloReply.SerializeToString,
+ ),
+ }
+ generic_handler = grpc.method_handlers_generic_handler(
+ 'helloworld.Greeter', rpc_method_handlers)
+ server.add_generic_rpc_handlers((generic_handler,))
+
+
+ # This class is part of an EXPERIMENTAL API.
+class Greeter(object):
+ """The greeting service definition.
+ """
+
+ @staticmethod
+ def SayHello(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, '/helloworld.Greeter/SayHello',
+ helloworld__pb2.HelloRequest.SerializeToString,
+ helloworld__pb2.HelloReply.FromString,
+ options, channel_credentials,
+ insecure, call_credentials, compression, wait_for_ready, timeout, metadata)