aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/python/grpcio
diff options
context:
space:
mode:
Diffstat (limited to 'src/python/grpcio')
-rw-r--r--src/python/grpcio/grpc/_adapter/_c/types.h2
-rw-r--r--src/python/grpcio/grpc/_adapter/_c/types/server.c16
-rw-r--r--src/python/grpcio/grpc/_adapter/_low.py3
-rw-r--r--src/python/grpcio/grpc/_links/invocation.py8
-rw-r--r--src/python/grpcio/grpc/_links/service.py14
-rw-r--r--src/python/grpcio/grpc/framework/core/_transmission.py14
-rw-r--r--src/python/grpcio/grpc/framework/interfaces/face/__init__.py30
-rw-r--r--src/python/grpcio/grpc/framework/interfaces/face/face.py933
-rw-r--r--src/python/grpcio/grpc/framework/interfaces/face/utilities.py178
-rw-r--r--src/python/grpcio/grpc/framework/interfaces/links/links.py24
10 files changed, 1202 insertions, 20 deletions
diff --git a/src/python/grpcio/grpc/_adapter/_c/types.h b/src/python/grpcio/grpc/_adapter/_c/types.h
index f646465c63..f6ff957baa 100644
--- a/src/python/grpcio/grpc/_adapter/_c/types.h
+++ b/src/python/grpcio/grpc/_adapter/_c/types.h
@@ -146,6 +146,7 @@ typedef struct Server {
PyObject_HEAD
grpc_server *c_serv;
CompletionQueue *cq;
+ int shutdown_called;
} Server;
Server *pygrpc_Server_new(PyTypeObject *type, PyObject *args, PyObject *kwargs);
void pygrpc_Server_dealloc(Server *self);
@@ -156,6 +157,7 @@ PyObject *pygrpc_Server_add_http2_port(
PyObject *pygrpc_Server_start(Server *self, PyObject *ignored);
PyObject *pygrpc_Server_shutdown(
Server *self, PyObject *args, PyObject *kwargs);
+PyObject *pygrpc_Server_cancel_all_calls(Server *self, PyObject *unused);
extern PyTypeObject pygrpc_Server_type;
/*=========*/
diff --git a/src/python/grpcio/grpc/_adapter/_c/types/server.c b/src/python/grpcio/grpc/_adapter/_c/types/server.c
index 15c98f28eb..8feab8aab1 100644
--- a/src/python/grpcio/grpc/_adapter/_c/types/server.c
+++ b/src/python/grpcio/grpc/_adapter/_c/types/server.c
@@ -45,6 +45,8 @@ PyMethodDef pygrpc_Server_methods[] = {
METH_KEYWORDS, ""},
{"start", (PyCFunction)pygrpc_Server_start, METH_NOARGS, ""},
{"shutdown", (PyCFunction)pygrpc_Server_shutdown, METH_KEYWORDS, ""},
+ {"cancel_all_calls", (PyCFunction)pygrpc_Server_cancel_all_calls,
+ METH_NOARGS, ""},
{NULL}
};
const char pygrpc_Server_doc[] = "See grpc._adapter._types.Server.";
@@ -109,6 +111,7 @@ Server *pygrpc_Server_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
pygrpc_discard_channel_args(c_args);
self->cq = cq;
Py_INCREF(self->cq);
+ self->shutdown_called = 0;
return self;
}
@@ -163,6 +166,7 @@ PyObject *pygrpc_Server_add_http2_port(
PyObject *pygrpc_Server_start(Server *self, PyObject *ignored) {
grpc_server_start(self->c_serv);
+ self->shutdown_called = 0;
Py_RETURN_NONE;
}
@@ -176,5 +180,17 @@ PyObject *pygrpc_Server_shutdown(
}
tag = pygrpc_produce_server_shutdown_tag(user_tag);
grpc_server_shutdown_and_notify(self->c_serv, self->cq->c_cq, tag);
+ self->shutdown_called = 1;
+ Py_RETURN_NONE;
+}
+
+PyObject *pygrpc_Server_cancel_all_calls(Server *self, PyObject *unused) {
+ if (!self->shutdown_called) {
+ PyErr_SetString(
+ PyExc_RuntimeError,
+ "shutdown must have been called prior to calling cancel_all_calls!");
+ return NULL;
+ }
+ grpc_server_cancel_all_calls(self->c_serv);
Py_RETURN_NONE;
}
diff --git a/src/python/grpcio/grpc/_adapter/_low.py b/src/python/grpcio/grpc/_adapter/_low.py
index 147086e725..3859ebb0e2 100644
--- a/src/python/grpcio/grpc/_adapter/_low.py
+++ b/src/python/grpcio/grpc/_adapter/_low.py
@@ -124,3 +124,6 @@ class Server(_types.Server):
def request_call(self, completion_queue, tag):
return self.server.request_call(completion_queue.completion_queue, tag)
+
+ def cancel_all_calls(self):
+ return self.server.cancel_all_calls()
diff --git a/src/python/grpcio/grpc/_links/invocation.py b/src/python/grpcio/grpc/_links/invocation.py
index 0058ae91f8..a74c77ebcc 100644
--- a/src/python/grpcio/grpc/_links/invocation.py
+++ b/src/python/grpcio/grpc/_links/invocation.py
@@ -101,7 +101,7 @@ class _Kernel(object):
else:
ticket = links.Ticket(
operation_id, rpc_state.sequence_number, None, None, None, None, 1,
- None, None, None, None, None, None)
+ None, None, None, None, None, None, None)
rpc_state.sequence_number += 1
self._relay.add_value(ticket)
rpc_state.low_write = _LowWrite.OPEN
@@ -118,7 +118,7 @@ class _Kernel(object):
ticket = links.Ticket(
operation_id, rpc_state.sequence_number, None, None, None, None, None,
None, rpc_state.response_deserializer(event.bytes), None, None, None,
- None)
+ None, None)
rpc_state.sequence_number += 1
self._relay.add_value(ticket)
@@ -129,7 +129,7 @@ class _Kernel(object):
ticket = links.Ticket(
operation_id, rpc_state.sequence_number, None, None,
links.Ticket.Subscription.FULL, None, None, event.metadata, None, None,
- None, None, None)
+ None, None, None, None)
rpc_state.sequence_number += 1
self._relay.add_value(ticket)
@@ -146,7 +146,7 @@ class _Kernel(object):
ticket = links.Ticket(
operation_id, rpc_state.sequence_number, None, None, None, None, None,
None, None, event.metadata, event.status.code, event.status.details,
- termination)
+ termination, None)
rpc_state.sequence_number += 1
self._relay.add_value(ticket)
diff --git a/src/python/grpcio/grpc/_links/service.py b/src/python/grpcio/grpc/_links/service.py
index 03be5af404..1436176246 100644
--- a/src/python/grpcio/grpc/_links/service.py
+++ b/src/python/grpcio/grpc/_links/service.py
@@ -131,7 +131,7 @@ class _Kernel(object):
ticket = links.Ticket(
call, 0, group, method, links.Ticket.Subscription.FULL,
service_acceptance.deadline - time.time(), None, event.metadata, None,
- None, None, None, None)
+ None, None, None, None, 'TODO: Service Context Object!')
self._relay.add_value(ticket)
def _on_read_event(self, event):
@@ -157,7 +157,7 @@ class _Kernel(object):
# rpc_state.read = _Read.AWAITING_ALLOWANCE
ticket = links.Ticket(
call, rpc_state.sequence_number, None, None, None, None, None, None,
- payload, None, None, None, termination)
+ payload, None, None, None, termination, None)
rpc_state.sequence_number += 1
self._relay.add_value(ticket)
@@ -176,7 +176,7 @@ class _Kernel(object):
else:
ticket = links.Ticket(
call, rpc_state.sequence_number, None, None, None, None, 1, None,
- None, None, None, None, None)
+ None, None, None, None, None, None)
rpc_state.sequence_number += 1
self._relay.add_value(ticket)
rpc_state.low_write = _LowWrite.OPEN
@@ -198,7 +198,7 @@ class _Kernel(object):
termination = links.Ticket.Termination.TRANSMISSION_FAILURE
ticket = links.Ticket(
call, rpc_state.sequence_number, None, None, None, None, None, None,
- None, None, None, None, termination)
+ None, None, None, None, termination, None)
rpc_state.sequence_number += 1
self._relay.add_value(ticket)
@@ -257,11 +257,11 @@ class _Kernel(object):
termination = None
else:
termination = links.Ticket.Termination.COMPLETION
- ticket = links.Ticket(
+ early_read_ticket = links.Ticket(
call, rpc_state.sequence_number, None, None, None, None, None,
- None, payload, None, None, None, termination)
+ None, payload, None, None, None, termination, None)
rpc_state.sequence_number += 1
- self._relay.add_value(ticket)
+ self._relay.add_value(early_read_ticket)
if ticket.payload is not None:
call.write(rpc_state.response_serializer(ticket.payload), call)
diff --git a/src/python/grpcio/grpc/framework/core/_transmission.py b/src/python/grpcio/grpc/framework/core/_transmission.py
index 01894d398d..03644f4d49 100644
--- a/src/python/grpcio/grpc/framework/core/_transmission.py
+++ b/src/python/grpcio/grpc/framework/core/_transmission.py
@@ -107,7 +107,7 @@ class TransmissionManager(_interfaces.TransmissionManager):
return links.Ticket(
self._operation_id, self._lowest_unused_sequence_number, None,
None, None, None, None, None, None, None, None, None,
- termination)
+ termination, None)
action = False
# TODO(nathaniel): Support other subscriptions.
@@ -144,7 +144,7 @@ class TransmissionManager(_interfaces.TransmissionManager):
ticket = links.Ticket(
self._operation_id, self._lowest_unused_sequence_number, None, None,
local_subscription, timeout, allowance, initial_metadata, payload,
- terminal_metadata, code, message, termination)
+ terminal_metadata, code, message, termination, None)
self._lowest_unused_sequence_number += 1
return ticket
else:
@@ -191,7 +191,7 @@ class TransmissionManager(_interfaces.TransmissionManager):
ticket = links.Ticket(
self._operation_id, 0, group, method, subscription, timeout, allowance,
initial_metadata, payload, terminal_metadata, code, message,
- termination)
+ termination, None)
self._lowest_unused_sequence_number = 1
self._transmit(ticket)
@@ -236,7 +236,7 @@ class TransmissionManager(_interfaces.TransmissionManager):
ticket = links.Ticket(
self._operation_id, self._lowest_unused_sequence_number, None, None,
None, None, allowance, effective_initial_metadata, ticket_payload,
- terminal_metadata, code, message, termination)
+ terminal_metadata, code, message, termination, None)
self._lowest_unused_sequence_number += 1
self._transmit(ticket)
@@ -247,7 +247,7 @@ class TransmissionManager(_interfaces.TransmissionManager):
else:
ticket = links.Ticket(
self._operation_id, self._lowest_unused_sequence_number, None, None,
- None, timeout, None, None, None, None, None, None, None)
+ None, timeout, None, None, None, None, None, None, None, None)
self._lowest_unused_sequence_number += 1
self._transmit(ticket)
@@ -268,7 +268,7 @@ class TransmissionManager(_interfaces.TransmissionManager):
ticket = links.Ticket(
self._operation_id, self._lowest_unused_sequence_number, None, None,
None, None, None, None, payload, terminal_metadata, code, message,
- termination)
+ termination, None)
self._lowest_unused_sequence_number += 1
self._transmit(ticket)
@@ -290,5 +290,5 @@ class TransmissionManager(_interfaces.TransmissionManager):
ticket = links.Ticket(
self._operation_id, self._lowest_unused_sequence_number, None,
None, None, None, None, None, None, None, None, None,
- termination)
+ termination, None)
self._transmit(ticket)
diff --git a/src/python/grpcio/grpc/framework/interfaces/face/__init__.py b/src/python/grpcio/grpc/framework/interfaces/face/__init__.py
new file mode 100644
index 0000000000..7086519106
--- /dev/null
+++ b/src/python/grpcio/grpc/framework/interfaces/face/__init__.py
@@ -0,0 +1,30 @@
+# Copyright 2015, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
diff --git a/src/python/grpcio/grpc/framework/interfaces/face/face.py b/src/python/grpcio/grpc/framework/interfaces/face/face.py
new file mode 100644
index 0000000000..948e7505b6
--- /dev/null
+++ b/src/python/grpcio/grpc/framework/interfaces/face/face.py
@@ -0,0 +1,933 @@
+# Copyright 2015, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""Interfaces defining the Face layer of RPC Framework."""
+
+import abc
+import collections
+import enum
+
+# cardinality, style, abandonment, future, and stream are
+# referenced from specification in this module.
+from grpc.framework.common import cardinality # pylint: disable=unused-import
+from grpc.framework.common import style # pylint: disable=unused-import
+from grpc.framework.foundation import abandonment # pylint: disable=unused-import
+from grpc.framework.foundation import future # pylint: disable=unused-import
+from grpc.framework.foundation import stream # pylint: disable=unused-import
+
+
+class NoSuchMethodError(Exception):
+ """Raised by customer code to indicate an unrecognized method.
+
+ Attributes:
+ group: The group of the unrecognized method.
+ name: The name of the unrecognized method.
+ """
+
+ def __init__(self, group, method):
+ """Constructor.
+
+ Args:
+ group: The group identifier of the unrecognized RPC name.
+ method: The method identifier of the unrecognized RPC name.
+ """
+ super(NoSuchMethodError, self).__init__()
+ self.group = group
+ self.method = method
+
+ def __repr__(self):
+ return 'face.NoSuchMethodError(%s, %s)' % (self.group, self.method,)
+
+
+class Abortion(
+ collections.namedtuple(
+ 'Abortion',
+ ('kind', 'initial_metadata', 'terminal_metadata', 'code', 'details',))):
+ """A value describing RPC abortion.
+
+ Attributes:
+ kind: A Kind value identifying how the RPC failed.
+ initial_metadata: The initial metadata from the other side of the RPC or
+ None if no initial metadata value was received.
+ terminal_metadata: The terminal metadata from the other side of the RPC or
+ None if no terminal metadata value was received.
+ code: The code value from the other side of the RPC or None if no code value
+ was received.
+ details: The details value from the other side of the RPC or None if no
+ details value was received.
+ """
+
+ @enum.unique
+ class Kind(enum.Enum):
+ """Types of RPC abortion."""
+
+ CANCELLED = 'cancelled'
+ EXPIRED = 'expired'
+ LOCAL_SHUTDOWN = 'local shutdown'
+ REMOTE_SHUTDOWN = 'remote shutdown'
+ NETWORK_FAILURE = 'network failure'
+ LOCAL_FAILURE = 'local failure'
+ REMOTE_FAILURE = 'remote failure'
+
+
+class AbortionError(Exception):
+ """Common super type for exceptions indicating RPC abortion.
+
+ initial_metadata: The initial metadata from the other side of the RPC or
+ None if no initial metadata value was received.
+ terminal_metadata: The terminal metadata from the other side of the RPC or
+ None if no terminal metadata value was received.
+ code: The code value from the other side of the RPC or None if no code value
+ was received.
+ details: The details value from the other side of the RPC or None if no
+ details value was received.
+ """
+ __metaclass__ = abc.ABCMeta
+
+ def __init__(self, initial_metadata, terminal_metadata, code, details):
+ super(AbortionError, self).__init__()
+ self.initial_metadata = initial_metadata
+ self.terminal_metadata = terminal_metadata
+ self.code = code
+ self.details = details
+
+
+class CancellationError(AbortionError):
+ """Indicates that an RPC has been cancelled."""
+
+
+class ExpirationError(AbortionError):
+ """Indicates that an RPC has expired ("timed out")."""
+
+
+class LocalShutdownError(AbortionError):
+ """Indicates that an RPC has terminated due to local shutdown of RPCs."""
+
+
+class RemoteShutdownError(AbortionError):
+ """Indicates that an RPC has terminated due to remote shutdown of RPCs."""
+
+
+class NetworkError(AbortionError):
+ """Indicates that some error occurred on the network."""
+
+
+class LocalError(AbortionError):
+ """Indicates that an RPC has terminated due to a local defect."""
+
+
+class RemoteError(AbortionError):
+ """Indicates that an RPC has terminated due to a remote defect."""
+
+
+class RpcContext(object):
+ """Provides RPC-related information and action."""
+ __metaclass__ = abc.ABCMeta
+
+ @abc.abstractmethod
+ def is_active(self):
+ """Describes whether the RPC is active or has terminated."""
+ raise NotImplementedError()
+
+ @abc.abstractmethod
+ def time_remaining(self):
+ """Describes the length of allowed time remaining for the RPC.
+
+ Returns:
+ A nonnegative float indicating the length of allowed time in seconds
+ remaining for the RPC to complete before it is considered to have timed
+ out.
+ """
+ raise NotImplementedError()
+
+ @abc.abstractmethod
+ def add_abortion_callback(self, abortion_callback):
+ """Registers a callback to be called if the RPC is aborted.
+
+ Args:
+ abortion_callback: A callable to be called and passed an Abortion value
+ in the event of RPC abortion.
+ """
+ raise NotImplementedError()
+
+ @abc.abstractmethod
+ def cancel(self):
+ """Cancels the RPC.
+
+ Idempotent and has no effect if the RPC has already terminated.
+ """
+ raise NotImplementedError()
+
+
+class Call(RpcContext):
+ """Invocation-side utility object for an RPC."""
+ __metaclass__ = abc.ABCMeta
+
+ @abc.abstractmethod
+ def initial_metadata(self):
+ """Accesses the initial metadata from the service-side of the RPC.
+
+ This method blocks until the value is available or is known not to have been
+ emitted from the service-side of the RPC.
+
+ Returns:
+ The initial metadata object emitted by the service-side of the RPC, or
+ None if there was no such value.
+ """
+ raise NotImplementedError()
+
+ @abc.abstractmethod
+ def terminal_metadata(self):
+ """Accesses the terminal metadata from the service-side of the RPC.
+
+ This method blocks until the value is available or is known not to have been
+ emitted from the service-side of the RPC.
+
+ Returns:
+ The terminal metadata object emitted by the service-side of the RPC, or
+ None if there was no such value.
+ """
+ raise NotImplementedError()
+
+ @abc.abstractmethod
+ def code(self):
+ """Accesses the code emitted by the service-side of the RPC.
+
+ This method blocks until the value is available or is known not to have been
+ emitted from the service-side of the RPC.
+
+ Returns:
+ The code object emitted by the service-side of the RPC, or None if there
+ was no such value.
+ """
+ raise NotImplementedError()
+
+ @abc.abstractmethod
+ def details(self):
+ """Accesses the details value emitted by the service-side of the RPC.
+
+ This method blocks until the value is available or is known not to have been
+ emitted from the service-side of the RPC.
+
+ Returns:
+ The details value emitted by the service-side of the RPC, or None if there
+ was no such value.
+ """
+ raise NotImplementedError()
+
+
+class ServicerContext(RpcContext):
+ """A context object passed to method implementations."""
+ __metaclass__ = abc.ABCMeta
+
+ @abc.abstractmethod
+ def invocation_metadata(self):
+ """Accesses the metadata from the invocation-side of the RPC.
+
+ This method blocks until the value is available or is known not to have been
+ emitted from the invocation-side of the RPC.
+
+ Returns:
+ The metadata object emitted by the invocation-side of the RPC, or None if
+ there was no such value.
+ """
+ raise NotImplementedError()
+
+ @abc.abstractmethod
+ def initial_metadata(self, initial_metadata):
+ """Accepts the service-side initial metadata value of the RPC.
+
+ This method need not be called by method implementations if they have no
+ service-side initial metadata to transmit.
+
+ Args:
+ initial_metadata: The service-side initial metadata value of the RPC to
+ be transmitted to the invocation side of the RPC.
+ """
+ raise NotImplementedError()
+
+ @abc.abstractmethod
+ def terminal_metadata(self, terminal_metadata):
+ """Accepts the service-side terminal metadata value of the RPC.
+
+ This method need not be called by method implementations if they have no
+ service-side terminal metadata to transmit.
+
+ Args:
+ terminal_metadata: The service-side terminal metadata value of the RPC to
+ be transmitted to the invocation side of the RPC.
+ """
+ raise NotImplementedError()
+
+ @abc.abstractmethod
+ def code(self, code):
+ """Accepts the service-side code of the RPC.
+
+ This method need not be called by method implementations if they have no
+ code to transmit.
+
+ Args:
+ code: The code of the RPC to be transmitted to the invocation side of the
+ RPC.
+ """
+ raise NotImplementedError()
+
+ @abc.abstractmethod
+ def details(self, details):
+ """Accepts the service-side details of the RPC.
+
+ This method need not be called by method implementations if they have no
+ service-side details to transmit.
+
+ Args:
+ details: The service-side details value of the RPC to be transmitted to
+ the invocation side of the RPC.
+ """
+ raise NotImplementedError()
+
+
+class ResponseReceiver(object):
+ """Invocation-side object used to accept the output of an RPC."""
+ __metaclass__ = abc.ABCMeta
+
+ @abc.abstractmethod
+ def initial_metadata(self, initial_metadata):
+ """Receives the initial metadata from the service-side of the RPC.
+
+ Args:
+ initial_metadata: The initial metadata object emitted from the
+ service-side of the RPC.
+ """
+ raise NotImplementedError()
+
+ @abc.abstractmethod
+ def response(self, response):
+ """Receives a response from the service-side of the RPC.
+
+ Args:
+ response: A response object emitted from the service-side of the RPC.
+ """
+ raise NotImplementedError()
+
+ @abc.abstractmethod
+ def complete(self, terminal_metadata, code, details):
+ """Receives the completion values emitted from the service-side of the RPC.
+
+ Args:
+ terminal_metadata: The terminal metadata object emitted from the
+ service-side of the RPC.
+ code: The code object emitted from the service-side of the RPC.
+ details: The details object emitted from the service-side of the RPC.
+ """
+ raise NotImplementedError()
+
+
+class UnaryUnaryMultiCallable(object):
+ """Affords invoking a unary-unary RPC in any call style."""
+ __metaclass__ = abc.ABCMeta
+
+ @abc.abstractmethod
+ def __call__(
+ self, request, timeout, metadata=None, with_call=False):
+ """Synchronously invokes the underlying RPC.
+
+ Args:
+ request: The request value for the RPC.
+ timeout: A duration of time in seconds to allow for the RPC.
+ metadata: A metadata value to be passed to the service-side of
+ the RPC.
+ with_call: Whether or not to include return a Call for the RPC in addition
+ to the reponse.
+
+ Returns:
+ The response value for the RPC, and a Call for the RPC if with_call was
+ set to True at invocation.
+
+ Raises:
+ AbortionError: Indicating that the RPC was aborted.
+ """
+ raise NotImplementedError()
+
+ @abc.abstractmethod
+ def future(self, request, timeout, metadata=None):
+ """Asynchronously invokes the underlying RPC.
+
+ Args:
+ request: The request value for the RPC.
+ timeout: A duration of time in seconds to allow for the RPC.
+ metadata: A metadata value to be passed to the service-side of
+ the RPC.
+
+ Returns:
+ An object that is both a Call for the RPC and a future.Future. In the
+ event of RPC completion, the return Future's result value will be the
+ response value of the RPC. In the event of RPC abortion, the returned
+ Future's exception value will be an AbortionError.
+ """
+ raise NotImplementedError()
+
+ @abc.abstractmethod
+ def event(
+ self, request, receiver, abortion_callback, timeout,
+ metadata=None):
+ """Asynchronously invokes the underlying RPC.
+
+ Args:
+ request: The request value for the RPC.
+ receiver: A ResponseReceiver to be passed the response data of the RPC.
+ abortion_callback: A callback to be called and passed an Abortion value
+ in the event of RPC abortion.
+ timeout: A duration of time in seconds to allow for the RPC.
+ metadata: A metadata value to be passed to the service-side of
+ the RPC.
+
+ Returns:
+ A Call for the RPC.
+ """
+ raise NotImplementedError()
+
+
+class UnaryStreamMultiCallable(object):
+ """Affords invoking a unary-stream RPC in any call style."""
+ __metaclass__ = abc.ABCMeta
+
+ @abc.abstractmethod
+ def __call__(self, request, timeout, metadata=None):
+ """Invokes the underlying RPC.
+
+ Args:
+ request: The request value for the RPC.
+ timeout: A duration of time in seconds to allow for the RPC.
+ metadata: A metadata value to be passed to the service-side of
+ the RPC.
+
+ Returns:
+ An object that is both a Call for the RPC and an iterator of response
+ values. Drawing response values from the returned iterator may raise
+ AbortionError indicating abortion of the RPC.
+ """
+ raise NotImplementedError()
+
+ @abc.abstractmethod
+ def event(
+ self, request, receiver, abortion_callback, timeout,
+ metadata=None):
+ """Asynchronously invokes the underlying RPC.
+
+ Args:
+ request: The request value for the RPC.
+ receiver: A ResponseReceiver to be passed the response data of the RPC.
+ abortion_callback: A callback to be called and passed an Abortion value
+ in the event of RPC abortion.
+ timeout: A duration of time in seconds to allow for the RPC.
+ metadata: A metadata value to be passed to the service-side of
+ the RPC.
+
+ Returns:
+ A Call object for the RPC.
+ """
+ raise NotImplementedError()
+
+
+class StreamUnaryMultiCallable(object):
+ """Affords invoking a stream-unary RPC in any call style."""
+ __metaclass__ = abc.ABCMeta
+
+ @abc.abstractmethod
+ def __call__(
+ self, request_iterator, timeout, metadata=None,
+ with_call=False):
+ """Synchronously invokes the underlying RPC.
+
+ Args:
+ request_iterator: An iterator that yields request values for the RPC.
+ timeout: A duration of time in seconds to allow for the RPC.
+ metadata: A metadata value to be passed to the service-side of
+ the RPC.
+ with_call: Whether or not to include return a Call for the RPC in addition
+ to the reponse.
+
+ Returns:
+ The response value for the RPC, and a Call for the RPC if with_call was
+ set to True at invocation.
+
+ Raises:
+ AbortionError: Indicating that the RPC was aborted.
+ """
+ raise NotImplementedError()
+
+ @abc.abstractmethod
+ def future(self, request_iterator, timeout, metadata=None):
+ """Asynchronously invokes the underlying RPC.
+
+ Args:
+ request_iterator: An iterator that yields request values for the RPC.
+ timeout: A duration of time in seconds to allow for the RPC.
+ metadata: A metadata value to be passed to the service-side of
+ the RPC.
+
+ Returns:
+ An object that is both a Call for the RPC and a future.Future. In the
+ event of RPC completion, the return Future's result value will be the
+ response value of the RPC. In the event of RPC abortion, the returned
+ Future's exception value will be an AbortionError.
+ """
+ raise NotImplementedError()
+
+ @abc.abstractmethod
+ def event(
+ self, receiver, abortion_callback, timeout, metadata=None):
+ """Asynchronously invokes the underlying RPC.
+
+ Args:
+ receiver: A ResponseReceiver to be passed the response data of the RPC.
+ abortion_callback: A callback to be called and passed an Abortion value
+ in the event of RPC abortion.
+ timeout: A duration of time in seconds to allow for the RPC.
+ metadata: A metadata value to be passed to the service-side of
+ the RPC.
+
+ Returns:
+ A single object that is both a Call object for the RPC and a
+ stream.Consumer to which the request values of the RPC should be passed.
+ """
+ raise NotImplementedError()
+
+
+class StreamStreamMultiCallable(object):
+ """Affords invoking a stream-stream RPC in any call style."""
+ __metaclass__ = abc.ABCMeta
+
+ @abc.abstractmethod
+ def __call__(self, request_iterator, timeout, metadata=None):
+ """Invokes the underlying RPC.
+
+ Args:
+ request_iterator: An iterator that yields request values for the RPC.
+ timeout: A duration of time in seconds to allow for the RPC.
+ metadata: A metadata value to be passed to the service-side of
+ the RPC.
+
+ Returns:
+ An object that is both a Call for the RPC and an iterator of response
+ values. Drawing response values from the returned iterator may raise
+ AbortionError indicating abortion of the RPC.
+ """
+ raise NotImplementedError()
+
+ @abc.abstractmethod
+ def event(
+ self, receiver, abortion_callback, timeout, metadata=None):
+ """Asynchronously invokes the underlying RPC.
+
+ Args:
+ receiver: A ResponseReceiver to be passed the response data of the RPC.
+ abortion_callback: A callback to be called and passed an Abortion value
+ in the event of RPC abortion.
+ timeout: A duration of time in seconds to allow for the RPC.
+ metadata: A metadata value to be passed to the service-side of
+ the RPC.
+
+ Returns:
+ A single object that is both a Call object for the RPC and a
+ stream.Consumer to which the request values of the RPC should be passed.
+ """
+ raise NotImplementedError()
+
+
+class MethodImplementation(object):
+ """A sum type that describes a method implementation.
+
+ Attributes:
+ cardinality: A cardinality.Cardinality value.
+ style: A style.Service value.
+ unary_unary_inline: The implementation of the method as a callable value
+ that takes a request value and a ServicerContext object and returns a
+ response value. Only non-None if cardinality is
+ cardinality.Cardinality.UNARY_UNARY and style is style.Service.INLINE.
+ unary_stream_inline: The implementation of the method as a callable value
+ that takes a request value and a ServicerContext object and returns an
+ iterator of response values. Only non-None if cardinality is
+ cardinality.Cardinality.UNARY_STREAM and style is style.Service.INLINE.
+ stream_unary_inline: The implementation of the method as a callable value
+ that takes an iterator of request values and a ServicerContext object and
+ returns a response value. Only non-None if cardinality is
+ cardinality.Cardinality.STREAM_UNARY and style is style.Service.INLINE.
+ stream_stream_inline: The implementation of the method as a callable value
+ that takes an iterator of request values and a ServicerContext object and
+ returns an iterator of response values. Only non-None if cardinality is
+ cardinality.Cardinality.STREAM_STREAM and style is style.Service.INLINE.
+ unary_unary_event: The implementation of the method as a callable value that
+ takes a request value, a response callback to which to pass the response
+ value of the RPC, and a ServicerContext. Only non-None if cardinality is
+ cardinality.Cardinality.UNARY_UNARY and style is style.Service.EVENT.
+ unary_stream_event: The implementation of the method as a callable value
+ that takes a request value, a stream.Consumer to which to pass the
+ response values of the RPC, and a ServicerContext. Only non-None if
+ cardinality is cardinality.Cardinality.UNARY_STREAM and style is
+ style.Service.EVENT.
+ stream_unary_event: The implementation of the method as a callable value
+ that takes a response callback to which to pass the response value of the
+ RPC and a ServicerContext and returns a stream.Consumer to which the
+ request values of the RPC should be passed. Only non-None if cardinality
+ is cardinality.Cardinality.STREAM_UNARY and style is style.Service.EVENT.
+ stream_stream_event: The implementation of the method as a callable value
+ that takes a stream.Consumer to which to pass the response values of the
+ RPC and a ServicerContext and returns a stream.Consumer to which the
+ request values of the RPC should be passed. Only non-None if cardinality
+ is cardinality.Cardinality.STREAM_STREAM and style is
+ style.Service.EVENT.
+ """
+ __metaclass__ = abc.ABCMeta
+
+
+class MultiMethodImplementation(object):
+ """A general type able to service many methods."""
+ __metaclass__ = abc.ABCMeta
+
+ @abc.abstractmethod
+ def service(self, group, method, response_consumer, context):
+ """Services an RPC.
+
+ Args:
+ group: The group identifier of the RPC.
+ method: The method identifier of the RPC.
+ response_consumer: A stream.Consumer to be called to accept the response
+ values of the RPC.
+ context: a ServicerContext object.
+
+ Returns:
+ A stream.Consumer with which to accept the request values of the RPC. The
+ consumer returned from this method may or may not be invoked to
+ completion: in the case of RPC abortion, RPC Framework will simply stop
+ passing values to this object. Implementations must not assume that this
+ object will be called to completion of the request stream or even called
+ at all.
+
+ Raises:
+ abandonment.Abandoned: May or may not be raised when the RPC has been
+ aborted.
+ NoSuchMethodError: If this MultiMethod does not recognize the given group
+ and name for the RPC and is not able to service the RPC.
+ """
+ raise NotImplementedError()
+
+
+class GenericStub(object):
+ """Affords RPC invocation via generic methods."""
+ __metaclass__ = abc.ABCMeta
+
+ @abc.abstractmethod
+ def blocking_unary_unary(
+ self, group, method, request, timeout, metadata=None,
+ with_call=False):
+ """Invokes a unary-request-unary-response method.
+
+ This method blocks until either returning the response value of the RPC
+ (in the event of RPC completion) or raising an exception (in the event of
+ RPC abortion).
+
+ Args:
+ group: The group identifier of the RPC.
+ method: The method identifier of the RPC.
+ request: The request value for the RPC.
+ timeout: A duration of time in seconds to allow for the RPC.
+ metadata: A metadata value to be passed to the service-side of the RPC.
+ with_call: Whether or not to include return a Call for the RPC in addition
+ to the reponse.
+
+ Returns:
+ The response value for the RPC, and a Call for the RPC if with_call was
+ set to True at invocation.
+
+ Raises:
+ AbortionError: Indicating that the RPC was aborted.
+ """
+ raise NotImplementedError()
+
+ @abc.abstractmethod
+ def future_unary_unary(
+ self, group, method, request, timeout, metadata=None):
+ """Invokes a unary-request-unary-response method.
+
+ Args:
+ group: The group identifier of the RPC.
+ method: The method identifier of the RPC.
+ request: The request value for the RPC.
+ timeout: A duration of time in seconds to allow for the RPC.
+ metadata: A metadata value to be passed to the service-side of the RPC.
+
+ Returns:
+ An object that is both a Call for the RPC and a future.Future. In the
+ event of RPC completion, the return Future's result value will be the
+ response value of the RPC. In the event of RPC abortion, the returned
+ Future's exception value will be an AbortionError.
+ """
+ raise NotImplementedError()
+
+ @abc.abstractmethod
+ def inline_unary_stream(
+ self, group, method, request, timeout, metadata=None):
+ """Invokes a unary-request-stream-response method.
+
+ Args:
+ group: The group identifier of the RPC.
+ method: The method identifier of the RPC.
+ request: The request value for the RPC.
+ timeout: A duration of time in seconds to allow for the RPC.
+ metadata: A metadata value to be passed to the service-side of the RPC.
+
+ Returns:
+ An object that is both a Call for the RPC and an iterator of response
+ values. Drawing response values from the returned iterator may raise
+ AbortionError indicating abortion of the RPC.
+ """
+ raise NotImplementedError()
+
+ @abc.abstractmethod
+ def blocking_stream_unary(
+ self, group, method, request_iterator, timeout, metadata=None,
+ with_call=False):
+ """Invokes a stream-request-unary-response method.
+
+ This method blocks until either returning the response value of the RPC
+ (in the event of RPC completion) or raising an exception (in the event of
+ RPC abortion).
+
+ Args:
+ group: The group identifier of the RPC.
+ method: The method identifier of the RPC.
+ request_iterator: An iterator that yields request values for the RPC.
+ timeout: A duration of time in seconds to allow for the RPC.
+ metadata: A metadata value to be passed to the service-side of the RPC.
+ with_call: Whether or not to include return a Call for the RPC in addition
+ to the reponse.
+
+ Returns:
+ The response value for the RPC, and a Call for the RPC if with_call was
+ set to True at invocation.
+
+ Raises:
+ AbortionError: Indicating that the RPC was aborted.
+ """
+ raise NotImplementedError()
+
+ @abc.abstractmethod
+ def future_stream_unary(
+ self, group, method, request_iterator, timeout, metadata=None):
+ """Invokes a stream-request-unary-response method.
+
+ Args:
+ group: The group identifier of the RPC.
+ method: The method identifier of the RPC.
+ request_iterator: An iterator that yields request values for the RPC.
+ timeout: A duration of time in seconds to allow for the RPC.
+ metadata: A metadata value to be passed to the service-side of the RPC.
+
+ Returns:
+ An object that is both a Call for the RPC and a future.Future. In the
+ event of RPC completion, the return Future's result value will be the
+ response value of the RPC. In the event of RPC abortion, the returned
+ Future's exception value will be an AbortionError.
+ """
+ raise NotImplementedError()
+
+ @abc.abstractmethod
+ def inline_stream_stream(
+ self, group, method, request_iterator, timeout, metadata=None):
+ """Invokes a stream-request-stream-response method.
+
+ Args:
+ group: The group identifier of the RPC.
+ method: The method identifier of the RPC.
+ request_iterator: An iterator that yields request values for the RPC.
+ timeout: A duration of time in seconds to allow for the RPC.
+ metadata: A metadata value to be passed to the service-side of the RPC.
+
+ Returns:
+ An object that is both a Call for the RPC and an iterator of response
+ values. Drawing response values from the returned iterator may raise
+ AbortionError indicating abortion of the RPC.
+ """
+ raise NotImplementedError()
+
+ @abc.abstractmethod
+ def event_unary_unary(
+ self, group, method, request, receiver, abortion_callback, timeout,
+ metadata=None):
+ """Event-driven invocation of a unary-request-unary-response method.
+
+ Args:
+ group: The group identifier of the RPC.
+ method: The method identifier of the RPC.
+ request: The request value for the RPC.
+ receiver: A ResponseReceiver to be passed the response data of the RPC.
+ abortion_callback: A callback to be called and passed an Abortion value
+ in the event of RPC abortion.
+ timeout: A duration of time in seconds to allow for the RPC.
+ metadata: A metadata value to be passed to the service-side of the RPC.
+
+ Returns:
+ A Call for the RPC.
+ """
+ raise NotImplementedError()
+
+ @abc.abstractmethod
+ def event_unary_stream(
+ self, group, method, request, receiver, abortion_callback, timeout,
+ metadata=None):
+ """Event-driven invocation of a unary-request-stream-response method.
+
+ Args:
+ group: The group identifier of the RPC.
+ method: The method identifier of the RPC.
+ request: The request value for the RPC.
+ receiver: A ResponseReceiver to be passed the response data of the RPC.
+ abortion_callback: A callback to be called and passed an Abortion value
+ in the event of RPC abortion.
+ timeout: A duration of time in seconds to allow for the RPC.
+ metadata: A metadata value to be passed to the service-side of the RPC.
+
+ Returns:
+ A Call for the RPC.
+ """
+ raise NotImplementedError()
+
+ @abc.abstractmethod
+ def event_stream_unary(
+ self, group, method, receiver, abortion_callback, timeout,
+ metadata=None):
+ """Event-driven invocation of a unary-request-unary-response method.
+
+ Args:
+ group: The group identifier of the RPC.
+ method: The method identifier of the RPC.
+ receiver: A ResponseReceiver to be passed the response data of the RPC.
+ abortion_callback: A callback to be called and passed an Abortion value
+ in the event of RPC abortion.
+ timeout: A duration of time in seconds to allow for the RPC.
+ metadata: A metadata value to be passed to the service-side of the RPC.
+
+ Returns:
+ A pair of a Call object for the RPC and a stream.Consumer to which the
+ request values of the RPC should be passed.
+ """
+ raise NotImplementedError()
+
+ @abc.abstractmethod
+ def event_stream_stream(
+ self, group, method, receiver, abortion_callback, timeout,
+ metadata=None):
+ """Event-driven invocation of a unary-request-stream-response method.
+
+ Args:
+ group: The group identifier of the RPC.
+ method: The method identifier of the RPC.
+ receiver: A ResponseReceiver to be passed the response data of the RPC.
+ abortion_callback: A callback to be called and passed an Abortion value
+ in the event of RPC abortion.
+ timeout: A duration of time in seconds to allow for the RPC.
+ metadata: A metadata value to be passed to the service-side of the RPC.
+
+ Returns:
+ A pair of a Call object for the RPC and a stream.Consumer to which the
+ request values of the RPC should be passed.
+ """
+ raise NotImplementedError()
+
+ @abc.abstractmethod
+ def unary_unary(self, group, method):
+ """Creates a UnaryUnaryMultiCallable for a unary-unary method.
+
+ Args:
+ group: The group identifier of the RPC.
+ method: The method identifier of the RPC.
+
+ Returns:
+ A UnaryUnaryMultiCallable value for the named unary-unary method.
+ """
+ raise NotImplementedError()
+
+ @abc.abstractmethod
+ def unary_stream(self, group, method):
+ """Creates a UnaryStreamMultiCallable for a unary-stream method.
+
+ Args:
+ group: The group identifier of the RPC.
+ method: The method identifier of the RPC.
+
+ Returns:
+ A UnaryStreamMultiCallable value for the name unary-stream method.
+ """
+ raise NotImplementedError()
+
+ @abc.abstractmethod
+ def stream_unary(self, group, method):
+ """Creates a StreamUnaryMultiCallable for a stream-unary method.
+
+ Args:
+ group: The group identifier of the RPC.
+ method: The method identifier of the RPC.
+
+ Returns:
+ A StreamUnaryMultiCallable value for the named stream-unary method.
+ """
+ raise NotImplementedError()
+
+ @abc.abstractmethod
+ def stream_stream(self, group, method):
+ """Creates a StreamStreamMultiCallable for a stream-stream method.
+
+ Args:
+ group: The group identifier of the RPC.
+ method: The method identifier of the RPC.
+
+ Returns:
+ A StreamStreamMultiCallable value for the named stream-stream method.
+ """
+ raise NotImplementedError()
+
+
+class DynamicStub(object):
+ """Affords RPC invocation via attributes corresponding to afforded methods.
+
+ Instances of this type may be scoped to a single group so that attribute
+ access is unambiguous.
+
+ Instances of this type respond to attribute access as follows: if the
+ requested attribute is the name of a unary-unary method, the value of the
+ attribute will be a UnaryUnaryMultiCallable with which to invoke an RPC; if
+ the requested attribute is the name of a unary-stream method, the value of the
+ attribute will be a UnaryStreamMultiCallable with which to invoke an RPC; if
+ the requested attribute is the name of a stream-unary method, the value of the
+ attribute will be a StreamUnaryMultiCallable with which to invoke an RPC; and
+ if the requested attribute is the name of a stream-stream method, the value of
+ the attribute will be a StreamStreamMultiCallable with which to invoke an RPC.
+ """
+ __metaclass__ = abc.ABCMeta
diff --git a/src/python/grpcio/grpc/framework/interfaces/face/utilities.py b/src/python/grpcio/grpc/framework/interfaces/face/utilities.py
new file mode 100644
index 0000000000..db2ec6ed87
--- /dev/null
+++ b/src/python/grpcio/grpc/framework/interfaces/face/utilities.py
@@ -0,0 +1,178 @@
+# Copyright 2015, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""Utilities for RPC Framework's Face interface."""
+
+import collections
+
+# stream is referenced from specification in this module.
+from grpc.framework.common import cardinality
+from grpc.framework.common import style
+from grpc.framework.foundation import stream # pylint: disable=unused-import
+from grpc.framework.interfaces.face import face
+
+
+class _MethodImplementation(
+ face.MethodImplementation,
+ collections.namedtuple(
+ '_MethodImplementation',
+ ['cardinality', 'style', 'unary_unary_inline', 'unary_stream_inline',
+ 'stream_unary_inline', 'stream_stream_inline', 'unary_unary_event',
+ 'unary_stream_event', 'stream_unary_event', 'stream_stream_event',])):
+ pass
+
+
+def unary_unary_inline(behavior):
+ """Creates an face.MethodImplementation for the given behavior.
+
+ Args:
+ behavior: The implementation of a unary-unary RPC method as a callable value
+ that takes a request value and an face.ServicerContext object and
+ returns a response value.
+
+ Returns:
+ An face.MethodImplementation derived from the given behavior.
+ """
+ return _MethodImplementation(
+ cardinality.Cardinality.UNARY_UNARY, style.Service.INLINE, behavior,
+ None, None, None, None, None, None, None)
+
+
+def unary_stream_inline(behavior):
+ """Creates an face.MethodImplementation for the given behavior.
+
+ Args:
+ behavior: The implementation of a unary-stream RPC method as a callable
+ value that takes a request value and an face.ServicerContext object and
+ returns an iterator of response values.
+
+ Returns:
+ An face.MethodImplementation derived from the given behavior.
+ """
+ return _MethodImplementation(
+ cardinality.Cardinality.UNARY_STREAM, style.Service.INLINE, None,
+ behavior, None, None, None, None, None, None)
+
+
+def stream_unary_inline(behavior):
+ """Creates an face.MethodImplementation for the given behavior.
+
+ Args:
+ behavior: The implementation of a stream-unary RPC method as a callable
+ value that takes an iterator of request values and an
+ face.ServicerContext object and returns a response value.
+
+ Returns:
+ An face.MethodImplementation derived from the given behavior.
+ """
+ return _MethodImplementation(
+ cardinality.Cardinality.STREAM_UNARY, style.Service.INLINE, None, None,
+ behavior, None, None, None, None, None)
+
+
+def stream_stream_inline(behavior):
+ """Creates an face.MethodImplementation for the given behavior.
+
+ Args:
+ behavior: The implementation of a stream-stream RPC method as a callable
+ value that takes an iterator of request values and an
+ face.ServicerContext object and returns an iterator of response values.
+
+ Returns:
+ An face.MethodImplementation derived from the given behavior.
+ """
+ return _MethodImplementation(
+ cardinality.Cardinality.STREAM_STREAM, style.Service.INLINE, None, None,
+ None, behavior, None, None, None, None)
+
+
+def unary_unary_event(behavior):
+ """Creates an face.MethodImplementation for the given behavior.
+
+ Args:
+ behavior: The implementation of a unary-unary RPC method as a callable
+ value that takes a request value, a response callback to which to pass
+ the response value of the RPC, and an face.ServicerContext.
+
+ Returns:
+ An face.MethodImplementation derived from the given behavior.
+ """
+ return _MethodImplementation(
+ cardinality.Cardinality.UNARY_UNARY, style.Service.EVENT, None, None,
+ None, None, behavior, None, None, None)
+
+
+def unary_stream_event(behavior):
+ """Creates an face.MethodImplementation for the given behavior.
+
+ Args:
+ behavior: The implementation of a unary-stream RPC method as a callable
+ value that takes a request value, a stream.Consumer to which to pass the
+ the response values of the RPC, and an face.ServicerContext.
+
+ Returns:
+ An face.MethodImplementation derived from the given behavior.
+ """
+ return _MethodImplementation(
+ cardinality.Cardinality.UNARY_STREAM, style.Service.EVENT, None, None,
+ None, None, None, behavior, None, None)
+
+
+def stream_unary_event(behavior):
+ """Creates an face.MethodImplementation for the given behavior.
+
+ Args:
+ behavior: The implementation of a stream-unary RPC method as a callable
+ value that takes a response callback to which to pass the response value
+ of the RPC and an face.ServicerContext and returns a stream.Consumer to
+ which the request values of the RPC should be passed.
+
+ Returns:
+ An face.MethodImplementation derived from the given behavior.
+ """
+ return _MethodImplementation(
+ cardinality.Cardinality.STREAM_UNARY, style.Service.EVENT, None, None,
+ None, None, None, None, behavior, None)
+
+
+def stream_stream_event(behavior):
+ """Creates an face.MethodImplementation for the given behavior.
+
+ Args:
+ behavior: The implementation of a stream-stream RPC method as a callable
+ value that takes a stream.Consumer to which to pass the response values
+ of the RPC and an face.ServicerContext and returns a stream.Consumer to
+ which the request values of the RPC should be passed.
+
+ Returns:
+ An face.MethodImplementation derived from the given behavior.
+ """
+ return _MethodImplementation(
+ cardinality.Cardinality.STREAM_STREAM, style.Service.EVENT, None, None,
+ None, None, None, None, None, behavior)
diff --git a/src/python/grpcio/grpc/framework/interfaces/links/links.py b/src/python/grpcio/grpc/framework/interfaces/links/links.py
index 069ff024dd..b98a30a399 100644
--- a/src/python/grpcio/grpc/framework/interfaces/links/links.py
+++ b/src/python/grpcio/grpc/framework/interfaces/links/links.py
@@ -34,12 +34,30 @@ import collections
import enum
+class Transport(collections.namedtuple('Transport', ('kind', 'value',))):
+ """A sum type for handles to an underlying transport system.
+
+ Attributes:
+ kind: A Kind value identifying the kind of value being passed to or from
+ the underlying transport.
+ value: The value being passed through RPC Framework between the high-level
+ application and the underlying transport.
+ """
+
+ @enum.unique
+ class Kind(enum.Enum):
+ CALL_OPTION = 'call option'
+ SERVICER_CONTEXT = 'servicer context'
+ INVOCATION_CONTEXT = 'invocation context'
+
+
class Ticket(
collections.namedtuple(
'Ticket',
- ['operation_id', 'sequence_number', 'group', 'method', 'subscription',
+ ('operation_id', 'sequence_number', 'group', 'method', 'subscription',
'timeout', 'allowance', 'initial_metadata', 'payload',
- 'terminal_metadata', 'code', 'message', 'termination'])):
+ 'terminal_metadata', 'code', 'message', 'termination',
+ 'transport',))):
"""A sum type for all values sent from a front to a back.
Attributes:
@@ -81,6 +99,8 @@ class Ticket(
termination: A Termination value describing the end of the operation, or
None if the operation has not yet terminated. If set, no further tickets
may be sent in the same direction.
+ transport: A Transport value or None, with further semantics being a matter
+ between high-level application and underlying transport.
"""
@enum.unique