aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/python/grpcio
diff options
context:
space:
mode:
Diffstat (limited to 'src/python/grpcio')
-rw-r--r--src/python/grpcio/README.rst13
-rw-r--r--src/python/grpcio/grpc/_adapter/fore.py363
-rw-r--r--src/python/grpcio/grpc/_adapter/rear.py395
-rw-r--r--src/python/grpcio/grpc/_cython/imports.generated.c2
-rw-r--r--src/python/grpcio/grpc/_cython/imports.generated.h3
-rw-r--r--src/python/grpcio/grpc/beta/implementations.py9
-rw-r--r--src/python/grpcio/grpc/early_adopter/__init__.py35
-rw-r--r--src/python/grpcio/grpc/early_adopter/implementations.py262
-rw-r--r--src/python/grpcio/grpc/framework/alpha/__init__.py35
-rw-r--r--src/python/grpcio/grpc/framework/alpha/_face_utilities.py183
-rw-r--r--src/python/grpcio/grpc/framework/alpha/_reexport.py205
-rw-r--r--src/python/grpcio/grpc/framework/alpha/interfaces.py384
-rw-r--r--src/python/grpcio/grpc/framework/alpha/utilities.py269
-rw-r--r--src/python/grpcio/grpc/framework/base/__init__.py35
-rw-r--r--src/python/grpcio/grpc/framework/base/_constants.py32
-rw-r--r--src/python/grpcio/grpc/framework/base/_context.py99
-rw-r--r--src/python/grpcio/grpc/framework/base/_emission.py125
-rw-r--r--src/python/grpcio/grpc/framework/base/_ends.py399
-rw-r--r--src/python/grpcio/grpc/framework/base/_expiration.py158
-rw-r--r--src/python/grpcio/grpc/framework/base/_ingestion.py443
-rw-r--r--src/python/grpcio/grpc/framework/base/_interfaces.py266
-rw-r--r--src/python/grpcio/grpc/framework/base/_reception.py400
-rw-r--r--src/python/grpcio/grpc/framework/base/_termination.py204
-rw-r--r--src/python/grpcio/grpc/framework/base/_transmission.py429
-rw-r--r--src/python/grpcio/grpc/framework/base/implementations.py77
-rw-r--r--src/python/grpcio/grpc/framework/base/in_memory.py108
-rw-r--r--src/python/grpcio/grpc/framework/base/interfaces.py353
-rw-r--r--src/python/grpcio/grpc/framework/base/util.py94
-rw-r--r--src/python/grpcio/grpc/framework/face/__init__.py35
-rw-r--r--src/python/grpcio/grpc/framework/face/_calls.py422
-rw-r--r--src/python/grpcio/grpc/framework/face/_control.py201
-rw-r--r--src/python/grpcio/grpc/framework/face/_service.py187
-rw-r--r--src/python/grpcio/grpc/framework/face/demonstration.py118
-rw-r--r--src/python/grpcio/grpc/framework/face/implementations.py320
-rw-r--r--src/python/grpcio/grpc/framework/face/interfaces.py634
-rw-r--r--src/python/grpcio/grpc/framework/face/utilities.py177
-rw-r--r--src/python/grpcio/tests/protoc_plugin/beta_python_plugin_test.py41
-rw-r--r--src/python/grpcio/tests/qps/__init__.py (renamed from src/python/grpcio/tests/unit/framework/face/__init__.py)4
-rw-r--r--src/python/grpcio/tests/qps/benchmark_client.py186
-rw-r--r--src/python/grpcio/tests/qps/benchmark_server.py (renamed from src/python/grpcio/grpc/framework/base/exceptions.py)32
-rw-r--r--src/python/grpcio/tests/qps/client_runner.py104
-rw-r--r--src/python/grpcio/tests/qps/histogram.py (renamed from src/python/grpcio/grpc/framework/base/_cancellation.py)79
-rw-r--r--src/python/grpcio/tests/qps/qps_worker.py (renamed from src/python/grpcio/grpc/framework/base/null.py)44
-rw-r--r--src/python/grpcio/tests/qps/worker_server.py184
-rw-r--r--src/python/grpcio/tests/stress/__init__.py (renamed from src/python/grpcio/tests/unit/framework/face/testing/__init__.py)4
-rw-r--r--src/python/grpcio/tests/stress/client.py132
-rw-r--r--src/python/grpcio/tests/stress/metrics_server.py (renamed from src/python/grpcio/grpc/framework/alpha/exceptions.py)37
-rw-r--r--src/python/grpcio/tests/stress/test_runner.py (renamed from src/python/grpcio/grpc/framework/face/exceptions.py)95
-rw-r--r--src/python/grpcio/tests/unit/framework/face/testing/base_util.py102
-rw-r--r--src/python/grpcio/tests/unit/framework/face/testing/blocking_invocation_inline_service_test_case.py224
-rw-r--r--src/python/grpcio/tests/unit/framework/face/testing/callback.py94
-rw-r--r--src/python/grpcio/tests/unit/framework/face/testing/control.py87
-rw-r--r--src/python/grpcio/tests/unit/framework/face/testing/coverage.py121
-rw-r--r--src/python/grpcio/tests/unit/framework/face/testing/digest.py452
-rw-r--r--src/python/grpcio/tests/unit/framework/face/testing/event_invocation_synchronous_event_service_test_case.py378
-rw-r--r--src/python/grpcio/tests/unit/framework/face/testing/future_invocation_asynchronous_event_service_test_case.py384
-rw-r--r--src/python/grpcio/tests/unit/framework/face/testing/interfaces.py118
-rw-r--r--src/python/grpcio/tests/unit/framework/face/testing/service.py321
-rw-r--r--src/python/grpcio/tests/unit/framework/face/testing/stock_service.py374
-rw-r--r--src/python/grpcio/tests/unit/framework/face/testing/test_case.py81
60 files changed, 845 insertions, 10307 deletions
diff --git a/src/python/grpcio/README.rst b/src/python/grpcio/README.rst
index 33a462b66f..cb3f6b87fe 100644
--- a/src/python/grpcio/README.rst
+++ b/src/python/grpcio/README.rst
@@ -23,6 +23,16 @@ Else system wide (on Ubuntu)...
$ sudo pip install grpcio
+If you're on Windows make sure that you installed the :code:`pip.exe` component
+when you installed Python (if not go back and install it!) then invoke:
+
+::
+
+ $ pip.exe install grpcio
+
+Windows users may need to invoke :code:`pip.exe` from a command line ran as
+administrator.
+
n.b. On Windows and on Mac OS X one *must* have a recent release of :code:`pip`
to retrieve the proper wheel from PyPI. Be sure to upgrade to the latest
version!
@@ -43,6 +53,9 @@ package named :code:`python-dev`).
$ pip install -rrequirements.txt
$ GRPC_PYTHON_BUILD_WITH_CYTHON=1 pip install .
+You cannot currently install Python from source on Windows. Things might work
+out for you in MSYS2 (follow the Linux instructions), but it isn't officially
+supported at the moment.
Troubleshooting
~~~~~~~~~~~~~~~
diff --git a/src/python/grpcio/grpc/_adapter/fore.py b/src/python/grpcio/grpc/_adapter/fore.py
deleted file mode 100644
index acdd69c420..0000000000
--- a/src/python/grpcio/grpc/_adapter/fore.py
+++ /dev/null
@@ -1,363 +0,0 @@
-# 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.
-
-"""The RPC-service-side bridge between RPC Framework and GRPC-on-the-wire."""
-
-import enum
-import logging
-import threading
-import time
-
-from grpc._adapter import _common
-from grpc._adapter import _intermediary_low as _low
-from grpc.framework.base import interfaces as base_interfaces
-from grpc.framework.base import null
-from grpc.framework.foundation import activated
-from grpc.framework.foundation import logging_pool
-
-_THREAD_POOL_SIZE = 10
-
-
-@enum.unique
-class _LowWrite(enum.Enum):
- """The possible categories of low-level write state."""
-
- OPEN = 'OPEN'
- ACTIVE = 'ACTIVE'
- CLOSED = 'CLOSED'
-
-
-def _write(call, rpc_state, payload):
- serialized_payload = rpc_state.serializer(payload)
- if rpc_state.write.low is _LowWrite.OPEN:
- call.write(serialized_payload, call, 0)
- rpc_state.write.low = _LowWrite.ACTIVE
- else:
- rpc_state.write.pending.append(serialized_payload)
-
-
-def _status(call, rpc_state):
- call.status(_low.Status(_low.Code.OK, ''), call)
- rpc_state.write.low = _LowWrite.CLOSED
-
-
-class ForeLink(base_interfaces.ForeLink, activated.Activated):
- """A service-side bridge between RPC Framework and the C-ish _low code."""
-
- def __init__(
- self, pool, request_deserializers, response_serializers,
- root_certificates, key_chain_pairs, port=None):
- """Constructor.
-
- Args:
- pool: A thread pool.
- request_deserializers: A dict from RPC method names to request object
- deserializer behaviors.
- response_serializers: A dict from RPC method names to response object
- serializer behaviors.
- root_certificates: The PEM-encoded client root certificates as a
- bytestring or None.
- key_chain_pairs: A sequence of PEM-encoded private key-certificate chain
- pairs.
- port: The port on which to serve, or None to have a port selected
- automatically.
- """
- self._condition = threading.Condition()
- self._pool = pool
- self._request_deserializers = request_deserializers
- self._response_serializers = response_serializers
- self._root_certificates = root_certificates
- self._key_chain_pairs = key_chain_pairs
- self._requested_port = port
-
- self._rear_link = null.NULL_REAR_LINK
- self._completion_queue = None
- self._server = None
- self._rpc_states = {}
- self._spinning = False
- self._port = None
-
- def _on_stop_event(self):
- self._spinning = False
- self._condition.notify_all()
-
- def _on_service_acceptance_event(self, event, server):
- """Handle a service invocation event."""
- service_acceptance = event.service_acceptance
- if service_acceptance is None:
- return
-
- call = service_acceptance.call
- call.accept(self._completion_queue, call)
- # TODO(nathaniel): Metadata support.
- call.premetadata()
- call.read(call)
- method = service_acceptance.method
-
- self._rpc_states[call] = _common.CommonRPCState(
- _common.WriteState(_LowWrite.OPEN, _common.HighWrite.OPEN, []), 1,
- self._request_deserializers[method],
- self._response_serializers[method])
-
- ticket = base_interfaces.FrontToBackTicket(
- call, 0, base_interfaces.FrontToBackTicket.Kind.COMMENCEMENT, method,
- base_interfaces.ServicedSubscription.Kind.FULL, None, None,
- service_acceptance.deadline - time.time())
- self._rear_link.accept_front_to_back_ticket(ticket)
-
- server.service(None)
-
- def _on_read_event(self, event):
- """Handle data arriving during an RPC."""
- call = event.tag
- rpc_state = self._rpc_states.get(call, None)
- if rpc_state is None:
- return
-
- sequence_number = rpc_state.sequence_number
- rpc_state.sequence_number += 1
- if event.bytes is None:
- ticket = base_interfaces.FrontToBackTicket(
- call, sequence_number,
- base_interfaces.FrontToBackTicket.Kind.COMPLETION, None, None, None,
- None, None)
- else:
- call.read(call)
- ticket = base_interfaces.FrontToBackTicket(
- call, sequence_number,
- base_interfaces.FrontToBackTicket.Kind.CONTINUATION, None, None,
- None, rpc_state.deserializer(event.bytes), None)
-
- self._rear_link.accept_front_to_back_ticket(ticket)
-
- def _on_write_event(self, event):
- call = event.tag
- rpc_state = self._rpc_states.get(call, None)
- if rpc_state is None:
- return
-
- if rpc_state.write.pending:
- serialized_payload = rpc_state.write.pending.pop(0)
- call.write(serialized_payload, call, 0)
- elif rpc_state.write.high is _common.HighWrite.CLOSED:
- _status(call, rpc_state)
- else:
- rpc_state.write.low = _LowWrite.OPEN
-
- def _on_complete_event(self, event):
- if not event.complete_accepted:
- logging.error('Complete not accepted! %s', (event,))
- call = event.tag
- rpc_state = self._rpc_states.pop(call, None)
- if rpc_state is None:
- return
-
- sequence_number = rpc_state.sequence_number
- rpc_state.sequence_number += 1
- ticket = base_interfaces.FrontToBackTicket(
- call, sequence_number,
- base_interfaces.FrontToBackTicket.Kind.TRANSMISSION_FAILURE, None,
- None, None, None, None)
- self._rear_link.accept_front_to_back_ticket(ticket)
-
- def _on_finish_event(self, event):
- """Handle termination of an RPC."""
- call = event.tag
- rpc_state = self._rpc_states.pop(call, None)
- if rpc_state is None:
- return
-
- code = event.status.code
- if code is _low.Code.OK:
- return
-
- sequence_number = rpc_state.sequence_number
- rpc_state.sequence_number += 1
- if code is _low.Code.CANCELLED:
- ticket = base_interfaces.FrontToBackTicket(
- call, sequence_number,
- base_interfaces.FrontToBackTicket.Kind.CANCELLATION, None, None,
- None, None, None)
- elif code is _low.Code.DEADLINE_EXCEEDED:
- ticket = base_interfaces.FrontToBackTicket(
- call, sequence_number,
- base_interfaces.FrontToBackTicket.Kind.EXPIRATION, None, None, None,
- None, None)
- else:
- # TODO(nathaniel): Better mapping of codes to ticket-categories
- ticket = base_interfaces.FrontToBackTicket(
- call, sequence_number,
- base_interfaces.FrontToBackTicket.Kind.TRANSMISSION_FAILURE, None,
- None, None, None, None)
- self._rear_link.accept_front_to_back_ticket(ticket)
-
- def _spin(self, completion_queue, server):
- while True:
- event = completion_queue.get(None)
-
- with self._condition:
- if event.kind is _low.Event.Kind.STOP:
- self._on_stop_event()
- return
- elif self._server is None:
- continue
- elif event.kind is _low.Event.Kind.SERVICE_ACCEPTED:
- self._on_service_acceptance_event(event, server)
- elif event.kind is _low.Event.Kind.READ_ACCEPTED:
- self._on_read_event(event)
- elif event.kind is _low.Event.Kind.WRITE_ACCEPTED:
- self._on_write_event(event)
- elif event.kind is _low.Event.Kind.COMPLETE_ACCEPTED:
- self._on_complete_event(event)
- elif event.kind is _low.Event.Kind.FINISH:
- self._on_finish_event(event)
- else:
- logging.error('Illegal event! %s', (event,))
-
- def _continue(self, call, payload):
- rpc_state = self._rpc_states.get(call, None)
- if rpc_state is None:
- return
-
- _write(call, rpc_state, payload)
-
- def _complete(self, call, payload):
- """Handle completion of the writes of an RPC."""
- rpc_state = self._rpc_states.get(call, None)
- if rpc_state is None:
- return
-
- if rpc_state.write.low is _LowWrite.OPEN:
- if payload is None:
- _status(call, rpc_state)
- else:
- _write(call, rpc_state, payload)
- elif rpc_state.write.low is _LowWrite.ACTIVE:
- if payload is not None:
- rpc_state.write.pending.append(rpc_state.serializer(payload))
- else:
- raise ValueError('Called to complete after having already completed!')
- rpc_state.write.high = _common.HighWrite.CLOSED
-
- def _cancel(self, call):
- call.cancel()
- self._rpc_states.pop(call, None)
-
- def join_rear_link(self, rear_link):
- """See base_interfaces.ForeLink.join_rear_link for specification."""
- self._rear_link = null.NULL_REAR_LINK if rear_link is None else rear_link
-
- def _start(self):
- """Starts this ForeLink.
-
- This method must be called before attempting to exchange tickets with this
- object.
- """
- with self._condition:
- address = '[::]:%d' % (
- 0 if self._requested_port is None else self._requested_port)
- self._completion_queue = _low.CompletionQueue()
- if self._root_certificates is None and not self._key_chain_pairs:
- self._server = _low.Server(self._completion_queue)
- self._port = self._server.add_http2_addr(address)
- else:
- server_credentials = _low.ServerCredentials(
- self._root_certificates, self._key_chain_pairs, False)
- self._server = _low.Server(self._completion_queue)
- self._port = self._server.add_secure_http2_addr(
- address, server_credentials)
- self._server.start()
-
- self._server.service(None)
-
- self._pool.submit(self._spin, self._completion_queue, self._server)
- self._spinning = True
-
- return self
-
- # TODO(nathaniel): Expose graceful-shutdown semantics in which this object
- # enters a state in which it finishes ongoing RPCs but refuses new ones.
- def _stop(self):
- """Stops this ForeLink.
-
- This method must be called for proper termination of this object, and no
- attempts to exchange tickets with this object may be made after this method
- has been called.
- """
- with self._condition:
- self._server.stop()
- # TODO(nathaniel): Yep, this is weird. Deleting a server shouldn't have a
- # behaviorally significant side-effect.
- self._server = None
- self._completion_queue.stop()
-
- while self._spinning:
- self._condition.wait()
-
- self._port = None
-
- def __enter__(self):
- """See activated.Activated.__enter__ for specification."""
- return self._start()
-
- def __exit__(self, exc_type, exc_val, exc_tb):
- """See activated.Activated.__exit__ for specification."""
- self._stop()
- return False
-
- def start(self):
- """See activated.Activated.start for specification."""
- return self._start()
-
- def stop(self):
- """See activated.Activated.stop for specification."""
- self._stop()
-
- def port(self):
- """Identifies the port on which this ForeLink is servicing RPCs.
-
- Returns:
- The number of the port on which this ForeLink is servicing RPCs, or None
- if this ForeLink is not currently activated and servicing RPCs.
- """
- with self._condition:
- return self._port
-
- def accept_back_to_front_ticket(self, ticket):
- """See base_interfaces.ForeLink.accept_back_to_front_ticket for spec."""
- with self._condition:
- if self._server is None:
- return
-
- if ticket.kind is base_interfaces.BackToFrontTicket.Kind.CONTINUATION:
- self._continue(ticket.operation_id, ticket.payload)
- elif ticket.kind is base_interfaces.BackToFrontTicket.Kind.COMPLETION:
- self._complete(ticket.operation_id, ticket.payload)
- else:
- self._cancel(ticket.operation_id)
diff --git a/src/python/grpcio/grpc/_adapter/rear.py b/src/python/grpcio/grpc/_adapter/rear.py
deleted file mode 100644
index 17fa47f746..0000000000
--- a/src/python/grpcio/grpc/_adapter/rear.py
+++ /dev/null
@@ -1,395 +0,0 @@
-# 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.
-
-"""The RPC-invocation-side bridge between RPC Framework and GRPC-on-the-wire."""
-
-import enum
-import logging
-import threading
-import time
-
-from grpc._adapter import _common
-from grpc._adapter import _intermediary_low as _low
-from grpc.framework.base import interfaces as base_interfaces
-from grpc.framework.base import null
-from grpc.framework.foundation import activated
-from grpc.framework.foundation import logging_pool
-
-_THREAD_POOL_SIZE = 10
-
-_INVOCATION_EVENT_KINDS = (
- _low.Event.Kind.METADATA_ACCEPTED,
- _low.Event.Kind.FINISH
-)
-
-
-@enum.unique
-class _LowWrite(enum.Enum):
- """The possible categories of low-level write state."""
-
- OPEN = 'OPEN'
- ACTIVE = 'ACTIVE'
- CLOSED = 'CLOSED'
-
-
-class _RPCState(object):
- """The full state of any tracked RPC.
-
- Attributes:
- call: The _low.Call object for the RPC.
- outstanding: The set of Event.Kind values describing expected future events
- for the RPC.
- active: A boolean indicating whether or not the RPC is active.
- common: An _common.RPCState describing additional state for the RPC.
- """
-
- def __init__(self, call, outstanding, active, common):
- self.call = call
- self.outstanding = outstanding
- self.active = active
- self.common = common
-
-
-def _write(operation_id, call, outstanding, write_state, serialized_payload):
- if write_state.low is _LowWrite.OPEN:
- call.write(serialized_payload, operation_id, 0)
- outstanding.add(_low.Event.Kind.WRITE_ACCEPTED)
- write_state.low = _LowWrite.ACTIVE
- elif write_state.low is _LowWrite.ACTIVE:
- write_state.pending.append(serialized_payload)
- else:
- raise ValueError('Write attempted after writes completed!')
-
-
-class RearLink(base_interfaces.RearLink, activated.Activated):
- """An invocation-side bridge between RPC Framework and the C-ish _low code."""
-
- def __init__(
- self, host, port, pool, request_serializers, response_deserializers,
- secure, root_certificates, private_key, certificate_chain,
- metadata_transformer=None, server_host_override=None):
- """Constructor.
-
- Args:
- host: The host to which to connect for RPC service.
- port: The port to which to connect for RPC service.
- pool: A thread pool.
- request_serializers: A dict from RPC method names to request object
- serializer behaviors.
- response_deserializers: A dict from RPC method names to response object
- deserializer behaviors.
- secure: A boolean indicating whether or not to use a secure connection.
- root_certificates: The PEM-encoded root certificates or None to ask for
- them to be retrieved from a default location.
- private_key: The PEM-encoded private key to use or None if no private
- key should be used.
- certificate_chain: The PEM-encoded certificate chain to use or None if
- no certificate chain should be used.
- metadata_transformer: A function that given a metadata object produces
- another metadata to be used in the underlying communication on the
- wire.
- server_host_override: (For testing only) the target name used for SSL
- host name checking.
- """
- self._condition = threading.Condition()
- self._host = host
- self._port = port
- self._pool = pool
- self._request_serializers = request_serializers
- self._response_deserializers = response_deserializers
-
- self._fore_link = null.NULL_FORE_LINK
- self._completion_queue = None
- self._channel = None
- self._rpc_states = {}
- self._spinning = False
- if secure:
- self._client_credentials = _low.ClientCredentials(
- root_certificates, private_key, certificate_chain)
- else:
- self._client_credentials = None
- self._root_certificates = root_certificates
- self._private_key = private_key
- self._certificate_chain = certificate_chain
- self._metadata_transformer = metadata_transformer
- self._server_host_override = server_host_override
-
- def _on_write_event(self, operation_id, event, rpc_state):
- if event.write_accepted:
- if rpc_state.common.write.pending:
- rpc_state.call.write(
- rpc_state.common.write.pending.pop(0), operation_id, 0)
- rpc_state.outstanding.add(_low.Event.Kind.WRITE_ACCEPTED)
- elif rpc_state.common.write.high is _common.HighWrite.CLOSED:
- rpc_state.call.complete(operation_id)
- rpc_state.outstanding.add(_low.Event.Kind.COMPLETE_ACCEPTED)
- rpc_state.common.write.low = _LowWrite.CLOSED
- else:
- rpc_state.common.write.low = _LowWrite.OPEN
- else:
- logging.error('RPC write not accepted! Event: %s', (event,))
- rpc_state.active = False
- ticket = base_interfaces.BackToFrontTicket(
- operation_id, rpc_state.common.sequence_number,
- base_interfaces.BackToFrontTicket.Kind.TRANSMISSION_FAILURE, None)
- rpc_state.common.sequence_number += 1
- self._fore_link.accept_back_to_front_ticket(ticket)
-
- def _on_read_event(self, operation_id, event, rpc_state):
- if event.bytes is not None:
- rpc_state.call.read(operation_id)
- rpc_state.outstanding.add(_low.Event.Kind.READ_ACCEPTED)
-
- ticket = base_interfaces.BackToFrontTicket(
- operation_id, rpc_state.common.sequence_number,
- base_interfaces.BackToFrontTicket.Kind.CONTINUATION,
- rpc_state.common.deserializer(event.bytes))
- rpc_state.common.sequence_number += 1
- self._fore_link.accept_back_to_front_ticket(ticket)
-
- def _on_complete_event(self, operation_id, event, rpc_state):
- if not event.complete_accepted:
- logging.error('RPC complete not accepted! Event: %s', (event,))
- rpc_state.active = False
- ticket = base_interfaces.BackToFrontTicket(
- operation_id, rpc_state.common.sequence_number,
- base_interfaces.BackToFrontTicket.Kind.TRANSMISSION_FAILURE, None)
- rpc_state.common.sequence_number += 1
- self._fore_link.accept_back_to_front_ticket(ticket)
-
- # TODO(nathaniel): Metadata support.
- def _on_metadata_event(self, operation_id, event, rpc_state): # pylint: disable=unused-argument
- rpc_state.call.read(operation_id)
- rpc_state.outstanding.add(_low.Event.Kind.READ_ACCEPTED)
-
- def _on_finish_event(self, operation_id, event, rpc_state):
- """Handle termination of an RPC."""
- # TODO(nathaniel): Cover all statuses.
- if event.status.code is _low.Code.OK:
- kind = base_interfaces.BackToFrontTicket.Kind.COMPLETION
- elif event.status.code is _low.Code.CANCELLED:
- kind = base_interfaces.BackToFrontTicket.Kind.CANCELLATION
- elif event.status.code is _low.Code.DEADLINE_EXCEEDED:
- kind = base_interfaces.BackToFrontTicket.Kind.EXPIRATION
- else:
- kind = base_interfaces.BackToFrontTicket.Kind.TRANSMISSION_FAILURE
- ticket = base_interfaces.BackToFrontTicket(
- operation_id, rpc_state.common.sequence_number, kind, None)
- rpc_state.common.sequence_number += 1
- self._fore_link.accept_back_to_front_ticket(ticket)
-
- def _spin(self, completion_queue):
- while True:
- event = completion_queue.get(None)
- operation_id = event.tag
-
- with self._condition:
- rpc_state = self._rpc_states[operation_id]
- rpc_state.outstanding.remove(event.kind)
- if rpc_state.active and self._completion_queue is not None:
- if event.kind is _low.Event.Kind.WRITE_ACCEPTED:
- self._on_write_event(operation_id, event, rpc_state)
- elif event.kind is _low.Event.Kind.METADATA_ACCEPTED:
- self._on_metadata_event(operation_id, event, rpc_state)
- elif event.kind is _low.Event.Kind.READ_ACCEPTED:
- self._on_read_event(operation_id, event, rpc_state)
- elif event.kind is _low.Event.Kind.COMPLETE_ACCEPTED:
- self._on_complete_event(operation_id, event, rpc_state)
- elif event.kind is _low.Event.Kind.FINISH:
- self._on_finish_event(operation_id, event, rpc_state)
- else:
- logging.error('Illegal RPC event! %s', (event,))
-
- if not rpc_state.outstanding:
- self._rpc_states.pop(operation_id)
- if not self._rpc_states:
- self._spinning = False
- self._condition.notify_all()
- return
-
- def _invoke(self, operation_id, name, high_state, payload, timeout):
- """Invoke an RPC.
-
- Args:
- operation_id: Any object to be used as an operation ID for the RPC.
- name: The RPC method name.
- high_state: A _common.HighWrite value representing the "high write state"
- of the RPC.
- payload: A payload object for the RPC or None if no payload was given at
- invocation-time.
- timeout: A duration of time in seconds to allow for the RPC.
- """
- request_serializer = self._request_serializers[name]
- call = _low.Call(self._channel, self._completion_queue, name, self._host, time.time() + timeout)
- if self._metadata_transformer is not None:
- metadata = self._metadata_transformer([])
- for metadata_key, metadata_value in metadata:
- call.add_metadata(metadata_key, metadata_value)
- call.invoke(self._completion_queue, operation_id, operation_id)
- outstanding = set(_INVOCATION_EVENT_KINDS)
-
- if payload is None:
- if high_state is _common.HighWrite.CLOSED:
- call.complete(operation_id)
- low_state = _LowWrite.CLOSED
- outstanding.add(_low.Event.Kind.COMPLETE_ACCEPTED)
- else:
- low_state = _LowWrite.OPEN
- else:
- serialized_payload = request_serializer(payload)
- call.write(serialized_payload, operation_id, 0)
- outstanding.add(_low.Event.Kind.WRITE_ACCEPTED)
- low_state = _LowWrite.ACTIVE
-
- write_state = _common.WriteState(low_state, high_state, [])
- common_state = _common.CommonRPCState(
- write_state, 0, self._response_deserializers[name], request_serializer)
- self._rpc_states[operation_id] = _RPCState(
- call, outstanding, True, common_state)
-
- if not self._spinning:
- self._pool.submit(self._spin, self._completion_queue)
- self._spinning = True
-
- def _commence(self, operation_id, name, payload, timeout):
- self._invoke(operation_id, name, _common.HighWrite.OPEN, payload, timeout)
-
- def _continue(self, operation_id, payload):
- rpc_state = self._rpc_states.get(operation_id, None)
- if rpc_state is None or not rpc_state.active:
- return
-
- _write(
- operation_id, rpc_state.call, rpc_state.outstanding,
- rpc_state.common.write, rpc_state.common.serializer(payload))
-
- def _complete(self, operation_id, payload):
- """Close writes associated with an ongoing RPC.
-
- Args:
- operation_id: Any object being use as an operation ID for the RPC.
- payload: A payload object for the RPC (and thus the last payload object
- for the RPC) or None if no payload was given along with the instruction
- to indicate the end of writes for the RPC.
- """
- rpc_state = self._rpc_states.get(operation_id, None)
- if rpc_state is None or not rpc_state.active:
- return
-
- write_state = rpc_state.common.write
- if payload is None:
- if write_state.low is _LowWrite.OPEN:
- rpc_state.call.complete(operation_id)
- rpc_state.outstanding.add(_low.Event.Kind.COMPLETE_ACCEPTED)
- write_state.low = _LowWrite.CLOSED
- else:
- _write(
- operation_id, rpc_state.call, rpc_state.outstanding, write_state,
- rpc_state.common.serializer(payload))
- write_state.high = _common.HighWrite.CLOSED
-
- def _entire(self, operation_id, name, payload, timeout):
- self._invoke(operation_id, name, _common.HighWrite.CLOSED, payload, timeout)
-
- def _cancel(self, operation_id):
- rpc_state = self._rpc_states.get(operation_id, None)
- if rpc_state is not None and rpc_state.active:
- rpc_state.call.cancel()
- rpc_state.active = False
-
- def join_fore_link(self, fore_link):
- """See base_interfaces.RearLink.join_fore_link for specification."""
- with self._condition:
- self._fore_link = null.NULL_FORE_LINK if fore_link is None else fore_link
-
- def _start(self):
- """Starts this RearLink.
-
- This method must be called before attempting to exchange tickets with this
- object.
- """
- with self._condition:
- self._completion_queue = _low.CompletionQueue()
- self._channel = _low.Channel(
- '%s:%d' % (self._host, self._port), self._client_credentials,
- server_host_override=self._server_host_override)
- return self
-
- def _stop(self):
- """Stops this RearLink.
-
- This method must be called for proper termination of this object, and no
- attempts to exchange tickets with this object may be made after this method
- has been called.
- """
- with self._condition:
- self._completion_queue.stop()
- self._completion_queue = None
-
- while self._spinning:
- self._condition.wait()
-
- def __enter__(self):
- """See activated.Activated.__enter__ for specification."""
- return self._start()
-
- def __exit__(self, exc_type, exc_val, exc_tb):
- """See activated.Activated.__exit__ for specification."""
- self._stop()
- return False
-
- def start(self):
- """See activated.Activated.start for specification."""
- return self._start()
-
- def stop(self):
- """See activated.Activated.stop for specification."""
- self._stop()
-
- def accept_front_to_back_ticket(self, ticket):
- """See base_interfaces.RearLink.accept_front_to_back_ticket for spec."""
- with self._condition:
- if self._completion_queue is None:
- return
-
- if ticket.kind is base_interfaces.FrontToBackTicket.Kind.COMMENCEMENT:
- self._commence(
- ticket.operation_id, ticket.name, ticket.payload, ticket.timeout)
- elif ticket.kind is base_interfaces.FrontToBackTicket.Kind.CONTINUATION:
- self._continue(ticket.operation_id, ticket.payload)
- elif ticket.kind is base_interfaces.FrontToBackTicket.Kind.COMPLETION:
- self._complete(ticket.operation_id, ticket.payload)
- elif ticket.kind is base_interfaces.FrontToBackTicket.Kind.ENTIRE:
- self._entire(
- ticket.operation_id, ticket.name, ticket.payload, ticket.timeout)
- elif ticket.kind is base_interfaces.FrontToBackTicket.Kind.CANCELLATION:
- self._cancel(ticket.operation_id)
- else:
- # NOTE(nathaniel): All other categories are treated as cancellation.
- self._cancel(ticket.operation_id)
diff --git a/src/python/grpcio/grpc/_cython/imports.generated.c b/src/python/grpcio/grpc/_cython/imports.generated.c
index 9ab0696702..f0a40dbb35 100644
--- a/src/python/grpcio/grpc/_cython/imports.generated.c
+++ b/src/python/grpcio/grpc/_cython/imports.generated.c
@@ -124,6 +124,7 @@ grpc_tracer_set_enabled_type grpc_tracer_set_enabled_import;
grpc_header_key_is_legal_type grpc_header_key_is_legal_import;
grpc_header_nonbin_value_is_legal_type grpc_header_nonbin_value_is_legal_import;
grpc_is_binary_header_type grpc_is_binary_header_import;
+grpc_call_error_to_string_type grpc_call_error_to_string_import;
grpc_auth_property_iterator_next_type grpc_auth_property_iterator_next_import;
grpc_auth_context_property_iterator_type grpc_auth_context_property_iterator_import;
grpc_auth_context_peer_identity_type grpc_auth_context_peer_identity_import;
@@ -393,6 +394,7 @@ void pygrpc_load_imports(HMODULE library) {
grpc_header_key_is_legal_import = (grpc_header_key_is_legal_type) GetProcAddress(library, "grpc_header_key_is_legal");
grpc_header_nonbin_value_is_legal_import = (grpc_header_nonbin_value_is_legal_type) GetProcAddress(library, "grpc_header_nonbin_value_is_legal");
grpc_is_binary_header_import = (grpc_is_binary_header_type) GetProcAddress(library, "grpc_is_binary_header");
+ grpc_call_error_to_string_import = (grpc_call_error_to_string_type) GetProcAddress(library, "grpc_call_error_to_string");
grpc_auth_property_iterator_next_import = (grpc_auth_property_iterator_next_type) GetProcAddress(library, "grpc_auth_property_iterator_next");
grpc_auth_context_property_iterator_import = (grpc_auth_context_property_iterator_type) GetProcAddress(library, "grpc_auth_context_property_iterator");
grpc_auth_context_peer_identity_import = (grpc_auth_context_peer_identity_type) GetProcAddress(library, "grpc_auth_context_peer_identity");
diff --git a/src/python/grpcio/grpc/_cython/imports.generated.h b/src/python/grpcio/grpc/_cython/imports.generated.h
index e50051ddc7..d5e810b7cf 100644
--- a/src/python/grpcio/grpc/_cython/imports.generated.h
+++ b/src/python/grpcio/grpc/_cython/imports.generated.h
@@ -322,6 +322,9 @@ extern grpc_header_nonbin_value_is_legal_type grpc_header_nonbin_value_is_legal_
typedef int(*grpc_is_binary_header_type)(const char *key, size_t length);
extern grpc_is_binary_header_type grpc_is_binary_header_import;
#define grpc_is_binary_header grpc_is_binary_header_import
+typedef const char *(*grpc_call_error_to_string_type)(grpc_call_error error);
+extern grpc_call_error_to_string_type grpc_call_error_to_string_import;
+#define grpc_call_error_to_string grpc_call_error_to_string_import
typedef const grpc_auth_property *(*grpc_auth_property_iterator_next_type)(grpc_auth_property_iterator *it);
extern grpc_auth_property_iterator_next_type grpc_auth_property_iterator_next_import;
#define grpc_auth_property_iterator_next grpc_auth_property_iterator_next_import
diff --git a/src/python/grpcio/grpc/beta/implementations.py b/src/python/grpcio/grpc/beta/implementations.py
index 742e94dc65..822f593323 100644
--- a/src/python/grpcio/grpc/beta/implementations.py
+++ b/src/python/grpcio/grpc/beta/implementations.py
@@ -1,4 +1,4 @@
-# Copyright 2015, Google Inc.
+# Copyright 2015-2016, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -188,12 +188,13 @@ def insecure_channel(host, port):
Args:
host: The name of the remote host to which to connect.
port: The port of the remote host to which to connect.
+ If None only the 'host' part will be used.
Returns:
A Channel to the remote host through which RPCs may be conducted.
"""
intermediary_low_channel = _intermediary_low.Channel(
- '%s:%d' % (host, port), None)
+ '%s:%d' % (host, port) if port else host, None)
return Channel(intermediary_low_channel._internal, intermediary_low_channel) # pylint: disable=protected-access
@@ -203,13 +204,15 @@ def secure_channel(host, port, channel_credentials):
Args:
host: The name of the remote host to which to connect.
port: The port of the remote host to which to connect.
+ If None only the 'host' part will be used.
channel_credentials: A ChannelCredentials.
Returns:
A secure Channel to the remote host through which RPCs may be conducted.
"""
intermediary_low_channel = _intermediary_low.Channel(
- '%s:%d' % (host, port), channel_credentials._low_credentials)
+ '%s:%d' % (host, port) if port else host,
+ channel_credentials._low_credentials)
return Channel(intermediary_low_channel._internal, intermediary_low_channel) # pylint: disable=protected-access
diff --git a/src/python/grpcio/grpc/early_adopter/__init__.py b/src/python/grpcio/grpc/early_adopter/__init__.py
deleted file mode 100644
index bff74be2c7..0000000000
--- a/src/python/grpcio/grpc/early_adopter/__init__.py
+++ /dev/null
@@ -1,35 +0,0 @@
-# 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.
-
-import warnings
-
-warnings.simplefilter('always', DeprecationWarning)
-warnings.warn('the alpha API (includes this package) is deprecated, '
- 'unmaintained, and no longer tested. Please migrate to the beta '
- 'API.', DeprecationWarning, stacklevel=2)
diff --git a/src/python/grpcio/grpc/early_adopter/implementations.py b/src/python/grpcio/grpc/early_adopter/implementations.py
deleted file mode 100644
index 9c396aa7ad..0000000000
--- a/src/python/grpcio/grpc/early_adopter/implementations.py
+++ /dev/null
@@ -1,262 +0,0 @@
-# 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.
-
-"""Entry points into GRPC."""
-
-import threading
-
-from grpc._adapter import fore as _fore
-from grpc._adapter import rear as _rear
-from grpc.framework.alpha import _face_utilities
-from grpc.framework.alpha import _reexport
-from grpc.framework.alpha import interfaces
-from grpc.framework.base import implementations as _base_implementations
-from grpc.framework.base import util as _base_utilities
-from grpc.framework.face import implementations as _face_implementations
-from grpc.framework.foundation import logging_pool
-
-_DEFAULT_THREAD_POOL_SIZE = 8
-_ONE_DAY_IN_SECONDS = 24 * 60 * 60
-
-
-class _Server(interfaces.Server):
-
- def __init__(
- self, breakdown, port, private_key, certificate_chain,
- thread_pool_size=_DEFAULT_THREAD_POOL_SIZE):
- self._lock = threading.Lock()
- self._breakdown = breakdown
- self._port = port
- if private_key is None or certificate_chain is None:
- self._key_chain_pairs = ()
- else:
- self._key_chain_pairs = ((private_key, certificate_chain),)
-
- self._pool_size = thread_pool_size
- self._pool = None
- self._back = None
- self._fore_link = None
-
- def _start(self):
- with self._lock:
- if self._pool is None:
- self._pool = logging_pool.pool(self._pool_size)
- servicer = _face_implementations.servicer(
- self._pool, self._breakdown.implementations, None)
- self._back = _base_implementations.back_link(
- servicer, self._pool, self._pool, self._pool, _ONE_DAY_IN_SECONDS,
- _ONE_DAY_IN_SECONDS)
- self._fore_link = _fore.ForeLink(
- self._pool, self._breakdown.request_deserializers,
- self._breakdown.response_serializers, None, self._key_chain_pairs,
- port=self._port)
- self._back.join_fore_link(self._fore_link)
- self._fore_link.join_rear_link(self._back)
- self._fore_link.start()
- else:
- raise ValueError('Server currently running!')
-
- def _stop(self):
- with self._lock:
- if self._pool is None:
- raise ValueError('Server not running!')
- else:
- self._fore_link.stop()
- _base_utilities.wait_for_idle(self._back)
- self._pool.shutdown(wait=True)
- self._fore_link = None
- self._back = None
- self._pool = None
-
- def __enter__(self):
- self._start()
- return self
-
- def __exit__(self, exc_type, exc_val, exc_tb):
- self._stop()
- return False
-
- def start(self):
- self._start()
-
- def stop(self):
- self._stop()
-
- def port(self):
- with self._lock:
- return self._fore_link.port()
-
-
-class _Stub(interfaces.Stub):
-
- def __init__(
- self, breakdown, host, port, secure, root_certificates, private_key,
- certificate_chain, metadata_transformer=None, server_host_override=None,
- thread_pool_size=_DEFAULT_THREAD_POOL_SIZE):
- self._lock = threading.Lock()
- self._breakdown = breakdown
- self._host = host
- self._port = port
- self._secure = secure
- self._root_certificates = root_certificates
- self._private_key = private_key
- self._certificate_chain = certificate_chain
- self._metadata_transformer = metadata_transformer
- self._server_host_override = server_host_override
-
- self._pool_size = thread_pool_size
- self._pool = None
- self._front = None
- self._rear_link = None
- self._understub = None
-
- def __enter__(self):
- with self._lock:
- if self._pool is None:
- self._pool = logging_pool.pool(self._pool_size)
- self._front = _base_implementations.front_link(
- self._pool, self._pool, self._pool)
- self._rear_link = _rear.RearLink(
- self._host, self._port, self._pool,
- self._breakdown.request_serializers,
- self._breakdown.response_deserializers, self._secure,
- self._root_certificates, self._private_key, self._certificate_chain,
- metadata_transformer=self._metadata_transformer,
- server_host_override=self._server_host_override)
- self._front.join_rear_link(self._rear_link)
- self._rear_link.join_fore_link(self._front)
- self._rear_link.start()
- self._understub = _face_implementations.dynamic_stub(
- self._breakdown.face_cardinalities, self._front, self._pool, '')
- else:
- raise ValueError('Tried to __enter__ already-__enter__ed Stub!')
- return self
-
- def __exit__(self, exc_type, exc_val, exc_tb):
- with self._lock:
- if self._pool is None:
- raise ValueError('Tried to __exit__ non-__enter__ed Stub!')
- else:
- self._rear_link.stop()
- _base_utilities.wait_for_idle(self._front)
- self._pool.shutdown(wait=True)
- self._rear_link = None
- self._front = None
- self._pool = None
- self._understub = None
- return False
-
- def __getattr__(self, attr):
- with self._lock:
- if self._pool is None:
- raise ValueError('Tried to __getattr__ non-__enter__ed Stub!')
- else:
- method_cardinality = self._breakdown.cardinalities.get(attr)
- underlying_attr = getattr(
- self._understub, self._breakdown.qualified_names.get(attr), None)
- if method_cardinality is interfaces.Cardinality.UNARY_UNARY:
- return _reexport.unary_unary_sync_async(underlying_attr)
- elif method_cardinality is interfaces.Cardinality.UNARY_STREAM:
- return lambda request, timeout: _reexport.cancellable_iterator(
- underlying_attr(request, timeout))
- elif method_cardinality is interfaces.Cardinality.STREAM_UNARY:
- return _reexport.stream_unary_sync_async(underlying_attr)
- elif method_cardinality is interfaces.Cardinality.STREAM_STREAM:
- return lambda request_iterator, timeout: (
- _reexport.cancellable_iterator(underlying_attr(
- request_iterator, timeout)))
- else:
- raise AttributeError(attr)
-
-
-def stub(
- service_name, methods, host, port, metadata_transformer=None, secure=False,
- root_certificates=None, private_key=None, certificate_chain=None,
- server_host_override=None, thread_pool_size=_DEFAULT_THREAD_POOL_SIZE):
- """Constructs an interfaces.Stub.
-
- Args:
- service_name: The package-qualified full name of the service.
- methods: A dictionary from RPC method name to
- interfaces.RpcMethodInvocationDescription describing the RPCs to be
- supported by the created stub. The RPC method names in the dictionary are
- not qualified by the service name or decorated in any other way.
- host: The host to which to connect for RPC service.
- port: The port to which to connect for RPC service.
- metadata_transformer: A callable that given a metadata object produces
- another metadata object to be used in the underlying communication on the
- wire.
- secure: Whether or not to construct the stub with a secure connection.
- root_certificates: The PEM-encoded root certificates or None to ask for
- them to be retrieved from a default location.
- private_key: The PEM-encoded private key to use or None if no private key
- should be used.
- certificate_chain: The PEM-encoded certificate chain to use or None if no
- certificate chain should be used.
- server_host_override: (For testing only) the target name used for SSL
- host name checking.
- thread_pool_size: The maximum number of threads to allow in the backing
- thread pool.
-
- Returns:
- An interfaces.Stub affording RPC invocation.
- """
- breakdown = _face_utilities.break_down_invocation(service_name, methods)
- return _Stub(
- breakdown, host, port, secure, root_certificates, private_key,
- certificate_chain, server_host_override=server_host_override,
- metadata_transformer=metadata_transformer,
- thread_pool_size=thread_pool_size)
-
-
-def server(
- service_name, methods, port, private_key=None, certificate_chain=None,
- thread_pool_size=_DEFAULT_THREAD_POOL_SIZE):
- """Constructs an interfaces.Server.
-
- Args:
- service_name: The package-qualified full name of the service.
- methods: A dictionary from RPC method name to
- interfaces.RpcMethodServiceDescription describing the RPCs to
- be serviced by the created server. The RPC method names in the dictionary
- are not qualified by the service name or decorated in any other way.
- port: The port on which to serve or zero to ask for a port to be
- automatically selected.
- private_key: A pem-encoded private key, or None for an insecure server.
- certificate_chain: A pem-encoded certificate chain, or None for an insecure
- server.
- thread_pool_size: The maximum number of threads to allow in the backing
- thread pool.
-
- Returns:
- An interfaces.Server that will serve secure traffic.
- """
- breakdown = _face_utilities.break_down_service(service_name, methods)
- return _Server(breakdown, port, private_key, certificate_chain,
- thread_pool_size=thread_pool_size)
diff --git a/src/python/grpcio/grpc/framework/alpha/__init__.py b/src/python/grpcio/grpc/framework/alpha/__init__.py
deleted file mode 100644
index bff74be2c7..0000000000
--- a/src/python/grpcio/grpc/framework/alpha/__init__.py
+++ /dev/null
@@ -1,35 +0,0 @@
-# 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.
-
-import warnings
-
-warnings.simplefilter('always', DeprecationWarning)
-warnings.warn('the alpha API (includes this package) is deprecated, '
- 'unmaintained, and no longer tested. Please migrate to the beta '
- 'API.', DeprecationWarning, stacklevel=2)
diff --git a/src/python/grpcio/grpc/framework/alpha/_face_utilities.py b/src/python/grpcio/grpc/framework/alpha/_face_utilities.py
deleted file mode 100644
index 15c47d5c92..0000000000
--- a/src/python/grpcio/grpc/framework/alpha/_face_utilities.py
+++ /dev/null
@@ -1,183 +0,0 @@
-# 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.
-
-import abc
-import collections
-
-import six
-
-# face_interfaces is referenced from specification in this module.
-from grpc.framework.common import cardinality
-from grpc.framework.face import interfaces as face_interfaces # pylint: disable=unused-import
-from grpc.framework.face import utilities as face_utilities
-from grpc.framework.alpha import _reexport
-from grpc.framework.alpha import interfaces
-
-
-def _qualified_name(service_name, method_name):
- return '/%s/%s' % (service_name, method_name)
-
-
-# TODO(nathaniel): This structure is getting bloated; it could be shrunk if
-# implementations._Stub used a generic rather than a dynamic underlying
-# face-layer stub.
-class InvocationBreakdown(six.with_metaclass(abc.ABCMeta)):
- """An intermediate representation of invocation-side views of RPC methods.
-
- Attributes:
- cardinalities: A dictionary from RPC method name to interfaces.Cardinality
- value.
- qualified_names: A dictionary from unqualified RPC method name to
- service-qualified RPC method name.
- face_cardinalities: A dictionary from service-qualified RPC method name to
- to cardinality.Cardinality value.
- request_serializers: A dictionary from service-qualified RPC method name to
- callable behavior to be used serializing request values for the RPC.
- response_deserializers: A dictionary from service-qualified RPC method name
- to callable behavior to be used deserializing response values for the
- RPC.
- """
-
-
-class _EasyInvocationBreakdown(
- InvocationBreakdown,
- collections.namedtuple(
- '_EasyInvocationBreakdown',
- ('cardinalities', 'qualified_names', 'face_cardinalities',
- 'request_serializers', 'response_deserializers'))):
- pass
-
-
-class ServiceBreakdown(six.with_metaclass(abc.ABCMeta)):
- """An intermediate representation of service-side views of RPC methods.
-
- Attributes:
- implementations: A dictionary from service-qualified RPC method name to
- face_interfaces.MethodImplementation implementing the RPC method.
- request_deserializers: A dictionary from service-qualified RPC method name
- to callable behavior to be used deserializing request values for the RPC.
- response_serializers: A dictionary from service-qualified RPC method name
- to callable behavior to be used serializing response values for the RPC.
- """
-
-
-class _EasyServiceBreakdown(
- ServiceBreakdown,
- collections.namedtuple(
- '_EasyServiceBreakdown',
- ('implementations', 'request_deserializers', 'response_serializers'))):
- pass
-
-
-def break_down_invocation(service_name, method_descriptions):
- """Derives an InvocationBreakdown from several RPC method descriptions.
-
- Args:
- service_name: The package-qualified full name of the service.
- method_descriptions: A dictionary from RPC method name to
- interfaces.RpcMethodInvocationDescription describing the RPCs.
-
- Returns:
- An InvocationBreakdown corresponding to the given method descriptions.
- """
- cardinalities = {}
- qualified_names = {}
- face_cardinalities = {}
- request_serializers = {}
- response_deserializers = {}
- for name, method_description in six.iteritems(method_descriptions):
- qualified_name = _qualified_name(service_name, name)
- method_cardinality = method_description.cardinality()
- cardinalities[name] = method_description.cardinality()
- qualified_names[name] = qualified_name
- face_cardinalities[qualified_name] = _reexport.common_cardinality(
- method_cardinality)
- request_serializers[qualified_name] = method_description.serialize_request
- response_deserializers[qualified_name] = (
- method_description.deserialize_response)
- return _EasyInvocationBreakdown(
- cardinalities, qualified_names, face_cardinalities, request_serializers,
- response_deserializers)
-
-
-def break_down_service(service_name, method_descriptions):
- """Derives a ServiceBreakdown from several RPC method descriptions.
-
- Args:
- method_descriptions: A dictionary from RPC method name to
- interfaces.RpcMethodServiceDescription describing the RPCs.
-
- Returns:
- A ServiceBreakdown corresponding to the given method descriptions.
- """
- implementations = {}
- request_deserializers = {}
- response_serializers = {}
- for name, method_description in six.iteritems(method_descriptions):
- qualified_name = _qualified_name(service_name, name)
- method_cardinality = method_description.cardinality()
- if method_cardinality is interfaces.Cardinality.UNARY_UNARY:
- def service(
- request, face_rpc_context,
- service_behavior=method_description.service_unary_unary):
- return service_behavior(
- request, _reexport.rpc_context(face_rpc_context))
- implementations[qualified_name] = face_utilities.unary_unary_inline(
- service)
- elif method_cardinality is interfaces.Cardinality.UNARY_STREAM:
- def service(
- request, face_rpc_context,
- service_behavior=method_description.service_unary_stream):
- return service_behavior(
- request, _reexport.rpc_context(face_rpc_context))
- implementations[qualified_name] = face_utilities.unary_stream_inline(
- service)
- elif method_cardinality is interfaces.Cardinality.STREAM_UNARY:
- def service(
- request_iterator, face_rpc_context,
- service_behavior=method_description.service_stream_unary):
- return service_behavior(
- request_iterator, _reexport.rpc_context(face_rpc_context))
- implementations[qualified_name] = face_utilities.stream_unary_inline(
- service)
- elif method_cardinality is interfaces.Cardinality.STREAM_STREAM:
- def service(
- request_iterator, face_rpc_context,
- service_behavior=method_description.service_stream_stream):
- return service_behavior(
- request_iterator, _reexport.rpc_context(face_rpc_context))
- implementations[qualified_name] = face_utilities.stream_stream_inline(
- service)
- request_deserializers[qualified_name] = (
- method_description.deserialize_request)
- response_serializers[qualified_name] = (
- method_description.serialize_response)
-
- return _EasyServiceBreakdown(
- implementations, request_deserializers, response_serializers)
diff --git a/src/python/grpcio/grpc/framework/alpha/_reexport.py b/src/python/grpcio/grpc/framework/alpha/_reexport.py
deleted file mode 100644
index e027077a77..0000000000
--- a/src/python/grpcio/grpc/framework/alpha/_reexport.py
+++ /dev/null
@@ -1,205 +0,0 @@
-# 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.
-
-import six
-
-from grpc.framework.common import cardinality
-from grpc.framework.face import exceptions as face_exceptions
-from grpc.framework.face import interfaces as face_interfaces
-from grpc.framework.foundation import future
-from grpc.framework.alpha import exceptions
-from grpc.framework.alpha import interfaces
-
-_EARLY_ADOPTER_CARDINALITY_TO_COMMON_CARDINALITY = {
- interfaces.Cardinality.UNARY_UNARY: cardinality.Cardinality.UNARY_UNARY,
- interfaces.Cardinality.UNARY_STREAM: cardinality.Cardinality.UNARY_STREAM,
- interfaces.Cardinality.STREAM_UNARY: cardinality.Cardinality.STREAM_UNARY,
- interfaces.Cardinality.STREAM_STREAM: cardinality.Cardinality.STREAM_STREAM,
-}
-
-_ABORTION_REEXPORT = {
- face_interfaces.Abortion.CANCELLED: interfaces.Abortion.CANCELLED,
- face_interfaces.Abortion.EXPIRED: interfaces.Abortion.EXPIRED,
- face_interfaces.Abortion.NETWORK_FAILURE:
- interfaces.Abortion.NETWORK_FAILURE,
- face_interfaces.Abortion.SERVICED_FAILURE:
- interfaces.Abortion.SERVICED_FAILURE,
- face_interfaces.Abortion.SERVICER_FAILURE:
- interfaces.Abortion.SERVICER_FAILURE,
-}
-
-
-class _RpcError(exceptions.RpcError):
- pass
-
-
-def _reexport_error(face_rpc_error):
- if isinstance(face_rpc_error, face_exceptions.CancellationError):
- return exceptions.CancellationError()
- elif isinstance(face_rpc_error, face_exceptions.ExpirationError):
- return exceptions.ExpirationError()
- else:
- return _RpcError()
-
-
-def _as_face_abortion_callback(abortion_callback):
- def face_abortion_callback(face_abortion):
- abortion_callback(_ABORTION_REEXPORT[face_abortion])
- return face_abortion_callback
-
-
-class _ReexportedFuture(future.Future):
-
- def __init__(self, face_future):
- self._face_future = face_future
-
- def cancel(self):
- return self._face_future.cancel()
-
- def cancelled(self):
- return self._face_future.cancelled()
-
- def running(self):
- return self._face_future.running()
-
- def done(self):
- return self._face_future.done()
-
- def result(self, timeout=None):
- try:
- return self._face_future.result(timeout=timeout)
- except face_exceptions.RpcError as e:
- raise _reexport_error(e)
-
- def exception(self, timeout=None):
- face_error = self._face_future.exception(timeout=timeout)
- return None if face_error is None else _reexport_error(face_error)
-
- def traceback(self, timeout=None):
- return self._face_future.traceback(timeout=timeout)
-
- def add_done_callback(self, fn):
- self._face_future.add_done_callback(lambda unused_face_future: fn(self))
-
-
-def _call_reexporting_errors(behavior, *args, **kwargs):
- try:
- return behavior(*args, **kwargs)
- except face_exceptions.RpcError as e:
- raise _reexport_error(e)
-
-
-def _reexported_future(face_future):
- return _ReexportedFuture(face_future)
-
-
-class _CancellableIterator(interfaces.CancellableIterator):
-
- def __init__(self, face_cancellable_iterator):
- self._face_cancellable_iterator = face_cancellable_iterator
-
- def __iter__(self):
- return self
-
- def next(self):
- return _call_reexporting_errors(self._face_cancellable_iterator.next)
-
- def cancel(self):
- self._face_cancellable_iterator.cancel()
-
-
-class _RpcContext(interfaces.RpcContext):
-
- def __init__(self, face_rpc_context):
- self._face_rpc_context = face_rpc_context
-
- def is_active(self):
- return self._face_rpc_context.is_active()
-
- def time_remaining(self):
- return self._face_rpc_context.time_remaining()
-
- def add_abortion_callback(self, abortion_callback):
- self._face_rpc_context.add_abortion_callback(
- _as_face_abortion_callback(abortion_callback))
-
-
-class _UnaryUnarySyncAsync(interfaces.UnaryUnarySyncAsync):
-
- def __init__(self, face_unary_unary_multi_callable):
- self._underlying = face_unary_unary_multi_callable
-
- def __call__(self, request, timeout):
- return _call_reexporting_errors(
- self._underlying, request, timeout)
-
- def async(self, request, timeout):
- return _ReexportedFuture(self._underlying.future(request, timeout))
-
-
-class _StreamUnarySyncAsync(interfaces.StreamUnarySyncAsync):
-
- def __init__(self, face_stream_unary_multi_callable):
- self._underlying = face_stream_unary_multi_callable
-
- def __call__(self, request_iterator, timeout):
- return _call_reexporting_errors(
- self._underlying, request_iterator, timeout)
-
- def async(self, request_iterator, timeout):
- return _ReexportedFuture(self._underlying.future(request_iterator, timeout))
-
-
-def common_cardinality(early_adopter_cardinality):
- return _EARLY_ADOPTER_CARDINALITY_TO_COMMON_CARDINALITY[
- early_adopter_cardinality]
-
-
-def common_cardinalities(early_adopter_cardinalities):
- common_cardinalities = {}
- for name, early_adopter_cardinality in six.iteritems(early_adopter_cardinalities):
- common_cardinalities[name] = _EARLY_ADOPTER_CARDINALITY_TO_COMMON_CARDINALITY[
- early_adopter_cardinality]
- return common_cardinalities
-
-
-def rpc_context(face_rpc_context):
- return _RpcContext(face_rpc_context)
-
-
-def cancellable_iterator(face_cancellable_iterator):
- return _CancellableIterator(face_cancellable_iterator)
-
-
-def unary_unary_sync_async(face_unary_unary_multi_callable):
- return _UnaryUnarySyncAsync(face_unary_unary_multi_callable)
-
-
-def stream_unary_sync_async(face_stream_unary_multi_callable):
- return _StreamUnarySyncAsync(face_stream_unary_multi_callable)
diff --git a/src/python/grpcio/grpc/framework/alpha/interfaces.py b/src/python/grpcio/grpc/framework/alpha/interfaces.py
deleted file mode 100644
index 48f144f614..0000000000
--- a/src/python/grpcio/grpc/framework/alpha/interfaces.py
+++ /dev/null
@@ -1,384 +0,0 @@
-# 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 of GRPC."""
-
-import abc
-import enum
-
-import six
-
-# exceptions is referenced from specification in this module.
-from grpc.framework.alpha import exceptions # pylint: disable=unused-import
-from grpc.framework.foundation import activated
-from grpc.framework.foundation import future
-
-
-@enum.unique
-class Cardinality(enum.Enum):
- """Constants for the four cardinalities of RPC."""
-
- UNARY_UNARY = 'request-unary/response-unary'
- UNARY_STREAM = 'request-unary/response-streaming'
- STREAM_UNARY = 'request-streaming/response-unary'
- STREAM_STREAM = 'request-streaming/response-streaming'
-
-
-@enum.unique
-class Abortion(enum.Enum):
- """Categories of RPC abortion."""
-
- CANCELLED = 'cancelled'
- EXPIRED = 'expired'
- NETWORK_FAILURE = 'network failure'
- SERVICED_FAILURE = 'serviced failure'
- SERVICER_FAILURE = 'servicer failure'
-
-
-class CancellableIterator(six.with_metaclass(abc.ABCMeta)):
- """Implements the Iterator protocol and affords a cancel method."""
-
- @abc.abstractmethod
- def __iter__(self):
- """Returns the self object in accordance with the Iterator protocol."""
- raise NotImplementedError()
-
- def __next__(self):
- return self.next()
-
- @abc.abstractmethod
- def next(self):
- """Returns a value or raises StopIteration per the Iterator protocol."""
- raise NotImplementedError()
-
- @abc.abstractmethod
- def cancel(self):
- """Requests cancellation of whatever computation underlies this iterator."""
- raise NotImplementedError()
-
-
-class RpcContext(six.with_metaclass(abc.ABCMeta)):
- """Provides RPC-related information and action."""
-
- @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()
-
-
-class UnaryUnarySyncAsync(six.with_metaclass(abc.ABCMeta)):
- """Affords invoking a unary-unary RPC synchronously or asynchronously.
- Values implementing this interface are directly callable and present an
- "async" method. Both calls take a request value and a numeric timeout.
- Direct invocation of a value of this type invokes its associated RPC and
- blocks until the RPC's response is available. Calling the "async" method
- of a value of this type invokes its associated RPC and immediately returns a
- future.Future bound to the asynchronous execution of the RPC.
- """
-
- @abc.abstractmethod
- def __call__(self, request, timeout):
- """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.
- Returns:
- The response value for the RPC.
- Raises:
- exceptions.RpcError: Indicating that the RPC was aborted.
- """
- raise NotImplementedError()
-
- @abc.abstractmethod
- def async(self, request, timeout):
- """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.
- Returns:
- A future.Future representing the RPC. In the event of RPC completion, the
- returned 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 exceptions.RpcError.
- """
- raise NotImplementedError()
-
-
-class StreamUnarySyncAsync(six.with_metaclass(abc.ABCMeta)):
- """Affords invoking a stream-unary RPC synchronously or asynchronously.
- Values implementing this interface are directly callable and present an
- "async" method. Both calls take an iterator of request values and a numeric
- timeout. Direct invocation of a value of this type invokes its associated RPC
- and blocks until the RPC's response is available. Calling the "async" method
- of a value of this type invokes its associated RPC and immediately returns a
- future.Future bound to the asynchronous execution of the RPC.
- """
-
- @abc.abstractmethod
- def __call__(self, request_iterator, timeout):
- """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.
-
- Returns:
- The response value for the RPC.
-
- Raises:
- exceptions.RpcError: Indicating that the RPC was aborted.
- """
- raise NotImplementedError()
-
- @abc.abstractmethod
- def async(self, request_iterator, timeout):
- """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.
-
- Returns:
- A future.Future representing the RPC. In the event of RPC completion, the
- returned 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 exceptions.RpcError.
- """
- raise NotImplementedError()
-
-
-class RpcMethodDescription(six.with_metaclass(abc.ABCMeta)):
- """A type for the common aspects of RPC method descriptions."""
-
- @abc.abstractmethod
- def cardinality(self):
- """Identifies the cardinality of this RpcMethodDescription.
-
- Returns:
- A Cardinality value identifying whether or not this
- RpcMethodDescription is request-unary or request-streaming and
- whether or not it is response-unary or response-streaming.
- """
- raise NotImplementedError()
-
-
-class RpcMethodInvocationDescription(six.with_metaclass(abc.ABCMeta, RpcMethodDescription)):
- """Invocation-side description of an RPC method."""
-
- @abc.abstractmethod
- def serialize_request(self, request):
- """Serializes a request value.
-
- Args:
- request: A request value appropriate for the RPC method described by this
- RpcMethodInvocationDescription.
-
- Returns:
- The serialization of the given request value as a
- bytestring.
- """
- raise NotImplementedError()
-
- @abc.abstractmethod
- def deserialize_response(self, serialized_response):
- """Deserializes a response value.
-
- Args:
- serialized_response: A bytestring that is the serialization of a response
- value appropriate for the RPC method described by this
- RpcMethodInvocationDescription.
-
- Returns:
- A response value corresponding to the given bytestring.
- """
- raise NotImplementedError()
-
-
-class RpcMethodServiceDescription(six.with_metaclass(abc.ABCMeta, RpcMethodDescription)):
- """Service-side description of an RPC method."""
-
- @abc.abstractmethod
- def deserialize_request(self, serialized_request):
- """Deserializes a request value.
-
- Args:
- serialized_request: A bytestring that is the serialization of a request
- value appropriate for the RPC method described by this
- RpcMethodServiceDescription.
-
- Returns:
- A request value corresponding to the given bytestring.
- """
- raise NotImplementedError()
-
- @abc.abstractmethod
- def serialize_response(self, response):
- """Serializes a response value.
-
- Args:
- response: A response value appropriate for the RPC method described by
- this RpcMethodServiceDescription.
-
- Returns:
- The serialization of the given response value as a
- bytestring.
- """
- raise NotImplementedError()
-
- @abc.abstractmethod
- def service_unary_unary(self, request, context):
- """Carries out this RPC.
-
- This method may only be called if the cardinality of this
- RpcMethodServiceDescription is Cardinality.UNARY_UNARY.
-
- Args:
- request: A request value appropriate for the RPC method described by this
- RpcMethodServiceDescription.
- context: An RpcContext object for the RPC.
-
- Returns:
- A response value appropriate for the RPC method described by this
- RpcMethodServiceDescription.
- """
- raise NotImplementedError()
-
- @abc.abstractmethod
- def service_unary_stream(self, request, context):
- """Carries out this RPC.
-
- This method may only be called if the cardinality of this
- RpcMethodServiceDescription is Cardinality.UNARY_STREAM.
-
- Args:
- request: A request value appropriate for the RPC method described by this
- RpcMethodServiceDescription.
- context: An RpcContext object for the RPC.
-
- Yields:
- Zero or more response values appropriate for the RPC method described by
- this RpcMethodServiceDescription.
- """
- raise NotImplementedError()
-
- @abc.abstractmethod
- def service_stream_unary(self, request_iterator, context):
- """Carries out this RPC.
-
- This method may only be called if the cardinality of this
- RpcMethodServiceDescription is Cardinality.STREAM_UNARY.
-
- Args:
- request_iterator: An iterator of request values appropriate for the RPC
- method described by this RpcMethodServiceDescription.
- context: An RpcContext object for the RPC.
-
- Returns:
- A response value appropriate for the RPC method described by this
- RpcMethodServiceDescription.
- """
- raise NotImplementedError()
-
- @abc.abstractmethod
- def service_stream_stream(self, request_iterator, context):
- """Carries out this RPC.
-
- This method may only be called if the cardinality of this
- RpcMethodServiceDescription is Cardinality.STREAM_STREAM.
-
- Args:
- request_iterator: An iterator of request values appropriate for the RPC
- method described by this RpcMethodServiceDescription.
- context: An RpcContext object for the RPC.
-
- Yields:
- Zero or more response values appropriate for the RPC method described by
- this RpcMethodServiceDescription.
- """
- raise NotImplementedError()
-
-
-class Stub(six.with_metaclass(abc.ABCMeta)):
- """A stub with callable RPC method names for attributes.
-
- Instances of this type are context managers and only afford RPC invocation
- when used in context.
-
- Instances of this type, when used in context, respond to attribute access
- as follows: if the requested attribute is the name of a unary-unary RPC
- method, the value of the attribute will be a UnaryUnarySyncAsync with which
- to invoke the RPC method. If the requested attribute is the name of a
- unary-stream RPC method, the value of the attribute will be a callable taking
- a request object and a timeout parameter and returning a CancellableIterator
- that yields the response values of the RPC. If the requested attribute is the
- name of a stream-unary RPC method, the value of the attribute will be a
- StreamUnarySyncAsync with which to invoke the RPC method. If the requested
- attribute is the name of a stream-stream RPC method, the value of the
- attribute will be a callable taking an iterator of request objects and a
- timeout and returning a CancellableIterator that yields the response values
- of the RPC.
-
- In all cases indication of abortion is indicated by raising of
- exceptions.RpcError, exceptions.CancellationError,
- and exceptions.ExpirationError.
- """
-
-
-class Server(six.with_metaclass(abc.ABCMeta, activated.Activated)):
- """A GRPC Server."""
-
- @abc.abstractmethod
- def port(self):
- """Reports the port on which the server is serving.
-
- This method may only be called while the server is activated.
-
- Returns:
- The port on which the server is serving.
- """
- raise NotImplementedError()
diff --git a/src/python/grpcio/grpc/framework/alpha/utilities.py b/src/python/grpcio/grpc/framework/alpha/utilities.py
deleted file mode 100644
index 7d7f78f5e4..0000000000
--- a/src/python/grpcio/grpc/framework/alpha/utilities.py
+++ /dev/null
@@ -1,269 +0,0 @@
-# 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 use with GRPC."""
-
-from grpc.framework.alpha import interfaces
-
-
-class _RpcMethodDescription(
- interfaces.RpcMethodInvocationDescription,
- interfaces.RpcMethodServiceDescription):
-
- def __init__(
- self, cardinality, unary_unary, unary_stream, stream_unary,
- stream_stream, request_serializer, request_deserializer,
- response_serializer, response_deserializer):
- self._cardinality = cardinality
- self._unary_unary = unary_unary
- self._unary_stream = unary_stream
- self._stream_unary = stream_unary
- self._stream_stream = stream_stream
- self._request_serializer = request_serializer
- self._request_deserializer = request_deserializer
- self._response_serializer = response_serializer
- self._response_deserializer = response_deserializer
-
- def cardinality(self):
- """See interfaces.RpcMethodDescription.cardinality for specification."""
- return self._cardinality
-
- def serialize_request(self, request):
- """See interfaces.RpcMethodInvocationDescription.serialize_request."""
- return self._request_serializer(request)
-
- def deserialize_request(self, serialized_request):
- """See interfaces.RpcMethodServiceDescription.deserialize_request."""
- return self._request_deserializer(serialized_request)
-
- def serialize_response(self, response):
- """See interfaces.RpcMethodServiceDescription.serialize_response."""
- return self._response_serializer(response)
-
- def deserialize_response(self, serialized_response):
- """See interfaces.RpcMethodInvocationDescription.deserialize_response."""
- return self._response_deserializer(serialized_response)
-
- def service_unary_unary(self, request, context):
- """See interfaces.RpcMethodServiceDescription.service_unary_unary."""
- return self._unary_unary(request, context)
-
- def service_unary_stream(self, request, context):
- """See interfaces.RpcMethodServiceDescription.service_unary_stream."""
- return self._unary_stream(request, context)
-
- def service_stream_unary(self, request_iterator, context):
- """See interfaces.RpcMethodServiceDescription.service_stream_unary."""
- return self._stream_unary(request_iterator, context)
-
- def service_stream_stream(self, request_iterator, context):
- """See interfaces.RpcMethodServiceDescription.service_stream_stream."""
- return self._stream_stream(request_iterator, context)
-
-
-def unary_unary_invocation_description(
- request_serializer, response_deserializer):
- """Creates an interfaces.RpcMethodInvocationDescription for an RPC method.
-
- Args:
- request_serializer: A callable that when called on a request
- value returns a bytestring corresponding to that value.
- response_deserializer: A callable that when called on a
- bytestring returns the response value corresponding to
- that bytestring.
-
- Returns:
- An interfaces.RpcMethodInvocationDescription constructed from the given
- arguments representing a unary-request/unary-response RPC method.
- """
- return _RpcMethodDescription(
- interfaces.Cardinality.UNARY_UNARY, None, None, None, None,
- request_serializer, None, None, response_deserializer)
-
-
-def unary_stream_invocation_description(
- request_serializer, response_deserializer):
- """Creates an interfaces.RpcMethodInvocationDescription for an RPC method.
-
- Args:
- request_serializer: A callable that when called on a request
- value returns a bytestring corresponding to that value.
- response_deserializer: A callable that when called on a
- bytestring returns the response value corresponding to
- that bytestring.
-
- Returns:
- An interfaces.RpcMethodInvocationDescription constructed from the given
- arguments representing a unary-request/streaming-response RPC method.
- """
- return _RpcMethodDescription(
- interfaces.Cardinality.UNARY_STREAM, None, None, None, None,
- request_serializer, None, None, response_deserializer)
-
-
-def stream_unary_invocation_description(
- request_serializer, response_deserializer):
- """Creates an interfaces.RpcMethodInvocationDescription for an RPC method.
-
- Args:
- request_serializer: A callable that when called on a request
- value returns a bytestring corresponding to that value.
- response_deserializer: A callable that when called on a
- bytestring returns the response value corresponding to
- that bytestring.
-
- Returns:
- An interfaces.RpcMethodInvocationDescription constructed from the given
- arguments representing a streaming-request/unary-response RPC method.
- """
- return _RpcMethodDescription(
- interfaces.Cardinality.STREAM_UNARY, None, None, None, None,
- request_serializer, None, None, response_deserializer)
-
-
-def stream_stream_invocation_description(
- request_serializer, response_deserializer):
- """Creates an interfaces.RpcMethodInvocationDescription for an RPC method.
-
- Args:
- request_serializer: A callable that when called on a request
- value returns a bytestring corresponding to that value.
- response_deserializer: A callable that when called on a
- bytestring returns the response value corresponding to
- that bytestring.
-
- Returns:
- An interfaces.RpcMethodInvocationDescription constructed from the given
- arguments representing a streaming-request/streaming-response RPC
- method.
- """
- return _RpcMethodDescription(
- interfaces.Cardinality.STREAM_STREAM, None, None, None, None,
- request_serializer, None, None, response_deserializer)
-
-
-def unary_unary_service_description(
- behavior, request_deserializer, response_serializer):
- """Creates an interfaces.RpcMethodServiceDescription for the given behavior.
-
- Args:
- behavior: A callable that implements a unary-unary RPC
- method that accepts a single request and an interfaces.RpcContext and
- returns a single response.
- request_deserializer: A callable that when called on a
- bytestring returns the request value corresponding to that
- bytestring.
- response_serializer: A callable that when called on a
- response value returns the bytestring corresponding to
- that value.
-
- Returns:
- An interfaces.RpcMethodServiceDescription constructed from the given
- arguments representing a unary-request/unary-response RPC
- method.
- """
- return _RpcMethodDescription(
- interfaces.Cardinality.UNARY_UNARY, behavior, None, None, None,
- None, request_deserializer, response_serializer, None)
-
-
-def unary_stream_service_description(
- behavior, request_deserializer, response_serializer):
- """Creates an interfaces.RpcMethodServiceDescription for the given behavior.
-
- Args:
- behavior: A callable that implements a unary-stream RPC
- method that accepts a single request and an interfaces.RpcContext
- and returns an iterator of zero or more responses.
- request_deserializer: A callable that when called on a
- bytestring returns the request value corresponding to that
- bytestring.
- response_serializer: A callable that when called on a
- response value returns the bytestring corresponding to
- that value.
-
- Returns:
- An interfaces.RpcMethodServiceDescription constructed from the given
- arguments representing a unary-request/streaming-response
- RPC method.
- """
- return _RpcMethodDescription(
- interfaces.Cardinality.UNARY_STREAM, None, behavior, None, None,
- None, request_deserializer, response_serializer, None)
-
-
-def stream_unary_service_description(
- behavior, request_deserializer, response_serializer):
- """Creates an interfaces.RpcMethodServiceDescription for the given behavior.
-
- Args:
- behavior: A callable that implements a stream-unary RPC
- method that accepts an iterator of zero or more requests
- and an interfaces.RpcContext and returns a single response.
- request_deserializer: A callable that when called on a
- bytestring returns the request value corresponding to that
- bytestring.
- response_serializer: A callable that when called on a
- response value returns the bytestring corresponding to
- that value.
-
- Returns:
- An interfaces.RpcMethodServiceDescription constructed from the given
- arguments representing a streaming-request/unary-response
- RPC method.
- """
- return _RpcMethodDescription(
- interfaces.Cardinality.STREAM_UNARY, None, None, behavior, None,
- None, request_deserializer, response_serializer, None)
-
-
-def stream_stream_service_description(
- behavior, request_deserializer, response_serializer):
- """Creates an interfaces.RpcMethodServiceDescription for the given behavior.
-
- Args:
- behavior: A callable that implements a stream-stream RPC
- method that accepts an iterator of zero or more requests
- and an interfaces.RpcContext and returns an iterator of
- zero or more responses.
- request_deserializer: A callable that when called on a
- bytestring returns the request value corresponding to that
- bytestring.
- response_serializer: A callable that when called on a
- response value returns the bytestring corresponding to
- that value.
-
- Returns:
- An interfaces.RpcMethodServiceDescription constructed from the given
- arguments representing a
- streaming-request/streaming-response RPC method.
- """
- return _RpcMethodDescription(
- interfaces.Cardinality.STREAM_STREAM, None, None, None, behavior,
- None, request_deserializer, response_serializer, None)
diff --git a/src/python/grpcio/grpc/framework/base/__init__.py b/src/python/grpcio/grpc/framework/base/__init__.py
deleted file mode 100644
index bff74be2c7..0000000000
--- a/src/python/grpcio/grpc/framework/base/__init__.py
+++ /dev/null
@@ -1,35 +0,0 @@
-# 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.
-
-import warnings
-
-warnings.simplefilter('always', DeprecationWarning)
-warnings.warn('the alpha API (includes this package) is deprecated, '
- 'unmaintained, and no longer tested. Please migrate to the beta '
- 'API.', DeprecationWarning, stacklevel=2)
diff --git a/src/python/grpcio/grpc/framework/base/_constants.py b/src/python/grpcio/grpc/framework/base/_constants.py
deleted file mode 100644
index 8fbdc82782..0000000000
--- a/src/python/grpcio/grpc/framework/base/_constants.py
+++ /dev/null
@@ -1,32 +0,0 @@
-# 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.
-
-"""Private constants for the package."""
-
-INTERNAL_ERROR_LOG_MESSAGE = ':-( RPC Framework (Base) internal error! :-('
diff --git a/src/python/grpcio/grpc/framework/base/_context.py b/src/python/grpcio/grpc/framework/base/_context.py
deleted file mode 100644
index d84871d639..0000000000
--- a/src/python/grpcio/grpc/framework/base/_context.py
+++ /dev/null
@@ -1,99 +0,0 @@
-# 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.
-
-"""State and behavior for operation context."""
-
-import time
-
-# _interfaces is referenced from specification in this module.
-from grpc.framework.base import interfaces
-from grpc.framework.base import _interfaces # pylint: disable=unused-import
-
-
-class OperationContext(interfaces.OperationContext):
- """An implementation of interfaces.OperationContext."""
-
- def __init__(
- self, lock, operation_id, local_failure, termination_manager,
- transmission_manager):
- """Constructor.
-
- Args:
- lock: The operation-wide lock.
- operation_id: An object identifying the operation.
- local_failure: Whichever one of interfaces.Outcome.SERVICED_FAILURE or
- interfaces.Outcome.SERVICER_FAILURE describes local failure of
- customer code.
- termination_manager: The _interfaces.TerminationManager for the operation.
- transmission_manager: The _interfaces.TransmissionManager for the
- operation.
- """
- self._lock = lock
- self._local_failure = local_failure
- self._termination_manager = termination_manager
- self._transmission_manager = transmission_manager
- self._ingestion_manager = None
- self._expiration_manager = None
-
- self.operation_id = operation_id
-
- def set_ingestion_and_expiration_managers(
- self, ingestion_manager, expiration_manager):
- """Sets managers with which this OperationContext cooperates.
-
- Args:
- ingestion_manager: The _interfaces.IngestionManager for the operation.
- expiration_manager: The _interfaces.ExpirationManager for the operation.
- """
- self._ingestion_manager = ingestion_manager
- self._expiration_manager = expiration_manager
-
- def is_active(self):
- """See interfaces.OperationContext.is_active for specification."""
- with self._lock:
- return self._termination_manager.is_active()
-
- def add_termination_callback(self, callback):
- """See interfaces.OperationContext.add_termination_callback."""
- with self._lock:
- self._termination_manager.add_callback(callback)
-
- def time_remaining(self):
- """See interfaces.OperationContext.time_remaining for specification."""
- with self._lock:
- deadline = self._expiration_manager.deadline()
- return max(0.0, deadline - time.time())
-
- def fail(self, exception):
- """See interfaces.OperationContext.fail for specification."""
- with self._lock:
- self._termination_manager.abort(self._local_failure)
- self._transmission_manager.abort(self._local_failure)
- self._ingestion_manager.abort()
- self._expiration_manager.abort()
diff --git a/src/python/grpcio/grpc/framework/base/_emission.py b/src/python/grpcio/grpc/framework/base/_emission.py
deleted file mode 100644
index 1829669a72..0000000000
--- a/src/python/grpcio/grpc/framework/base/_emission.py
+++ /dev/null
@@ -1,125 +0,0 @@
-# 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.
-
-"""State and behavior for handling emitted values."""
-
-from grpc.framework.base import interfaces
-from grpc.framework.base import _interfaces
-
-
-class _EmissionManager(_interfaces.EmissionManager):
- """An implementation of _interfaces.EmissionManager."""
-
- def __init__(
- self, lock, failure_outcome, termination_manager, transmission_manager):
- """Constructor.
-
- Args:
- lock: The operation-wide lock.
- failure_outcome: Whichever one of interfaces.Outcome.SERVICED_FAILURE or
- interfaces.Outcome.SERVICER_FAILURE describes this object's methods
- being called inappropriately by customer code.
- termination_manager: The _interfaces.TerminationManager for the operation.
- transmission_manager: The _interfaces.TransmissionManager for the
- operation.
- """
- self._lock = lock
- self._failure_outcome = failure_outcome
- self._termination_manager = termination_manager
- self._transmission_manager = transmission_manager
- self._ingestion_manager = None
- self._expiration_manager = None
-
- self._emission_complete = False
-
- def set_ingestion_manager_and_expiration_manager(
- self, ingestion_manager, expiration_manager):
- self._ingestion_manager = ingestion_manager
- self._expiration_manager = expiration_manager
-
- def _abort(self):
- self._termination_manager.abort(self._failure_outcome)
- self._transmission_manager.abort(self._failure_outcome)
- self._ingestion_manager.abort()
- self._expiration_manager.abort()
-
- def consume(self, value):
- with self._lock:
- if self._emission_complete:
- self._abort()
- else:
- self._transmission_manager.inmit(value, False)
-
- def terminate(self):
- with self._lock:
- if not self._emission_complete:
- self._termination_manager.emission_complete()
- self._transmission_manager.inmit(None, True)
- self._emission_complete = True
-
- def consume_and_terminate(self, value):
- with self._lock:
- if self._emission_complete:
- self._abort()
- else:
- self._termination_manager.emission_complete()
- self._transmission_manager.inmit(value, True)
- self._emission_complete = True
-
-
-def front_emission_manager(lock, termination_manager, transmission_manager):
- """Creates an _interfaces.EmissionManager appropriate for front-side use.
-
- Args:
- lock: The operation-wide lock.
- termination_manager: The _interfaces.TerminationManager for the operation.
- transmission_manager: The _interfaces.TransmissionManager for the operation.
-
- Returns:
- An _interfaces.EmissionManager appropriate for front-side use.
- """
- return _EmissionManager(
- lock, interfaces.Outcome.SERVICED_FAILURE, termination_manager,
- transmission_manager)
-
-
-def back_emission_manager(lock, termination_manager, transmission_manager):
- """Creates an _interfaces.EmissionManager appropriate for back-side use.
-
- Args:
- lock: The operation-wide lock.
- termination_manager: The _interfaces.TerminationManager for the operation.
- transmission_manager: The _interfaces.TransmissionManager for the operation.
-
- Returns:
- An _interfaces.EmissionManager appropriate for back-side use.
- """
- return _EmissionManager(
- lock, interfaces.Outcome.SERVICER_FAILURE, termination_manager,
- transmission_manager)
diff --git a/src/python/grpcio/grpc/framework/base/_ends.py b/src/python/grpcio/grpc/framework/base/_ends.py
deleted file mode 100644
index 176f3ac06e..0000000000
--- a/src/python/grpcio/grpc/framework/base/_ends.py
+++ /dev/null
@@ -1,399 +0,0 @@
-# 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.
-
-"""Implementations of FrontLinks and BackLinks."""
-
-import collections
-import threading
-import uuid
-
-# _interfaces is referenced from specification in this module.
-from grpc.framework.base import _cancellation
-from grpc.framework.base import _context
-from grpc.framework.base import _emission
-from grpc.framework.base import _expiration
-from grpc.framework.base import _ingestion
-from grpc.framework.base import _interfaces # pylint: disable=unused-import
-from grpc.framework.base import _reception
-from grpc.framework.base import _termination
-from grpc.framework.base import _transmission
-from grpc.framework.base import interfaces
-from grpc.framework.foundation import callable_util
-
-_IDLE_ACTION_EXCEPTION_LOG_MESSAGE = 'Exception calling idle action!'
-
-
-class _EasyOperation(interfaces.Operation):
- """A trivial implementation of interfaces.Operation."""
-
- def __init__(self, emission_manager, context, cancellation_manager):
- """Constructor.
-
- Args:
- emission_manager: The _interfaces.EmissionManager for the operation that
- will accept values emitted by customer code.
- context: The interfaces.OperationContext for use by the customer
- during the operation.
- cancellation_manager: The _interfaces.CancellationManager for the
- operation.
- """
- self.consumer = emission_manager
- self.context = context
- self._cancellation_manager = cancellation_manager
-
- def cancel(self):
- self._cancellation_manager.cancel()
-
-
-class _Endlette(object):
- """Utility for stateful behavior common to Fronts and Backs."""
-
- def __init__(self, pool):
- """Constructor.
-
- Args:
- pool: A thread pool to use when calling registered idle actions.
- """
- self._lock = threading.Lock()
- self._pool = pool
- # Dictionary from operation IDs to ReceptionManager-or-None. A None value
- # indicates an in-progress fire-and-forget operation for which the customer
- # has chosen to ignore results.
- self._operations = {}
- self._stats = {outcome: 0 for outcome in interfaces.Outcome}
- self._idle_actions = []
-
- def terminal_action(self, operation_id):
- """Constructs the termination action for a single operation.
-
- Args:
- operation_id: An operation ID.
-
- Returns:
- A callable that takes an operation outcome for an argument to be used as
- the termination action for the operation associated with the given
- operation ID.
- """
- def termination_action(outcome):
- with self._lock:
- self._stats[outcome] += 1
- self._operations.pop(operation_id, None)
- if not self._operations:
- for action in self._idle_actions:
- self._pool.submit(callable_util.with_exceptions_logged(
- action, _IDLE_ACTION_EXCEPTION_LOG_MESSAGE))
- self._idle_actions = []
- return termination_action
-
- def __enter__(self):
- self._lock.acquire()
-
- def __exit__(self, exc_type, exc_val, exc_tb):
- self._lock.release()
-
- def get_operation(self, operation_id):
- return self._operations.get(operation_id, None)
-
- def add_operation(self, operation_id, operation_reception_manager):
- self._operations[operation_id] = operation_reception_manager
-
- def operation_stats(self):
- with self._lock:
- return dict(self._stats)
-
- def add_idle_action(self, action):
- with self._lock:
- if self._operations:
- self._idle_actions.append(action)
- else:
- self._pool.submit(callable_util.with_exceptions_logged(
- action, _IDLE_ACTION_EXCEPTION_LOG_MESSAGE))
-
-
-class _FrontManagement(
- collections.namedtuple(
- '_FrontManagement',
- ('reception', 'emission', 'operation', 'cancellation'))):
- """Just a trivial helper class to bundle four fellow-traveling objects."""
-
-
-def _front_operate(
- callback, work_pool, transmission_pool, utility_pool,
- termination_action, operation_id, name, payload, complete, timeout,
- subscription, trace_id):
- """Constructs objects necessary for front-side operation management.
-
- Args:
- callback: A callable that accepts interfaces.FrontToBackTickets and
- delivers them to the other side of the operation. Execution of this
- callable may take any arbitrary length of time.
- work_pool: A thread pool in which to execute customer code.
- transmission_pool: A thread pool to use for transmitting to the other side
- of the operation.
- utility_pool: A thread pool for utility tasks.
- termination_action: A no-arg behavior to be called upon operation
- completion.
- operation_id: An object identifying the operation.
- name: The name of the method being called during the operation.
- payload: The first customer-significant value to be transmitted to the other
- side. May be None if there is no such value or if the customer chose not
- to pass it at operation invocation.
- complete: A boolean indicating whether or not additional payloads will be
- supplied by the customer.
- timeout: A length of time in seconds to allow for the operation.
- subscription: A interfaces.ServicedSubscription describing the
- customer's interest in the results of the operation.
- trace_id: A uuid.UUID identifying a set of related operations to which this
- operation belongs. May be None.
-
- Returns:
- A _FrontManagement object bundling together the
- _interfaces.ReceptionManager, _interfaces.EmissionManager,
- _context.OperationContext, and _interfaces.CancellationManager for the
- operation.
- """
- lock = threading.Lock()
- with lock:
- termination_manager = _termination.front_termination_manager(
- work_pool, utility_pool, termination_action, subscription.kind)
- transmission_manager = _transmission.front_transmission_manager(
- lock, transmission_pool, callback, operation_id, name,
- subscription.kind, trace_id, timeout, termination_manager)
- operation_context = _context.OperationContext(
- lock, operation_id, interfaces.Outcome.SERVICED_FAILURE,
- termination_manager, transmission_manager)
- emission_manager = _emission.front_emission_manager(
- lock, termination_manager, transmission_manager)
- ingestion_manager = _ingestion.front_ingestion_manager(
- lock, work_pool, subscription, termination_manager,
- transmission_manager, operation_context)
- expiration_manager = _expiration.front_expiration_manager(
- lock, termination_manager, transmission_manager, ingestion_manager,
- timeout)
- reception_manager = _reception.front_reception_manager(
- lock, termination_manager, transmission_manager, ingestion_manager,
- expiration_manager)
- cancellation_manager = _cancellation.CancellationManager(
- lock, termination_manager, transmission_manager, ingestion_manager,
- expiration_manager)
-
- termination_manager.set_expiration_manager(expiration_manager)
- transmission_manager.set_ingestion_and_expiration_managers(
- ingestion_manager, expiration_manager)
- operation_context.set_ingestion_and_expiration_managers(
- ingestion_manager, expiration_manager)
- emission_manager.set_ingestion_manager_and_expiration_manager(
- ingestion_manager, expiration_manager)
- ingestion_manager.set_expiration_manager(expiration_manager)
-
- transmission_manager.inmit(payload, complete)
-
- if subscription.kind is interfaces.ServicedSubscription.Kind.NONE:
- returned_reception_manager = None
- else:
- returned_reception_manager = reception_manager
-
- return _FrontManagement(
- returned_reception_manager, emission_manager, operation_context,
- cancellation_manager)
-
-
-class FrontLink(interfaces.FrontLink):
- """An implementation of interfaces.FrontLink."""
-
- def __init__(self, work_pool, transmission_pool, utility_pool):
- """Constructor.
-
- Args:
- work_pool: A thread pool to be used for executing customer code.
- transmission_pool: A thread pool to be used for transmitting values to
- the other side of the operation.
- utility_pool: A thread pool to be used for utility tasks.
- """
- self._endlette = _Endlette(utility_pool)
- self._work_pool = work_pool
- self._transmission_pool = transmission_pool
- self._utility_pool = utility_pool
- self._callback = None
-
- self._operations = {}
-
- def join_rear_link(self, rear_link):
- """See interfaces.ForeLink.join_rear_link for specification."""
- with self._endlette:
- self._callback = rear_link.accept_front_to_back_ticket
-
- def operation_stats(self):
- """See interfaces.End.operation_stats for specification."""
- return self._endlette.operation_stats()
-
- def add_idle_action(self, action):
- """See interfaces.End.add_idle_action for specification."""
- self._endlette.add_idle_action(action)
-
- def operate(
- self, name, payload, complete, timeout, subscription, trace_id):
- """See interfaces.Front.operate for specification."""
- operation_id = uuid.uuid4()
- with self._endlette:
- management = _front_operate(
- self._callback, self._work_pool, self._transmission_pool,
- self._utility_pool, self._endlette.terminal_action(operation_id),
- operation_id, name, payload, complete, timeout, subscription,
- trace_id)
- self._endlette.add_operation(operation_id, management.reception)
- return _EasyOperation(
- management.emission, management.operation, management.cancellation)
-
- def accept_back_to_front_ticket(self, ticket):
- """See interfaces.End.act for specification."""
- with self._endlette:
- reception_manager = self._endlette.get_operation(ticket.operation_id)
- if reception_manager:
- reception_manager.receive_ticket(ticket)
-
-
-def _back_operate(
- servicer, callback, work_pool, transmission_pool, utility_pool,
- termination_action, ticket, default_timeout, maximum_timeout):
- """Constructs objects necessary for back-side operation management.
-
- Also begins back-side operation by feeding the first received ticket into the
- constructed _interfaces.ReceptionManager.
-
- Args:
- servicer: An interfaces.Servicer for servicing operations.
- callback: A callable that accepts interfaces.BackToFrontTickets and
- delivers them to the other side of the operation. Execution of this
- callable may take any arbitrary length of time.
- work_pool: A thread pool in which to execute customer code.
- transmission_pool: A thread pool to use for transmitting to the other side
- of the operation.
- utility_pool: A thread pool for utility tasks.
- termination_action: A no-arg behavior to be called upon operation
- completion.
- ticket: The first interfaces.FrontToBackTicket received for the operation.
- default_timeout: A length of time in seconds to be used as the default
- time alloted for a single operation.
- maximum_timeout: A length of time in seconds to be used as the maximum
- time alloted for a single operation.
-
- Returns:
- The _interfaces.ReceptionManager to be used for the operation.
- """
- lock = threading.Lock()
- with lock:
- termination_manager = _termination.back_termination_manager(
- work_pool, utility_pool, termination_action, ticket.subscription)
- transmission_manager = _transmission.back_transmission_manager(
- lock, transmission_pool, callback, ticket.operation_id,
- termination_manager, ticket.subscription)
- operation_context = _context.OperationContext(
- lock, ticket.operation_id, interfaces.Outcome.SERVICER_FAILURE,
- termination_manager, transmission_manager)
- emission_manager = _emission.back_emission_manager(
- lock, termination_manager, transmission_manager)
- ingestion_manager = _ingestion.back_ingestion_manager(
- lock, work_pool, servicer, termination_manager,
- transmission_manager, operation_context, emission_manager)
- expiration_manager = _expiration.back_expiration_manager(
- lock, termination_manager, transmission_manager, ingestion_manager,
- ticket.timeout, default_timeout, maximum_timeout)
- reception_manager = _reception.back_reception_manager(
- lock, termination_manager, transmission_manager, ingestion_manager,
- expiration_manager)
-
- termination_manager.set_expiration_manager(expiration_manager)
- transmission_manager.set_ingestion_and_expiration_managers(
- ingestion_manager, expiration_manager)
- operation_context.set_ingestion_and_expiration_managers(
- ingestion_manager, expiration_manager)
- emission_manager.set_ingestion_manager_and_expiration_manager(
- ingestion_manager, expiration_manager)
- ingestion_manager.set_expiration_manager(expiration_manager)
-
- reception_manager.receive_ticket(ticket)
-
- return reception_manager
-
-
-class BackLink(interfaces.BackLink):
- """An implementation of interfaces.BackLink."""
-
- def __init__(
- self, servicer, work_pool, transmission_pool, utility_pool,
- default_timeout, maximum_timeout):
- """Constructor.
-
- Args:
- servicer: An interfaces.Servicer for servicing operations.
- work_pool: A thread pool in which to execute customer code.
- transmission_pool: A thread pool to use for transmitting to the other side
- of the operation.
- utility_pool: A thread pool for utility tasks.
- default_timeout: A length of time in seconds to be used as the default
- time alloted for a single operation.
- maximum_timeout: A length of time in seconds to be used as the maximum
- time alloted for a single operation.
- """
- self._endlette = _Endlette(utility_pool)
- self._servicer = servicer
- self._work_pool = work_pool
- self._transmission_pool = transmission_pool
- self._utility_pool = utility_pool
- self._default_timeout = default_timeout
- self._maximum_timeout = maximum_timeout
- self._callback = None
-
- def join_fore_link(self, fore_link):
- """See interfaces.RearLink.join_fore_link for specification."""
- with self._endlette:
- self._callback = fore_link.accept_back_to_front_ticket
-
- def accept_front_to_back_ticket(self, ticket):
- """See interfaces.RearLink.accept_front_to_back_ticket for specification."""
- with self._endlette:
- reception_manager = self._endlette.get_operation(ticket.operation_id)
- if reception_manager is None:
- reception_manager = _back_operate(
- self._servicer, self._callback, self._work_pool,
- self._transmission_pool, self._utility_pool,
- self._endlette.terminal_action(ticket.operation_id), ticket,
- self._default_timeout, self._maximum_timeout)
- self._endlette.add_operation(ticket.operation_id, reception_manager)
- else:
- reception_manager.receive_ticket(ticket)
-
- def operation_stats(self):
- """See interfaces.End.operation_stats for specification."""
- return self._endlette.operation_stats()
-
- def add_idle_action(self, action):
- """See interfaces.End.add_idle_action for specification."""
- self._endlette.add_idle_action(action)
diff --git a/src/python/grpcio/grpc/framework/base/_expiration.py b/src/python/grpcio/grpc/framework/base/_expiration.py
deleted file mode 100644
index 17acbef4c1..0000000000
--- a/src/python/grpcio/grpc/framework/base/_expiration.py
+++ /dev/null
@@ -1,158 +0,0 @@
-# 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.
-
-"""State and behavior for operation expiration."""
-
-import time
-
-from grpc.framework.base import _interfaces
-from grpc.framework.base import interfaces
-from grpc.framework.foundation import later
-
-
-class _ExpirationManager(_interfaces.ExpirationManager):
- """An implementation of _interfaces.ExpirationManager."""
-
- def __init__(
- self, lock, termination_manager, transmission_manager, ingestion_manager,
- commencement, timeout, maximum_timeout):
- """Constructor.
-
- Args:
- lock: The operation-wide lock.
- termination_manager: The _interfaces.TerminationManager for the operation.
- transmission_manager: The _interfaces.TransmissionManager for the
- operation.
- ingestion_manager: The _interfaces.IngestionManager for the operation.
- commencement: The time in seconds since the epoch at which the operation
- began.
- timeout: A length of time in seconds to allow for the operation to run.
- maximum_timeout: The maximum length of time in seconds to allow for the
- operation to run despite what is requested via this object's
- change_timout method.
- """
- self._lock = lock
- self._termination_manager = termination_manager
- self._transmission_manager = transmission_manager
- self._ingestion_manager = ingestion_manager
- self._commencement = commencement
- self._maximum_timeout = maximum_timeout
-
- self._timeout = timeout
- self._deadline = commencement + timeout
- self._index = None
- self._future = None
-
- def _expire(self, index):
- with self._lock:
- if self._future is not None and index == self._index:
- self._future = None
- self._termination_manager.abort(interfaces.Outcome.EXPIRED)
- self._transmission_manager.abort(interfaces.Outcome.EXPIRED)
- self._ingestion_manager.abort()
-
- def start(self):
- self._index = 0
- self._future = later.later(self._timeout, lambda: self._expire(0))
-
- def change_timeout(self, timeout):
- if self._future is not None and timeout != self._timeout:
- self._future.cancel()
- new_timeout = min(timeout, self._maximum_timeout)
- new_index = self._index + 1
- self._timeout = new_timeout
- self._deadline = self._commencement + new_timeout
- self._index = new_index
- delay = self._deadline - time.time()
- self._future = later.later(
- delay, lambda: self._expire(new_index))
-
- def deadline(self):
- return self._deadline
-
- def abort(self):
- if self._future:
- self._future.cancel()
- self._future = None
- self._deadline_index = None
-
-
-def front_expiration_manager(
- lock, termination_manager, transmission_manager, ingestion_manager,
- timeout):
- """Creates an _interfaces.ExpirationManager appropriate for front-side use.
-
- Args:
- lock: The operation-wide lock.
- termination_manager: The _interfaces.TerminationManager for the operation.
- transmission_manager: The _interfaces.TransmissionManager for the
- operation.
- ingestion_manager: The _interfaces.IngestionManager for the operation.
- timeout: A length of time in seconds to allow for the operation to run.
-
- Returns:
- An _interfaces.ExpirationManager appropriate for front-side use.
- """
- commencement = time.time()
- expiration_manager = _ExpirationManager(
- lock, termination_manager, transmission_manager, ingestion_manager,
- commencement, timeout, timeout)
- expiration_manager.start()
- return expiration_manager
-
-
-def back_expiration_manager(
- lock, termination_manager, transmission_manager, ingestion_manager,
- timeout, default_timeout, maximum_timeout):
- """Creates an _interfaces.ExpirationManager appropriate for back-side use.
-
- Args:
- lock: The operation-wide lock.
- termination_manager: The _interfaces.TerminationManager for the operation.
- transmission_manager: The _interfaces.TransmissionManager for the
- operation.
- ingestion_manager: The _interfaces.IngestionManager for the operation.
- timeout: A length of time in seconds to allow for the operation to run. May
- be None in which case default_timeout will be used.
- default_timeout: The default length of time in seconds to allow for the
- operation to run if the front-side customer has not specified such a value
- (or if the value they specified is not yet known).
- maximum_timeout: The maximum length of time in seconds to allow for the
- operation to run.
-
- Returns:
- An _interfaces.ExpirationManager appropriate for back-side use.
- """
- commencement = time.time()
- expiration_manager = _ExpirationManager(
- lock, termination_manager, transmission_manager, ingestion_manager,
- commencement, default_timeout if timeout is None else timeout,
- maximum_timeout)
- expiration_manager.start()
- return expiration_manager
diff --git a/src/python/grpcio/grpc/framework/base/_ingestion.py b/src/python/grpcio/grpc/framework/base/_ingestion.py
deleted file mode 100644
index c9b10acb77..0000000000
--- a/src/python/grpcio/grpc/framework/base/_ingestion.py
+++ /dev/null
@@ -1,443 +0,0 @@
-# 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.
-
-"""State and behavior for ingestion during an operation."""
-
-import abc
-import collections
-
-import six
-
-from grpc.framework.base import _constants
-from grpc.framework.base import _interfaces
-from grpc.framework.base import exceptions
-from grpc.framework.base import interfaces
-from grpc.framework.foundation import abandonment
-from grpc.framework.foundation import callable_util
-from grpc.framework.foundation import stream
-
-_CREATE_CONSUMER_EXCEPTION_LOG_MESSAGE = 'Exception initializing ingestion!'
-_CONSUME_EXCEPTION_LOG_MESSAGE = 'Exception during ingestion!'
-
-
-class _ConsumerCreation(collections.namedtuple(
- '_ConsumerCreation', ('consumer', 'remote_error', 'abandoned'))):
- """A sum type for the outcome of ingestion initialization.
-
- Either consumer will be non-None, remote_error will be True, or abandoned will
- be True.
-
- Attributes:
- consumer: A stream.Consumer for ingesting payloads.
- remote_error: A boolean indicating that the consumer could not be created
- due to an error on the remote side of the operation.
- abandoned: A boolean indicating that the consumer creation was abandoned.
- """
-
-
-class _EmptyConsumer(stream.Consumer):
- """A no-operative stream.Consumer that ignores all inputs and calls."""
-
- def consume(self, value):
- """See stream.Consumer.consume for specification."""
-
- def terminate(self):
- """See stream.Consumer.terminate for specification."""
-
- def consume_and_terminate(self, value):
- """See stream.Consumer.consume_and_terminate for specification."""
-
-
-class _ConsumerCreator(six.with_metaclass(abc.ABCMeta)):
- """Common specification of different consumer-creating behavior."""
-
- @abc.abstractmethod
- def create_consumer(self, requirement):
- """Creates the stream.Consumer to which customer payloads will be delivered.
-
- Any exceptions raised by this method should be attributed to and treated as
- defects in the serviced or servicer code called by this method.
-
- Args:
- requirement: A value required by this _ConsumerCreator for consumer
- creation.
-
- Returns:
- A _ConsumerCreation describing the result of consumer creation.
- """
- raise NotImplementedError()
-
-
-class _FrontConsumerCreator(_ConsumerCreator):
- """A _ConsumerCreator appropriate for front-side use."""
-
- def __init__(self, subscription, operation_context):
- """Constructor.
-
- Args:
- subscription: The serviced's interfaces.ServicedSubscription for the
- operation.
- operation_context: The interfaces.OperationContext object for the
- operation.
- """
- self._subscription = subscription
- self._operation_context = operation_context
-
- def create_consumer(self, requirement):
- """See _ConsumerCreator.create_consumer for specification."""
- if self._subscription.kind is interfaces.ServicedSubscription.Kind.FULL:
- try:
- return _ConsumerCreation(
- self._subscription.ingestor.consumer(self._operation_context),
- False, False)
- except abandonment.Abandoned:
- return _ConsumerCreation(None, False, True)
- else:
- return _ConsumerCreation(_EmptyConsumer(), False, False)
-
-
-class _BackConsumerCreator(_ConsumerCreator):
- """A _ConsumerCreator appropriate for back-side use."""
-
- def __init__(self, servicer, operation_context, emission_consumer):
- """Constructor.
-
- Args:
- servicer: The interfaces.Servicer that will service the operation.
- operation_context: The interfaces.OperationContext object for the
- operation.
- emission_consumer: The stream.Consumer object to which payloads emitted
- from the operation will be passed.
- """
- self._servicer = servicer
- self._operation_context = operation_context
- self._emission_consumer = emission_consumer
-
- def create_consumer(self, requirement):
- """See _ConsumerCreator.create_consumer for full specification.
-
- Args:
- requirement: The name of the Servicer method to be called during this
- operation.
-
- Returns:
- A _ConsumerCreation describing the result of consumer creation.
- """
- try:
- return _ConsumerCreation(
- self._servicer.service(
- requirement, self._operation_context, self._emission_consumer),
- False, False)
- except exceptions.NoSuchMethodError:
- return _ConsumerCreation(None, True, False)
- except abandonment.Abandoned:
- return _ConsumerCreation(None, False, True)
-
-
-class _WrappedConsumer(object):
- """Wraps a consumer to catch the exceptions that it is allowed to throw."""
-
- def __init__(self, consumer):
- """Constructor.
-
- Args:
- consumer: A stream.Consumer that may raise abandonment.Abandoned from any
- of its methods.
- """
- self._consumer = consumer
-
- def moar(self, payload, complete):
- """Makes progress with the wrapped consumer.
-
- This method catches all exceptions allowed to be thrown by the wrapped
- consumer. Any exceptions raised by this method should be blamed on the
- customer-supplied consumer.
-
- Args:
- payload: A customer-significant payload object. May be None only if
- complete is True.
- complete: Whether or not the end of the payload sequence has been reached.
- Must be True if payload is None.
-
- Returns:
- True if the wrapped consumer made progress or False if the wrapped
- consumer raised abandonment.Abandoned to indicate its abandonment of
- progress.
- """
- try:
- if payload is None:
- self._consumer.terminate()
- elif complete:
- self._consumer.consume_and_terminate(payload)
- else:
- self._consumer.consume(payload)
- return True
- except abandonment.Abandoned:
- return False
-
-
-class _IngestionManager(_interfaces.IngestionManager):
- """An implementation of _interfaces.IngestionManager."""
-
- def __init__(
- self, lock, pool, consumer_creator, failure_outcome, termination_manager,
- transmission_manager):
- """Constructor.
-
- Args:
- lock: The operation-wide lock.
- pool: A thread pool in which to execute customer code.
- consumer_creator: A _ConsumerCreator wrapping the portion of customer code
- that when called returns the stream.Consumer with which the customer
- code will ingest payload values.
- failure_outcome: Whichever one of
- interfaces.Outcome.SERVICED_FAILURE or
- interfaces.Outcome.SERVICER_FAILURE describes local failure of
- customer code.
- termination_manager: The _interfaces.TerminationManager for the operation.
- transmission_manager: The _interfaces.TransmissionManager for the
- operation.
- """
- self._lock = lock
- self._pool = pool
- self._consumer_creator = consumer_creator
- self._failure_outcome = failure_outcome
- self._termination_manager = termination_manager
- self._transmission_manager = transmission_manager
- self._expiration_manager = None
-
- self._wrapped_ingestion_consumer = None
- self._pending_ingestion = []
- self._ingestion_complete = False
- self._processing = False
-
- def set_expiration_manager(self, expiration_manager):
- self._expiration_manager = expiration_manager
-
- def _abort_internal_only(self):
- self._wrapped_ingestion_consumer = None
- self._pending_ingestion = None
-
- def _abort_and_notify(self, outcome):
- self._abort_internal_only()
- self._termination_manager.abort(outcome)
- self._transmission_manager.abort(outcome)
- self._expiration_manager.abort()
-
- def _next(self):
- """Computes the next step for ingestion.
-
- Returns:
- A payload, complete, continue triplet indicating what payload (if any) is
- available to feed into customer code, whether or not the sequence of
- payloads has terminated, and whether or not there is anything
- immediately actionable to call customer code to do.
- """
- if self._pending_ingestion is None:
- return None, False, False
- elif self._pending_ingestion:
- payload = self._pending_ingestion.pop(0)
- complete = self._ingestion_complete and not self._pending_ingestion
- return payload, complete, True
- elif self._ingestion_complete:
- return None, True, True
- else:
- return None, False, False
-
- def _process(self, wrapped_ingestion_consumer, payload, complete):
- """A method to call to execute customer code.
-
- This object's lock must *not* be held when calling this method.
-
- Args:
- wrapped_ingestion_consumer: The _WrappedConsumer with which to pass
- payloads to customer code.
- payload: A customer payload. May be None only if complete is True.
- complete: Whether or not the sequence of payloads to pass to the customer
- has concluded.
- """
- while True:
- consumption_outcome = callable_util.call_logging_exceptions(
- wrapped_ingestion_consumer.moar, _CONSUME_EXCEPTION_LOG_MESSAGE,
- payload, complete)
- if consumption_outcome.exception is None:
- if consumption_outcome.return_value:
- with self._lock:
- if complete:
- self._pending_ingestion = None
- self._termination_manager.ingestion_complete()
- return
- else:
- payload, complete, moar = self._next()
- if not moar:
- self._processing = False
- return
- else:
- with self._lock:
- if self._pending_ingestion is not None:
- self._abort_and_notify(self._failure_outcome)
- self._processing = False
- return
- else:
- with self._lock:
- self._abort_and_notify(self._failure_outcome)
- self._processing = False
- return
-
- def start(self, requirement):
- if self._pending_ingestion is not None:
- def initialize():
- consumer_creation_outcome = callable_util.call_logging_exceptions(
- self._consumer_creator.create_consumer,
- _CREATE_CONSUMER_EXCEPTION_LOG_MESSAGE, requirement)
- if consumer_creation_outcome.return_value is None:
- with self._lock:
- self._abort_and_notify(self._failure_outcome)
- self._processing = False
- elif consumer_creation_outcome.return_value.remote_error:
- with self._lock:
- self._abort_and_notify(interfaces.Outcome.RECEPTION_FAILURE)
- self._processing = False
- elif consumer_creation_outcome.return_value.abandoned:
- with self._lock:
- if self._pending_ingestion is not None:
- self._abort_and_notify(self._failure_outcome)
- self._processing = False
- else:
- wrapped_ingestion_consumer = _WrappedConsumer(
- consumer_creation_outcome.return_value.consumer)
- with self._lock:
- self._wrapped_ingestion_consumer = wrapped_ingestion_consumer
- payload, complete, moar = self._next()
- if not moar:
- self._processing = False
- return
-
- self._process(wrapped_ingestion_consumer, payload, complete)
-
- self._pool.submit(
- callable_util.with_exceptions_logged(
- initialize, _constants.INTERNAL_ERROR_LOG_MESSAGE))
- self._processing = True
-
- def consume(self, payload):
- if self._ingestion_complete:
- self._abort_and_notify(self._failure_outcome)
- elif self._pending_ingestion is not None:
- if self._processing:
- self._pending_ingestion.append(payload)
- else:
- self._pool.submit(
- callable_util.with_exceptions_logged(
- self._process, _constants.INTERNAL_ERROR_LOG_MESSAGE),
- self._wrapped_ingestion_consumer, payload, False)
- self._processing = True
-
- def terminate(self):
- if self._ingestion_complete:
- self._abort_and_notify(self._failure_outcome)
- else:
- self._ingestion_complete = True
- if self._pending_ingestion is not None and not self._processing:
- self._pool.submit(
- callable_util.with_exceptions_logged(
- self._process, _constants.INTERNAL_ERROR_LOG_MESSAGE),
- self._wrapped_ingestion_consumer, None, True)
- self._processing = True
-
- def consume_and_terminate(self, payload):
- if self._ingestion_complete:
- self._abort_and_notify(self._failure_outcome)
- else:
- self._ingestion_complete = True
- if self._pending_ingestion is not None:
- if self._processing:
- self._pending_ingestion.append(payload)
- else:
- self._pool.submit(
- callable_util.with_exceptions_logged(
- self._process, _constants.INTERNAL_ERROR_LOG_MESSAGE),
- self._wrapped_ingestion_consumer, payload, True)
- self._processing = True
-
- def abort(self):
- """See _interfaces.IngestionManager.abort for specification."""
- self._abort_internal_only()
-
-
-def front_ingestion_manager(
- lock, pool, subscription, termination_manager, transmission_manager,
- operation_context):
- """Creates an IngestionManager appropriate for front-side use.
-
- Args:
- lock: The operation-wide lock.
- pool: A thread pool in which to execute customer code.
- subscription: A interfaces.ServicedSubscription indicating the
- customer's interest in the results of the operation.
- termination_manager: The _interfaces.TerminationManager for the operation.
- transmission_manager: The _interfaces.TransmissionManager for the
- operation.
- operation_context: A interfaces.OperationContext for the operation.
-
- Returns:
- An IngestionManager appropriate for front-side use.
- """
- ingestion_manager = _IngestionManager(
- lock, pool, _FrontConsumerCreator(subscription, operation_context),
- interfaces.Outcome.SERVICED_FAILURE, termination_manager,
- transmission_manager)
- ingestion_manager.start(None)
- return ingestion_manager
-
-
-def back_ingestion_manager(
- lock, pool, servicer, termination_manager, transmission_manager,
- operation_context, emission_consumer):
- """Creates an IngestionManager appropriate for back-side use.
-
- Args:
- lock: The operation-wide lock.
- pool: A thread pool in which to execute customer code.
- servicer: A interfaces.Servicer for servicing the operation.
- termination_manager: The _interfaces.TerminationManager for the operation.
- transmission_manager: The _interfaces.TransmissionManager for the
- operation.
- operation_context: A interfaces.OperationContext for the operation.
- emission_consumer: The _interfaces.EmissionConsumer for the operation.
-
- Returns:
- An IngestionManager appropriate for back-side use.
- """
- ingestion_manager = _IngestionManager(
- lock, pool, _BackConsumerCreator(
- servicer, operation_context, emission_consumer),
- interfaces.Outcome.SERVICER_FAILURE, termination_manager,
- transmission_manager)
- return ingestion_manager
diff --git a/src/python/grpcio/grpc/framework/base/_interfaces.py b/src/python/grpcio/grpc/framework/base/_interfaces.py
deleted file mode 100644
index 6bb9837c4a..0000000000
--- a/src/python/grpcio/grpc/framework/base/_interfaces.py
+++ /dev/null
@@ -1,266 +0,0 @@
-# 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.
-
-"""Package-internal interfaces."""
-
-import abc
-
-import six
-
-# interfaces is referenced from specification in this module.
-from grpc.framework.base import interfaces # pylint: disable=unused-import
-from grpc.framework.foundation import stream
-
-
-class TerminationManager(six.with_metaclass(abc.ABCMeta)):
- """An object responsible for handling the termination of an operation."""
-
- @abc.abstractmethod
- def set_expiration_manager(self, expiration_manager):
- """Sets the ExpirationManager with which this object will cooperate."""
- raise NotImplementedError()
-
- @abc.abstractmethod
- def is_active(self):
- """Reports whether or not the operation is active.
-
- Returns:
- True if the operation is active or False if the operation has terminated.
- """
- raise NotImplementedError()
-
- @abc.abstractmethod
- def add_callback(self, callback):
- """Registers a callback to be called on operation termination.
-
- If the operation has already terminated, the callback will be called
- immediately.
-
- Args:
- callback: A callable that will be passed an interfaces.Outcome value.
- """
- raise NotImplementedError()
-
- @abc.abstractmethod
- def emission_complete(self):
- """Indicates that emissions from customer code have completed."""
- raise NotImplementedError()
-
- @abc.abstractmethod
- def transmission_complete(self):
- """Indicates that transmissions to the remote end are complete."""
- raise NotImplementedError()
-
- @abc.abstractmethod
- def ingestion_complete(self):
- """Indicates that customer code ingestion of received values is complete."""
- raise NotImplementedError()
-
- @abc.abstractmethod
- def abort(self, outcome):
- """Indicates that the operation must abort for the indicated reason.
-
- Args:
- outcome: An interfaces.Outcome indicating operation abortion.
- """
- raise NotImplementedError()
-
-
-class TransmissionManager(six.with_metaclass(abc.ABCMeta)):
- """A manager responsible for transmitting to the other end of an operation."""
-
- @abc.abstractmethod
- def inmit(self, emission, complete):
- """Accepts a value for transmission to the other end of the operation.
-
- Args:
- emission: A value of some significance to the customer to be transmitted
- to the other end of the operation. May be None only if complete is True.
- complete: A boolean that if True indicates that customer code has emitted
- all values it intends to emit.
- """
- raise NotImplementedError()
-
- @abc.abstractmethod
- def abort(self, outcome):
- """Indicates that the operation has aborted for the indicated reason.
-
- Args:
- outcome: An interfaces.Outcome indicating operation abortion.
- """
- raise NotImplementedError()
-
-
-class EmissionManager(six.with_metaclass(abc.ABCMeta, stream.Consumer)):
- """A manager of values emitted by customer code."""
-
- @abc.abstractmethod
- def set_ingestion_manager_and_expiration_manager(
- self, ingestion_manager, expiration_manager):
- """Sets two other objects with which this EmissionManager will cooperate.
-
- Args:
- ingestion_manager: The IngestionManager for the operation.
- expiration_manager: The ExpirationManager for the operation.
- """
- raise NotImplementedError()
-
- @abc.abstractmethod
- def consume(self, value):
- """Accepts a value emitted by customer code.
-
- This method should only be called by customer code.
-
- Args:
- value: Any value of significance to the customer.
- """
- raise NotImplementedError()
-
- @abc.abstractmethod
- def terminate(self):
- """Indicates that no more values will be emitted by customer code.
-
- This method should only be called by customer code.
-
- Implementations of this method may be idempotent and forgive customer code
- calling this method more than once.
- """
- raise NotImplementedError()
-
- @abc.abstractmethod
- def consume_and_terminate(self, value):
- """Accepts the last value emitted by customer code.
-
- This method should only be called by customer code.
-
- Args:
- value: Any value of significance to the customer.
- """
- raise NotImplementedError()
-
-
-class IngestionManager(six.with_metaclass(abc.ABCMeta, stream.Consumer)):
- """A manager responsible for executing customer code."""
-
- @abc.abstractmethod
- def set_expiration_manager(self, expiration_manager):
- """Sets the ExpirationManager with which this object will cooperate."""
- raise NotImplementedError()
-
- @abc.abstractmethod
- def start(self, requirement):
- """Commences execution of customer code.
-
- Args:
- requirement: Some value unavailable at the time of this object's
- construction that is required to begin executing customer code.
- """
- raise NotImplementedError()
-
- @abc.abstractmethod
- def consume(self, payload):
- """Accepts a customer-significant value to be supplied to customer code.
-
- Args:
- payload: Some customer-significant value.
- """
- raise NotImplementedError()
-
- @abc.abstractmethod
- def terminate(self):
- """Indicates the end of values to be supplied to customer code."""
- raise NotImplementedError()
-
- @abc.abstractmethod
- def consume_and_terminate(self, payload):
- """Accepts the last value to be supplied to customer code.
-
- Args:
- payload: Some customer-significant value (and the last such value).
- """
- raise NotImplementedError()
-
- @abc.abstractmethod
- def abort(self):
- """Indicates to this manager that the operation has aborted."""
- raise NotImplementedError()
-
-
-class ExpirationManager(six.with_metaclass(abc.ABCMeta)):
- """A manager responsible for aborting the operation if it runs out of time."""
-
- @abc.abstractmethod
- def change_timeout(self, timeout):
- """Changes the timeout allotted for the operation.
-
- Operation duration is always measure from the beginning of the operation;
- calling this method changes the operation's allotted time to timeout total
- seconds, not timeout seconds from the time of this method call.
-
- Args:
- timeout: A length of time in seconds to allow for the operation.
- """
- raise NotImplementedError()
-
- @abc.abstractmethod
- def deadline(self):
- """Returns the time until which the operation is allowed to run.
-
- Returns:
- The time (seconds since the epoch) at which the operation will expire.
- """
- raise NotImplementedError()
-
- @abc.abstractmethod
- def abort(self):
- """Indicates to this manager that the operation has aborted."""
- raise NotImplementedError()
-
-
-class ReceptionManager(six.with_metaclass(abc.ABCMeta)):
- """A manager responsible for receiving tickets from the other end."""
-
- @abc.abstractmethod
- def receive_ticket(self, ticket):
- """Handle a ticket from the other side of the operation.
-
- Args:
- ticket: An interfaces.BackToFrontTicket or interfaces.FrontToBackTicket
- appropriate to this end of the operation and this object.
- """
- raise NotImplementedError()
-
-
-class CancellationManager(six.with_metaclass(abc.ABCMeta)):
- """A manager of operation cancellation."""
-
- @abc.abstractmethod
- def cancel(self):
- """Cancels the operation."""
- raise NotImplementedError()
diff --git a/src/python/grpcio/grpc/framework/base/_reception.py b/src/python/grpcio/grpc/framework/base/_reception.py
deleted file mode 100644
index a59c5165f9..0000000000
--- a/src/python/grpcio/grpc/framework/base/_reception.py
+++ /dev/null
@@ -1,400 +0,0 @@
-# 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.
-
-"""State and behavior for ticket reception."""
-
-import abc
-
-import six
-
-from grpc.framework.base import interfaces
-from grpc.framework.base import _interfaces
-
-_INITIAL_FRONT_TO_BACK_TICKET_KINDS = (
- interfaces.FrontToBackTicket.Kind.COMMENCEMENT,
- interfaces.FrontToBackTicket.Kind.ENTIRE,
-)
-
-
-class _Receiver(six.with_metaclass(abc.ABCMeta)):
- """Common specification of different ticket-handling behavior."""
-
- @abc.abstractmethod
- def abort_if_abortive(self, ticket):
- """Aborts the operation if the ticket is abortive.
-
- Args:
- ticket: A just-arrived ticket.
-
- Returns:
- A boolean indicating whether or not this Receiver aborted the operation
- based on the ticket.
- """
- raise NotImplementedError()
-
- @abc.abstractmethod
- def receive(self, ticket):
- """Handles a just-arrived ticket.
-
- Args:
- ticket: A just-arrived ticket.
-
- Returns:
- A boolean indicating whether or not the ticket was terminal (i.e. whether
- or not non-abortive tickets are legal after this one).
- """
- raise NotImplementedError()
-
- @abc.abstractmethod
- def reception_failure(self):
- """Aborts the operation with an indication of reception failure."""
- raise NotImplementedError()
-
-
-def _abort(
- outcome, termination_manager, transmission_manager, ingestion_manager,
- expiration_manager):
- """Indicates abortion with the given outcome to the given managers."""
- termination_manager.abort(outcome)
- transmission_manager.abort(outcome)
- ingestion_manager.abort()
- expiration_manager.abort()
-
-
-def _abort_if_abortive(
- ticket, abortive, termination_manager, transmission_manager,
- ingestion_manager, expiration_manager):
- """Determines a ticket's being abortive and if so aborts the operation.
-
- Args:
- ticket: A just-arrived ticket.
- abortive: A callable that takes a ticket and returns an interfaces.Outcome
- indicating that the operation should be aborted or None indicating that
- the operation should not be aborted.
- termination_manager: The operation's _interfaces.TerminationManager.
- transmission_manager: The operation's _interfaces.TransmissionManager.
- ingestion_manager: The operation's _interfaces.IngestionManager.
- expiration_manager: The operation's _interfaces.ExpirationManager.
-
- Returns:
- True if the operation was aborted; False otherwise.
- """
- abortion_outcome = abortive(ticket)
- if abortion_outcome is None:
- return False
- else:
- _abort(
- abortion_outcome, termination_manager, transmission_manager,
- ingestion_manager, expiration_manager)
- return True
-
-
-def _reception_failure(
- termination_manager, transmission_manager, ingestion_manager,
- expiration_manager):
- """Aborts the operation with an indication of reception failure."""
- _abort(
- interfaces.Outcome.RECEPTION_FAILURE, termination_manager,
- transmission_manager, ingestion_manager, expiration_manager)
-
-
-class _BackReceiver(_Receiver):
- """Ticket-handling specific to the back side of an operation."""
-
- def __init__(
- self, termination_manager, transmission_manager, ingestion_manager,
- expiration_manager):
- """Constructor.
-
- Args:
- termination_manager: The operation's _interfaces.TerminationManager.
- transmission_manager: The operation's _interfaces.TransmissionManager.
- ingestion_manager: The operation's _interfaces.IngestionManager.
- expiration_manager: The operation's _interfaces.ExpirationManager.
- """
- self._termination_manager = termination_manager
- self._transmission_manager = transmission_manager
- self._ingestion_manager = ingestion_manager
- self._expiration_manager = expiration_manager
-
- self._first_ticket_seen = False
- self._last_ticket_seen = False
-
- def _abortive(self, ticket):
- """Determines whether or not (and if so, how) a ticket is abortive.
-
- Args:
- ticket: A just-arrived ticket.
-
- Returns:
- An interfaces.Outcome value describing operation abortion if the
- ticket is abortive or None if the ticket is not abortive.
- """
- if ticket.kind is interfaces.FrontToBackTicket.Kind.CANCELLATION:
- return interfaces.Outcome.CANCELLED
- elif ticket.kind is interfaces.FrontToBackTicket.Kind.EXPIRATION:
- return interfaces.Outcome.EXPIRED
- elif ticket.kind is interfaces.FrontToBackTicket.Kind.SERVICED_FAILURE:
- return interfaces.Outcome.SERVICED_FAILURE
- elif ticket.kind is interfaces.FrontToBackTicket.Kind.RECEPTION_FAILURE:
- return interfaces.Outcome.SERVICED_FAILURE
- elif (ticket.kind in _INITIAL_FRONT_TO_BACK_TICKET_KINDS and
- self._first_ticket_seen):
- return interfaces.Outcome.RECEPTION_FAILURE
- elif self._last_ticket_seen:
- return interfaces.Outcome.RECEPTION_FAILURE
- else:
- return None
-
- def abort_if_abortive(self, ticket):
- """See _Receiver.abort_if_abortive for specification."""
- return _abort_if_abortive(
- ticket, self._abortive, self._termination_manager,
- self._transmission_manager, self._ingestion_manager,
- self._expiration_manager)
-
- def receive(self, ticket):
- """See _Receiver.receive for specification."""
- if ticket.timeout is not None:
- self._expiration_manager.change_timeout(ticket.timeout)
-
- if ticket.kind is interfaces.FrontToBackTicket.Kind.COMMENCEMENT:
- self._first_ticket_seen = True
- self._ingestion_manager.start(ticket.name)
- if ticket.payload is not None:
- self._ingestion_manager.consume(ticket.payload)
- elif ticket.kind is interfaces.FrontToBackTicket.Kind.CONTINUATION:
- self._ingestion_manager.consume(ticket.payload)
- elif ticket.kind is interfaces.FrontToBackTicket.Kind.COMPLETION:
- self._last_ticket_seen = True
- if ticket.payload is None:
- self._ingestion_manager.terminate()
- else:
- self._ingestion_manager.consume_and_terminate(ticket.payload)
- else:
- self._first_ticket_seen = True
- self._last_ticket_seen = True
- self._ingestion_manager.start(ticket.name)
- if ticket.payload is None:
- self._ingestion_manager.terminate()
- else:
- self._ingestion_manager.consume_and_terminate(ticket.payload)
-
- def reception_failure(self):
- """See _Receiver.reception_failure for specification."""
- _reception_failure(
- self._termination_manager, self._transmission_manager,
- self._ingestion_manager, self._expiration_manager)
-
-
-class _FrontReceiver(_Receiver):
- """Ticket-handling specific to the front side of an operation."""
-
- def __init__(
- self, termination_manager, transmission_manager, ingestion_manager,
- expiration_manager):
- """Constructor.
-
- Args:
- termination_manager: The operation's _interfaces.TerminationManager.
- transmission_manager: The operation's _interfaces.TransmissionManager.
- ingestion_manager: The operation's _interfaces.IngestionManager.
- expiration_manager: The operation's _interfaces.ExpirationManager.
- """
- self._termination_manager = termination_manager
- self._transmission_manager = transmission_manager
- self._ingestion_manager = ingestion_manager
- self._expiration_manager = expiration_manager
-
- self._last_ticket_seen = False
-
- def _abortive(self, ticket):
- """Determines whether or not (and if so, how) a ticket is abortive.
-
- Args:
- ticket: A just-arrived ticket.
-
- Returns:
- An interfaces.Outcome value describing operation abortion if the ticket
- is abortive or None if the ticket is not abortive.
- """
- if ticket.kind is interfaces.BackToFrontTicket.Kind.CANCELLATION:
- return interfaces.Outcome.CANCELLED
- elif ticket.kind is interfaces.BackToFrontTicket.Kind.EXPIRATION:
- return interfaces.Outcome.EXPIRED
- elif ticket.kind is interfaces.BackToFrontTicket.Kind.SERVICER_FAILURE:
- return interfaces.Outcome.SERVICER_FAILURE
- elif ticket.kind is interfaces.BackToFrontTicket.Kind.RECEPTION_FAILURE:
- return interfaces.Outcome.SERVICER_FAILURE
- elif self._last_ticket_seen:
- return interfaces.Outcome.RECEPTION_FAILURE
- else:
- return None
-
- def abort_if_abortive(self, ticket):
- """See _Receiver.abort_if_abortive for specification."""
- return _abort_if_abortive(
- ticket, self._abortive, self._termination_manager,
- self._transmission_manager, self._ingestion_manager,
- self._expiration_manager)
-
- def receive(self, ticket):
- """See _Receiver.receive for specification."""
- if ticket.kind is interfaces.BackToFrontTicket.Kind.CONTINUATION:
- self._ingestion_manager.consume(ticket.payload)
- elif ticket.kind is interfaces.BackToFrontTicket.Kind.COMPLETION:
- self._last_ticket_seen = True
- if ticket.payload is None:
- self._ingestion_manager.terminate()
- else:
- self._ingestion_manager.consume_and_terminate(ticket.payload)
-
- def reception_failure(self):
- """See _Receiver.reception_failure for specification."""
- _reception_failure(
- self._termination_manager, self._transmission_manager,
- self._ingestion_manager, self._expiration_manager)
-
-
-class _ReceptionManager(_interfaces.ReceptionManager):
- """A ReceptionManager based around a _Receiver passed to it."""
-
- def __init__(self, lock, receiver):
- """Constructor.
-
- Args:
- lock: The operation-servicing-wide lock object.
- receiver: A _Receiver responsible for handling received tickets.
- """
- self._lock = lock
- self._receiver = receiver
-
- self._lowest_unseen_sequence_number = 0
- self._out_of_sequence_tickets = {}
- self._completed_sequence_number = None
- self._aborted = False
-
- def _sequence_failure(self, ticket):
- """Determines a just-arrived ticket's sequential legitimacy.
-
- Args:
- ticket: A just-arrived ticket.
-
- Returns:
- True if the ticket is sequentially legitimate; False otherwise.
- """
- if ticket.sequence_number < self._lowest_unseen_sequence_number:
- return True
- elif ticket.sequence_number in self._out_of_sequence_tickets:
- return True
- elif (self._completed_sequence_number is not None and
- self._completed_sequence_number <= ticket.sequence_number):
- return True
- else:
- return False
-
- def _process(self, ticket):
- """Process those tickets ready to be processed.
-
- Args:
- ticket: A just-arrived ticket the sequence number of which matches this
- _ReceptionManager's _lowest_unseen_sequence_number field.
- """
- while True:
- completed = self._receiver.receive(ticket)
- if completed:
- self._out_of_sequence_tickets.clear()
- self._completed_sequence_number = ticket.sequence_number
- self._lowest_unseen_sequence_number = ticket.sequence_number + 1
- return
- else:
- next_ticket = self._out_of_sequence_tickets.pop(
- ticket.sequence_number + 1, None)
- if next_ticket is None:
- self._lowest_unseen_sequence_number = ticket.sequence_number + 1
- return
- else:
- ticket = next_ticket
-
- def receive_ticket(self, ticket):
- """See _interfaces.ReceptionManager.receive_ticket for specification."""
- with self._lock:
- if self._aborted:
- return
- elif self._sequence_failure(ticket):
- self._receiver.reception_failure()
- self._aborted = True
- elif self._receiver.abort_if_abortive(ticket):
- self._aborted = True
- elif ticket.sequence_number == self._lowest_unseen_sequence_number:
- self._process(ticket)
- else:
- self._out_of_sequence_tickets[ticket.sequence_number] = ticket
-
-
-def front_reception_manager(
- lock, termination_manager, transmission_manager, ingestion_manager,
- expiration_manager):
- """Creates a _interfaces.ReceptionManager for front-side use.
-
- Args:
- lock: The operation-servicing-wide lock object.
- termination_manager: The operation's _interfaces.TerminationManager.
- transmission_manager: The operation's _interfaces.TransmissionManager.
- ingestion_manager: The operation's _interfaces.IngestionManager.
- expiration_manager: The operation's _interfaces.ExpirationManager.
-
- Returns:
- A _interfaces.ReceptionManager appropriate for front-side use.
- """
- return _ReceptionManager(
- lock, _FrontReceiver(
- termination_manager, transmission_manager, ingestion_manager,
- expiration_manager))
-
-
-def back_reception_manager(
- lock, termination_manager, transmission_manager, ingestion_manager,
- expiration_manager):
- """Creates a _interfaces.ReceptionManager for back-side use.
-
- Args:
- lock: The operation-servicing-wide lock object.
- termination_manager: The operation's _interfaces.TerminationManager.
- transmission_manager: The operation's _interfaces.TransmissionManager.
- ingestion_manager: The operation's _interfaces.IngestionManager.
- expiration_manager: The operation's _interfaces.ExpirationManager.
-
- Returns:
- A _interfaces.ReceptionManager appropriate for back-side use.
- """
- return _ReceptionManager(
- lock, _BackReceiver(
- termination_manager, transmission_manager, ingestion_manager,
- expiration_manager))
diff --git a/src/python/grpcio/grpc/framework/base/_termination.py b/src/python/grpcio/grpc/framework/base/_termination.py
deleted file mode 100644
index ddcbc60293..0000000000
--- a/src/python/grpcio/grpc/framework/base/_termination.py
+++ /dev/null
@@ -1,204 +0,0 @@
-# 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.
-
-"""State and behavior for operation termination."""
-
-import enum
-
-from grpc.framework.base import _constants
-from grpc.framework.base import _interfaces
-from grpc.framework.base import interfaces
-from grpc.framework.foundation import callable_util
-
-_CALLBACK_EXCEPTION_LOG_MESSAGE = 'Exception calling termination callback!'
-
-
-@enum.unique
-class _Requirement(enum.Enum):
- """Symbols indicating events required for termination."""
-
- EMISSION = 'emission'
- TRANSMISSION = 'transmission'
- INGESTION = 'ingestion'
-
-_FRONT_NOT_LISTENING_REQUIREMENTS = (_Requirement.TRANSMISSION,)
-_BACK_NOT_LISTENING_REQUIREMENTS = (
- _Requirement.EMISSION, _Requirement.INGESTION,)
-_LISTENING_REQUIREMENTS = (
- _Requirement.TRANSMISSION, _Requirement.INGESTION,)
-
-
-class _TerminationManager(_interfaces.TerminationManager):
- """An implementation of _interfaces.TerminationManager."""
-
- def __init__(
- self, work_pool, utility_pool, action, requirements, local_failure):
- """Constructor.
-
- Args:
- work_pool: A thread pool in which customer work will be done.
- utility_pool: A thread pool in which work utility work will be done.
- action: An action to call on operation termination.
- requirements: A combination of _Requirement values identifying what
- must finish for the operation to be considered completed.
- local_failure: An interfaces.Outcome specifying what constitutes local
- failure of customer work.
- """
- self._work_pool = work_pool
- self._utility_pool = utility_pool
- self._action = action
- self._local_failure = local_failure
- self._has_locally_failed = False
- self._expiration_manager = None
-
- self._outstanding_requirements = set(requirements)
- self._outcome = None
- self._callbacks = []
-
- def set_expiration_manager(self, expiration_manager):
- self._expiration_manager = expiration_manager
-
- def _terminate(self, outcome):
- """Terminates the operation.
-
- Args:
- outcome: An interfaces.Outcome describing the outcome of the operation.
- """
- self._expiration_manager.abort()
- self._outstanding_requirements = None
- callbacks = list(self._callbacks)
- self._callbacks = None
- self._outcome = outcome
-
- act = callable_util.with_exceptions_logged(
- self._action, _constants.INTERNAL_ERROR_LOG_MESSAGE)
-
- if self._has_locally_failed:
- self._utility_pool.submit(act, outcome)
- else:
- def call_callbacks_and_act(callbacks, outcome):
- for callback in callbacks:
- callback_outcome = callable_util.call_logging_exceptions(
- callback, _CALLBACK_EXCEPTION_LOG_MESSAGE, outcome)
- if callback_outcome.exception is not None:
- outcome = self._local_failure
- break
- self._utility_pool.submit(act, outcome)
-
- self._work_pool.submit(callable_util.with_exceptions_logged(
- call_callbacks_and_act,
- _constants.INTERNAL_ERROR_LOG_MESSAGE),
- callbacks, outcome)
-
- def is_active(self):
- """See _interfaces.TerminationManager.is_active for specification."""
- return self._outstanding_requirements is not None
-
- def add_callback(self, callback):
- """See _interfaces.TerminationManager.add_callback for specification."""
- if not self._has_locally_failed:
- if self._outstanding_requirements is None:
- self._work_pool.submit(
- callable_util.with_exceptions_logged(
- callback, _CALLBACK_EXCEPTION_LOG_MESSAGE), self._outcome)
- else:
- self._callbacks.append(callback)
-
- def emission_complete(self):
- """See superclass method for specification."""
- if self._outstanding_requirements is not None:
- self._outstanding_requirements.discard(_Requirement.EMISSION)
- if not self._outstanding_requirements:
- self._terminate(interfaces.Outcome.COMPLETED)
-
- def transmission_complete(self):
- """See superclass method for specification."""
- if self._outstanding_requirements is not None:
- self._outstanding_requirements.discard(_Requirement.TRANSMISSION)
- if not self._outstanding_requirements:
- self._terminate(interfaces.Outcome.COMPLETED)
-
- def ingestion_complete(self):
- """See superclass method for specification."""
- if self._outstanding_requirements is not None:
- self._outstanding_requirements.discard(_Requirement.INGESTION)
- if not self._outstanding_requirements:
- self._terminate(interfaces.Outcome.COMPLETED)
-
- def abort(self, outcome):
- """See _interfaces.TerminationManager.abort for specification."""
- if outcome is self._local_failure:
- self._has_failed_locally = True
- if self._outstanding_requirements is not None:
- self._terminate(outcome)
-
-
-def front_termination_manager(
- work_pool, utility_pool, action, subscription_kind):
- """Creates a TerminationManager appropriate for front-side use.
-
- Args:
- work_pool: A thread pool in which customer work will be done.
- utility_pool: A thread pool in which work utility work will be done.
- action: An action to call on operation termination.
- subscription_kind: An interfaces.ServicedSubscription.Kind value.
-
- Returns:
- A TerminationManager appropriate for front-side use.
- """
- if subscription_kind is interfaces.ServicedSubscription.Kind.NONE:
- requirements = _FRONT_NOT_LISTENING_REQUIREMENTS
- else:
- requirements = _LISTENING_REQUIREMENTS
-
- return _TerminationManager(
- work_pool, utility_pool, action, requirements,
- interfaces.Outcome.SERVICED_FAILURE)
-
-
-def back_termination_manager(work_pool, utility_pool, action, subscription_kind):
- """Creates a TerminationManager appropriate for back-side use.
-
- Args:
- work_pool: A thread pool in which customer work will be done.
- utility_pool: A thread pool in which work utility work will be done.
- action: An action to call on operation termination.
- subscription_kind: An interfaces.ServicedSubscription.Kind value.
-
- Returns:
- A TerminationManager appropriate for back-side use.
- """
- if subscription_kind is interfaces.ServicedSubscription.Kind.NONE:
- requirements = _BACK_NOT_LISTENING_REQUIREMENTS
- else:
- requirements = _LISTENING_REQUIREMENTS
-
- return _TerminationManager(
- work_pool, utility_pool, action, requirements,
- interfaces.Outcome.SERVICER_FAILURE)
diff --git a/src/python/grpcio/grpc/framework/base/_transmission.py b/src/python/grpcio/grpc/framework/base/_transmission.py
deleted file mode 100644
index e2a25626f1..0000000000
--- a/src/python/grpcio/grpc/framework/base/_transmission.py
+++ /dev/null
@@ -1,429 +0,0 @@
-# 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.
-
-"""State and behavior for ticket transmission during an operation."""
-
-import abc
-
-import six
-
-from grpc.framework.base import _constants
-from grpc.framework.base import _interfaces
-from grpc.framework.base import interfaces
-from grpc.framework.foundation import callable_util
-
-_TRANSMISSION_EXCEPTION_LOG_MESSAGE = 'Exception during transmission!'
-
-_FRONT_TO_BACK_NO_TRANSMISSION_OUTCOMES = (
- interfaces.Outcome.SERVICER_FAILURE,
- )
-_BACK_TO_FRONT_NO_TRANSMISSION_OUTCOMES = (
- interfaces.Outcome.CANCELLED,
- interfaces.Outcome.SERVICED_FAILURE,
- )
-
-_ABORTION_OUTCOME_TO_FRONT_TO_BACK_TICKET_KIND = {
- interfaces.Outcome.CANCELLED:
- interfaces.FrontToBackTicket.Kind.CANCELLATION,
- interfaces.Outcome.EXPIRED:
- interfaces.FrontToBackTicket.Kind.EXPIRATION,
- interfaces.Outcome.RECEPTION_FAILURE:
- interfaces.FrontToBackTicket.Kind.RECEPTION_FAILURE,
- interfaces.Outcome.TRANSMISSION_FAILURE:
- interfaces.FrontToBackTicket.Kind.TRANSMISSION_FAILURE,
- interfaces.Outcome.SERVICED_FAILURE:
- interfaces.FrontToBackTicket.Kind.SERVICED_FAILURE,
- interfaces.Outcome.SERVICER_FAILURE:
- interfaces.FrontToBackTicket.Kind.SERVICER_FAILURE,
-}
-
-_ABORTION_OUTCOME_TO_BACK_TO_FRONT_TICKET_KIND = {
- interfaces.Outcome.CANCELLED:
- interfaces.BackToFrontTicket.Kind.CANCELLATION,
- interfaces.Outcome.EXPIRED:
- interfaces.BackToFrontTicket.Kind.EXPIRATION,
- interfaces.Outcome.RECEPTION_FAILURE:
- interfaces.BackToFrontTicket.Kind.RECEPTION_FAILURE,
- interfaces.Outcome.TRANSMISSION_FAILURE:
- interfaces.BackToFrontTicket.Kind.TRANSMISSION_FAILURE,
- interfaces.Outcome.SERVICED_FAILURE:
- interfaces.BackToFrontTicket.Kind.SERVICED_FAILURE,
- interfaces.Outcome.SERVICER_FAILURE:
- interfaces.BackToFrontTicket.Kind.SERVICER_FAILURE,
-}
-
-
-class _Ticketizer(six.with_metaclass(abc.ABCMeta)):
- """Common specification of different ticket-creating behavior."""
-
- @abc.abstractmethod
- def ticketize(self, operation_id, sequence_number, payload, complete):
- """Creates a ticket indicating ordinary operation progress.
-
- Args:
- operation_id: The operation ID for the current operation.
- sequence_number: A sequence number for the ticket.
- payload: A customer payload object. May be None if sequence_number is
- zero or complete is true.
- complete: A boolean indicating whether or not the ticket should describe
- itself as (but for a later indication of operation abortion) the last
- ticket to be sent.
-
- Returns:
- An object of an appropriate type suitable for transmission to the other
- side of the operation.
- """
- raise NotImplementedError()
-
- @abc.abstractmethod
- def ticketize_abortion(self, operation_id, sequence_number, outcome):
- """Creates a ticket indicating that the operation is aborted.
-
- Args:
- operation_id: The operation ID for the current operation.
- sequence_number: A sequence number for the ticket.
- outcome: An interfaces.Outcome value describing the operation abortion.
-
- Returns:
- An object of an appropriate type suitable for transmission to the other
- side of the operation, or None if transmission is not appropriate for
- the given outcome.
- """
- raise NotImplementedError()
-
-
-class _FrontTicketizer(_Ticketizer):
- """Front-side ticket-creating behavior."""
-
- def __init__(self, name, subscription_kind, trace_id, timeout):
- """Constructor.
-
- Args:
- name: The name of the operation.
- subscription_kind: An interfaces.ServicedSubscription.Kind value
- describing the interest the front has in tickets sent from the back.
- trace_id: A uuid.UUID identifying a set of related operations to which
- this operation belongs.
- timeout: A length of time in seconds to allow for the entire operation.
- """
- self._name = name
- self._subscription_kind = subscription_kind
- self._trace_id = trace_id
- self._timeout = timeout
-
- def ticketize(self, operation_id, sequence_number, payload, complete):
- """See _Ticketizer.ticketize for specification."""
- if sequence_number:
- if complete:
- kind = interfaces.FrontToBackTicket.Kind.COMPLETION
- else:
- kind = interfaces.FrontToBackTicket.Kind.CONTINUATION
- return interfaces.FrontToBackTicket(
- operation_id, sequence_number, kind, self._name,
- self._subscription_kind, self._trace_id, payload, self._timeout)
- else:
- if complete:
- kind = interfaces.FrontToBackTicket.Kind.ENTIRE
- else:
- kind = interfaces.FrontToBackTicket.Kind.COMMENCEMENT
- return interfaces.FrontToBackTicket(
- operation_id, 0, kind, self._name, self._subscription_kind,
- self._trace_id, payload, self._timeout)
-
- def ticketize_abortion(self, operation_id, sequence_number, outcome):
- """See _Ticketizer.ticketize_abortion for specification."""
- if outcome in _FRONT_TO_BACK_NO_TRANSMISSION_OUTCOMES:
- return None
- else:
- kind = _ABORTION_OUTCOME_TO_FRONT_TO_BACK_TICKET_KIND[outcome]
- return interfaces.FrontToBackTicket(
- operation_id, sequence_number, kind, None, None, None, None, None)
-
-
-class _BackTicketizer(_Ticketizer):
- """Back-side ticket-creating behavior."""
-
- def ticketize(self, operation_id, sequence_number, payload, complete):
- """See _Ticketizer.ticketize for specification."""
- if complete:
- kind = interfaces.BackToFrontTicket.Kind.COMPLETION
- else:
- kind = interfaces.BackToFrontTicket.Kind.CONTINUATION
- return interfaces.BackToFrontTicket(
- operation_id, sequence_number, kind, payload)
-
- def ticketize_abortion(self, operation_id, sequence_number, outcome):
- """See _Ticketizer.ticketize_abortion for specification."""
- if outcome in _BACK_TO_FRONT_NO_TRANSMISSION_OUTCOMES:
- return None
- else:
- kind = _ABORTION_OUTCOME_TO_BACK_TO_FRONT_TICKET_KIND[outcome]
- return interfaces.BackToFrontTicket(
- operation_id, sequence_number, kind, None)
-
-
-class TransmissionManager(six.with_metaclass(abc.ABCMeta, _interfaces.TransmissionManager)):
- """A _interfaces.TransmissionManager on which other managers may be set."""
-
- @abc.abstractmethod
- def set_ingestion_and_expiration_managers(
- self, ingestion_manager, expiration_manager):
- """Sets two of the other managers with which this manager may interact.
-
- Args:
- ingestion_manager: The _interfaces.IngestionManager associated with the
- current operation.
- expiration_manager: The _interfaces.ExpirationManager associated with the
- current operation.
- """
- raise NotImplementedError()
-
-
-class _EmptyTransmissionManager(TransmissionManager):
- """A completely no-operative _interfaces.TransmissionManager."""
-
- def set_ingestion_and_expiration_managers(
- self, ingestion_manager, expiration_manager):
- """See overriden method for specification."""
-
- def inmit(self, emission, complete):
- """See _interfaces.TransmissionManager.inmit for specification."""
-
- def abort(self, outcome):
- """See _interfaces.TransmissionManager.abort for specification."""
-
-
-class _TransmittingTransmissionManager(TransmissionManager):
- """A TransmissionManager implementation that sends tickets."""
-
- def __init__(
- self, lock, pool, callback, operation_id, ticketizer,
- termination_manager):
- """Constructor.
-
- Args:
- lock: The operation-servicing-wide lock object.
- pool: A thread pool in which the work of transmitting tickets will be
- performed.
- callback: A callable that accepts tickets and sends them to the other side
- of the operation.
- operation_id: The operation's ID.
- ticketizer: A _Ticketizer for ticket creation.
- termination_manager: The _interfaces.TerminationManager associated with
- this operation.
- """
- self._lock = lock
- self._pool = pool
- self._callback = callback
- self._operation_id = operation_id
- self._ticketizer = ticketizer
- self._termination_manager = termination_manager
- self._ingestion_manager = None
- self._expiration_manager = None
-
- self._emissions = []
- self._emission_complete = False
- self._outcome = None
- self._lowest_unused_sequence_number = 0
- self._transmitting = False
-
- def set_ingestion_and_expiration_managers(
- self, ingestion_manager, expiration_manager):
- """See overridden method for specification."""
- self._ingestion_manager = ingestion_manager
- self._expiration_manager = expiration_manager
-
- def _lead_ticket(self, emission, complete):
- """Creates a ticket suitable for leading off the transmission loop.
-
- Args:
- emission: A customer payload object to be sent to the other side of the
- operation.
- complete: Whether or not the sequence of customer payloads ends with
- the passed object.
-
- Returns:
- A ticket with which to lead off the transmission loop.
- """
- sequence_number = self._lowest_unused_sequence_number
- self._lowest_unused_sequence_number += 1
- return self._ticketizer.ticketize(
- self._operation_id, sequence_number, emission, complete)
-
- def _abortive_response_ticket(self, outcome):
- """Creates a ticket indicating operation abortion.
-
- Args:
- outcome: An interfaces.Outcome value describing operation abortion.
-
- Returns:
- A ticket indicating operation abortion.
- """
- ticket = self._ticketizer.ticketize_abortion(
- self._operation_id, self._lowest_unused_sequence_number, outcome)
- if ticket is None:
- return None
- else:
- self._lowest_unused_sequence_number += 1
- return ticket
-
- def _next_ticket(self):
- """Creates the next ticket to be sent to the other side of the operation.
-
- Returns:
- A (completed, ticket) tuple comprised of a boolean indicating whether or
- not the sequence of tickets has completed normally and a ticket to send
- to the other side if the sequence of tickets hasn't completed. The tuple
- will never have both a True first element and a non-None second element.
- """
- if self._emissions is None:
- return False, None
- elif self._outcome is None:
- if self._emissions:
- payload = self._emissions.pop(0)
- complete = self._emission_complete and not self._emissions
- sequence_number = self._lowest_unused_sequence_number
- self._lowest_unused_sequence_number += 1
- return complete, self._ticketizer.ticketize(
- self._operation_id, sequence_number, payload, complete)
- else:
- return self._emission_complete, None
- else:
- ticket = self._abortive_response_ticket(self._outcome)
- self._emissions = None
- return False, None if ticket is None else ticket
-
- def _transmit(self, ticket):
- """Commences the transmission loop sending tickets.
-
- Args:
- ticket: A ticket to be sent to the other side of the operation.
- """
- def transmit(ticket):
- while True:
- transmission_outcome = callable_util.call_logging_exceptions(
- self._callback, _TRANSMISSION_EXCEPTION_LOG_MESSAGE, ticket)
- if transmission_outcome.exception is None:
- with self._lock:
- complete, ticket = self._next_ticket()
- if ticket is None:
- if complete:
- self._termination_manager.transmission_complete()
- self._transmitting = False
- return
- else:
- with self._lock:
- self._emissions = None
- self._termination_manager.abort(
- interfaces.Outcome.TRANSMISSION_FAILURE)
- self._ingestion_manager.abort()
- self._expiration_manager.abort()
- self._transmitting = False
- return
-
- self._pool.submit(callable_util.with_exceptions_logged(
- transmit, _constants.INTERNAL_ERROR_LOG_MESSAGE), ticket)
- self._transmitting = True
-
- def inmit(self, emission, complete):
- """See _interfaces.TransmissionManager.inmit for specification."""
- if self._emissions is not None and self._outcome is None:
- self._emission_complete = complete
- if self._transmitting:
- self._emissions.append(emission)
- else:
- self._transmit(self._lead_ticket(emission, complete))
-
- def abort(self, outcome):
- """See _interfaces.TransmissionManager.abort for specification."""
- if self._emissions is not None and self._outcome is None:
- self._outcome = outcome
- if not self._transmitting:
- ticket = self._abortive_response_ticket(outcome)
- self._emissions = None
- if ticket is not None:
- self._transmit(ticket)
-
-
-def front_transmission_manager(
- lock, pool, callback, operation_id, name, subscription_kind, trace_id,
- timeout, termination_manager):
- """Creates a TransmissionManager appropriate for front-side use.
-
- Args:
- lock: The operation-servicing-wide lock object.
- pool: A thread pool in which the work of transmitting tickets will be
- performed.
- callback: A callable that accepts tickets and sends them to the other side
- of the operation.
- operation_id: The operation's ID.
- name: The name of the operation.
- subscription_kind: An interfaces.ServicedSubscription.Kind value
- describing the interest the front has in tickets sent from the back.
- trace_id: A uuid.UUID identifying a set of related operations to which
- this operation belongs.
- timeout: A length of time in seconds to allow for the entire operation.
- termination_manager: The _interfaces.TerminationManager associated with
- this operation.
-
- Returns:
- A TransmissionManager appropriate for front-side use.
- """
- return _TransmittingTransmissionManager(
- lock, pool, callback, operation_id, _FrontTicketizer(
- name, subscription_kind, trace_id, timeout),
- termination_manager)
-
-
-def back_transmission_manager(
- lock, pool, callback, operation_id, termination_manager,
- subscription_kind):
- """Creates a TransmissionManager appropriate for back-side use.
-
- Args:
- lock: The operation-servicing-wide lock object.
- pool: A thread pool in which the work of transmitting tickets will be
- performed.
- callback: A callable that accepts tickets and sends them to the other side
- of the operation.
- operation_id: The operation's ID.
- termination_manager: The _interfaces.TerminationManager associated with
- this operation.
- subscription_kind: An interfaces.ServicedSubscription.Kind value
- describing the interest the front has in tickets sent from the back.
-
- Returns:
- A TransmissionManager appropriate for back-side use.
- """
- if subscription_kind is interfaces.ServicedSubscription.Kind.NONE:
- return _EmptyTransmissionManager()
- else:
- return _TransmittingTransmissionManager(
- lock, pool, callback, operation_id, _BackTicketizer(),
- termination_manager)
diff --git a/src/python/grpcio/grpc/framework/base/implementations.py b/src/python/grpcio/grpc/framework/base/implementations.py
deleted file mode 100644
index 5656f9f981..0000000000
--- a/src/python/grpcio/grpc/framework/base/implementations.py
+++ /dev/null
@@ -1,77 +0,0 @@
-# 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.
-
-"""Entry points into the ticket-exchange-based base layer implementation."""
-
-# interfaces is referenced from specification in this module.
-from grpc.framework.base import _ends
-from grpc.framework.base import interfaces # pylint: disable=unused-import
-
-
-def front_link(work_pool, transmission_pool, utility_pool):
- """Factory function for creating interfaces.FrontLinks.
-
- Args:
- work_pool: A thread pool to be used for doing work within the created
- FrontLink object.
- transmission_pool: A thread pool to be used within the created FrontLink
- object for transmitting values to a joined RearLink object.
- utility_pool: A thread pool to be used within the created FrontLink object
- for utility tasks.
-
- Returns:
- An interfaces.FrontLink.
- """
- return _ends.FrontLink(work_pool, transmission_pool, utility_pool)
-
-
-def back_link(
- servicer, work_pool, transmission_pool, utility_pool, default_timeout,
- maximum_timeout):
- """Factory function for creating interfaces.BackLinks.
-
- Args:
- servicer: An interfaces.Servicer for servicing operations.
- work_pool: A thread pool to be used for doing work within the created
- BackLink object.
- transmission_pool: A thread pool to be used within the created BackLink
- object for transmitting values to a joined ForeLink object.
- utility_pool: A thread pool to be used within the created BackLink object
- for utility tasks.
- default_timeout: A length of time in seconds to be used as the default
- time alloted for a single operation.
- maximum_timeout: A length of time in seconds to be used as the maximum
- time alloted for a single operation.
-
- Returns:
- An interfaces.BackLink.
- """
- return _ends.BackLink(
- servicer, work_pool, transmission_pool, utility_pool, default_timeout,
- maximum_timeout)
diff --git a/src/python/grpcio/grpc/framework/base/in_memory.py b/src/python/grpcio/grpc/framework/base/in_memory.py
deleted file mode 100644
index c92d0bc663..0000000000
--- a/src/python/grpcio/grpc/framework/base/in_memory.py
+++ /dev/null
@@ -1,108 +0,0 @@
-# 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.
-
-"""In-memory implementations of base layer interfaces."""
-
-import threading
-
-from grpc.framework.base import _constants
-from grpc.framework.base import interfaces
-from grpc.framework.foundation import callable_util
-
-
-class _Serializer(object):
- """A utility for serializing values that may arrive concurrently."""
-
- def __init__(self, pool):
- self._lock = threading.Lock()
- self._pool = pool
- self._sink = None
- self._spinning = False
- self._values = []
-
- def _spin(self, sink, value):
- while True:
- sink(value)
- with self._lock:
- if self._sink is None or not self._values:
- self._spinning = False
- return
- else:
- sink, value = self._sink, self._values.pop(0)
-
- def set_sink(self, sink):
- with self._lock:
- self._sink = sink
- if sink is not None and self._values and not self._spinning:
- self._spinning = True
- self._pool.submit(
- callable_util.with_exceptions_logged(
- self._spin, _constants.INTERNAL_ERROR_LOG_MESSAGE),
- sink, self._values.pop(0))
-
- def add_value(self, value):
- with self._lock:
- if self._sink and not self._spinning:
- self._spinning = True
- self._pool.submit(
- callable_util.with_exceptions_logged(
- self._spin, _constants.INTERNAL_ERROR_LOG_MESSAGE),
- self._sink, value)
- else:
- self._values.append(value)
-
-
-class Link(interfaces.ForeLink, interfaces.RearLink):
- """A trivial implementation of interfaces.ForeLink and interfaces.RearLink."""
-
- def __init__(self, pool):
- """Constructor.
-
- Args:
- pool: A thread pool to be used for serializing ticket exchange in each
- direction.
- """
- self._front_to_back = _Serializer(pool)
- self._back_to_front = _Serializer(pool)
-
- def join_fore_link(self, fore_link):
- """See interfaces.RearLink.join_fore_link for specification."""
- self._back_to_front.set_sink(fore_link.accept_back_to_front_ticket)
-
- def join_rear_link(self, rear_link):
- """See interfaces.ForeLink.join_rear_link for specification."""
- self._front_to_back.set_sink(rear_link.accept_front_to_back_ticket)
-
- def accept_front_to_back_ticket(self, ticket):
- """See interfaces.ForeLink.accept_front_to_back_ticket for specification."""
- self._front_to_back.add_value(ticket)
-
- def accept_back_to_front_ticket(self, ticket):
- """See interfaces.RearLink.accept_back_to_front_ticket for specification."""
- self._back_to_front.add_value(ticket)
diff --git a/src/python/grpcio/grpc/framework/base/interfaces.py b/src/python/grpcio/grpc/framework/base/interfaces.py
deleted file mode 100644
index 995b51cd5b..0000000000
--- a/src/python/grpcio/grpc/framework/base/interfaces.py
+++ /dev/null
@@ -1,353 +0,0 @@
-# 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 defined and used by the base layer of RPC Framework."""
-
-import abc
-import collections
-import enum
-
-import six
-
-# stream is referenced from specification in this module.
-from grpc.framework.foundation import stream # pylint: disable=unused-import
-
-
-@enum.unique
-class Outcome(enum.Enum):
- """Operation outcomes."""
-
- COMPLETED = 'completed'
- CANCELLED = 'cancelled'
- EXPIRED = 'expired'
- RECEPTION_FAILURE = 'reception failure'
- TRANSMISSION_FAILURE = 'transmission failure'
- SERVICER_FAILURE = 'servicer failure'
- SERVICED_FAILURE = 'serviced failure'
-
-
-class OperationContext(six.with_metaclass(abc.ABCMeta)):
- """Provides operation-related information and action.
-
- Attributes:
- trace_id: A uuid.UUID identifying a particular set of related operations.
- """
-
- @abc.abstractmethod
- def is_active(self):
- """Describes whether the operation is active or has terminated."""
- raise NotImplementedError()
-
- @abc.abstractmethod
- def add_termination_callback(self, callback):
- """Adds a function to be called upon operation termination.
-
- Args:
- callback: A callable that will be passed an Outcome value.
- """
- raise NotImplementedError()
-
- @abc.abstractmethod
- def time_remaining(self):
- """Describes the length of allowed time remaining for the operation.
-
- Returns:
- A nonnegative float indicating the length of allowed time in seconds
- remaining for the operation to complete before it is considered to have
- timed out.
- """
- raise NotImplementedError()
-
- @abc.abstractmethod
- def fail(self, exception):
- """Indicates that the operation has failed.
-
- Args:
- exception: An exception germane to the operation failure. May be None.
- """
- raise NotImplementedError()
-
-
-class Servicer(six.with_metaclass(abc.ABCMeta)):
- """Interface for service implementations."""
-
- @abc.abstractmethod
- def service(self, name, context, output_consumer):
- """Services an operation.
-
- Args:
- name: The name of the operation.
- context: A ServicerContext object affording contextual information and
- actions.
- output_consumer: A stream.Consumer that will accept output values of
- the operation.
-
- Returns:
- A stream.Consumer that will accept input values for the operation.
-
- Raises:
- exceptions.NoSuchMethodError: If this Servicer affords no method with the
- given name.
- abandonment.Abandoned: If the operation has been aborted and there no
- longer is any reason to service the operation.
- """
- raise NotImplementedError()
-
-
-class Operation(six.with_metaclass(abc.ABCMeta)):
- """Representation of an in-progress operation.
-
- Attributes:
- consumer: A stream.Consumer into which payloads constituting the operation's
- input may be passed.
- context: An OperationContext affording information and action about the
- operation.
- """
-
- @abc.abstractmethod
- def cancel(self):
- """Cancels this operation."""
- raise NotImplementedError()
-
-
-class ServicedIngestor(six.with_metaclass(abc.ABCMeta)):
- """Responsible for accepting the result of an operation."""
-
- @abc.abstractmethod
- def consumer(self, operation_context):
- """Affords a consumer to which operation results will be passed.
-
- Args:
- operation_context: An OperationContext object for the current operation.
-
- Returns:
- A stream.Consumer to which the results of the current operation will be
- passed.
-
- Raises:
- abandonment.Abandoned: If the operation has been aborted and there no
- longer is any reason to service the operation.
- """
- raise NotImplementedError()
-
-
-class ServicedSubscription(six.with_metaclass(abc.ABCMeta)):
- """A sum type representing a serviced's interest in an operation.
-
- Attributes:
- kind: A Kind value.
- ingestor: A ServicedIngestor. Must be present if kind is Kind.FULL. Must
- be None if kind is Kind.TERMINATION_ONLY or Kind.NONE.
- """
-
- @enum.unique
- class Kind(enum.Enum):
- """Kinds of subscription."""
-
- FULL = 'full'
- TERMINATION_ONLY = 'termination only'
- NONE = 'none'
-
-
-class End(six.with_metaclass(abc.ABCMeta)):
- """Common type for entry-point objects on both sides of an operation."""
-
- @abc.abstractmethod
- def operation_stats(self):
- """Reports the number of terminated operations broken down by outcome.
-
- Returns:
- A dictionary from Outcome value to an integer identifying the number
- of operations that terminated with that outcome.
- """
- raise NotImplementedError()
-
- @abc.abstractmethod
- def add_idle_action(self, action):
- """Adds an action to be called when this End has no ongoing operations.
-
- Args:
- action: A callable that accepts no arguments.
- """
- raise NotImplementedError()
-
-
-class Front(six.with_metaclass(abc.ABCMeta, End)):
- """Clientish objects that afford the invocation of operations."""
-
- @abc.abstractmethod
- def operate(
- self, name, payload, complete, timeout, subscription, trace_id):
- """Commences an operation.
-
- Args:
- name: The name of the method invoked for the operation.
- payload: An initial payload for the operation. May be None.
- complete: A boolean indicating whether or not additional payloads to be
- sent to the servicer may be supplied after this call.
- timeout: A length of time in seconds to allow for the operation.
- subscription: A ServicedSubscription for the operation.
- trace_id: A uuid.UUID identifying a set of related operations to which
- this operation belongs.
-
- Returns:
- An Operation object affording information and action about the operation
- in progress.
- """
- raise NotImplementedError()
-
-
-class Back(six.with_metaclass(abc.ABCMeta, End)):
- """Serverish objects that perform the work of operations."""
-
-
-class FrontToBackTicket(
- collections.namedtuple(
- 'FrontToBackTicket',
- ['operation_id', 'sequence_number', 'kind', 'name', 'subscription',
- 'trace_id', 'payload', 'timeout'])):
- """A sum type for all values sent from a front to a back.
-
- Attributes:
- operation_id: A unique-with-respect-to-equality hashable object identifying
- a particular operation.
- sequence_number: A zero-indexed integer sequence number identifying the
- ticket's place among all the tickets sent from front to back for this
- particular operation. Must be zero if kind is Kind.COMMENCEMENT or
- Kind.ENTIRE. Must be positive for any other kind.
- kind: A Kind value describing the overall kind of ticket.
- name: The name of an operation. Must be present if kind is Kind.COMMENCEMENT
- or Kind.ENTIRE. Must be None for any other kind.
- subscription: An ServicedSubscription.Kind value describing the interest
- the front has in tickets sent from the back. Must be present if
- kind is Kind.COMMENCEMENT or Kind.ENTIRE. Must be None for any other kind.
- trace_id: A uuid.UUID identifying a set of related operations to which this
- operation belongs. May be None.
- payload: A customer payload object. Must be present if kind is
- Kind.CONTINUATION. Must be None if kind is Kind.CANCELLATION. May be None
- for any other kind.
- timeout: An optional length of time (measured from the beginning of the
- operation) to allow for the entire operation. If None, a default value on
- the back will be used. If present and excessively large, the back may
- limit the operation to a smaller duration of its choice. May be present
- for any ticket kind; setting a value on a later ticket allows fronts
- to request time extensions (or even time reductions!) on in-progress
- operations.
- """
-
- @enum.unique
- class Kind(enum.Enum):
- """Identifies the overall kind of a FrontToBackTicket."""
-
- COMMENCEMENT = 'commencement'
- CONTINUATION = 'continuation'
- COMPLETION = 'completion'
- ENTIRE = 'entire'
- CANCELLATION = 'cancellation'
- EXPIRATION = 'expiration'
- SERVICER_FAILURE = 'servicer failure'
- SERVICED_FAILURE = 'serviced failure'
- RECEPTION_FAILURE = 'reception failure'
- TRANSMISSION_FAILURE = 'transmission failure'
-
-
-class BackToFrontTicket(
- collections.namedtuple(
- 'BackToFrontTicket',
- ['operation_id', 'sequence_number', 'kind', 'payload'])):
- """A sum type for all values sent from a back to a front.
-
- Attributes:
- operation_id: A unique-with-respect-to-equality hashable object identifying
- a particular operation.
- sequence_number: A zero-indexed integer sequence number identifying the
- ticket's place among all the tickets sent from back to front for this
- particular operation.
- kind: A Kind value describing the overall kind of ticket.
- payload: A customer payload object. Must be present if kind is
- Kind.CONTINUATION. May be None if kind is Kind.COMPLETION. Must be None
- otherwise.
- """
-
- @enum.unique
- class Kind(enum.Enum):
- """Identifies the overall kind of a BackToFrontTicket."""
-
- CONTINUATION = 'continuation'
- COMPLETION = 'completion'
- CANCELLATION = 'cancellation'
- EXPIRATION = 'expiration'
- SERVICER_FAILURE = 'servicer failure'
- SERVICED_FAILURE = 'serviced failure'
- RECEPTION_FAILURE = 'reception failure'
- TRANSMISSION_FAILURE = 'transmission failure'
-
-
-class ForeLink(six.with_metaclass(abc.ABCMeta)):
- """Accepts back-to-front tickets and emits front-to-back tickets."""
-
- @abc.abstractmethod
- def accept_back_to_front_ticket(self, ticket):
- """Accept a BackToFrontTicket.
-
- Args:
- ticket: Any BackToFrontTicket.
- """
- raise NotImplementedError()
-
- @abc.abstractmethod
- def join_rear_link(self, rear_link):
- """Mates this object with a peer with which it will exchange tickets."""
- raise NotImplementedError()
-
-
-class RearLink(six.with_metaclass(abc.ABCMeta)):
- """Accepts front-to-back tickets and emits back-to-front tickets."""
-
- @abc.abstractmethod
- def accept_front_to_back_ticket(self, ticket):
- """Accepts a FrontToBackTicket.
-
- Args:
- ticket: Any FrontToBackTicket.
- """
- raise NotImplementedError()
-
- @abc.abstractmethod
- def join_fore_link(self, fore_link):
- """Mates this object with a peer with which it will exchange tickets."""
- raise NotImplementedError()
-
-
-class FrontLink(six.with_metaclass(abc.ABCMeta, Front, ForeLink)):
- """Clientish objects that operate by sending and receiving tickets."""
-
-
-class BackLink(six.with_metaclass(abc.ABCMeta, Back, RearLink)):
- """Serverish objects that operate by sending and receiving tickets."""
diff --git a/src/python/grpcio/grpc/framework/base/util.py b/src/python/grpcio/grpc/framework/base/util.py
deleted file mode 100644
index c832c826cf..0000000000
--- a/src/python/grpcio/grpc/framework/base/util.py
+++ /dev/null
@@ -1,94 +0,0 @@
-# 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 helpful for working with the base layer of RPC Framework."""
-
-import collections
-import threading
-
-from grpc.framework.base import interfaces
-
-
-class _ServicedSubscription(
- collections.namedtuple('_ServicedSubscription', ['kind', 'ingestor']),
- interfaces.ServicedSubscription):
- """See interfaces.ServicedSubscription for specification."""
-
-_NONE_SUBSCRIPTION = _ServicedSubscription(
- interfaces.ServicedSubscription.Kind.NONE, None)
-_TERMINATION_ONLY_SUBSCRIPTION = _ServicedSubscription(
- interfaces.ServicedSubscription.Kind.TERMINATION_ONLY, None)
-
-
-def none_serviced_subscription():
- """Creates a "none" interfaces.ServicedSubscription object.
-
- Returns:
- An interfaces.ServicedSubscription indicating no subscription to an
- operation's results (such as would be the case for a fire-and-forget
- operation invocation).
- """
- return _NONE_SUBSCRIPTION
-
-
-def termination_only_serviced_subscription():
- """Creates a "termination only" interfaces.ServicedSubscription object.
-
- Returns:
- An interfaces.ServicedSubscription indicating that the front-side customer
- is interested only in the overall termination outcome of the operation
- (such as completion or expiration) and would ignore the actual results of
- the operation.
- """
- return _TERMINATION_ONLY_SUBSCRIPTION
-
-
-def full_serviced_subscription(ingestor):
- """Creates a "full" interfaces.ServicedSubscription object.
-
- Args:
- ingestor: An interfaces.ServicedIngestor.
-
- Returns:
- An interfaces.ServicedSubscription object indicating a full
- subscription.
- """
- return _ServicedSubscription(
- interfaces.ServicedSubscription.Kind.FULL, ingestor)
-
-
-def wait_for_idle(end):
- """Waits for an interfaces.End to complete all operations.
-
- Args:
- end: Any interfaces.End.
- """
- event = threading.Event()
- end.add_idle_action(event.set)
- event.wait()
diff --git a/src/python/grpcio/grpc/framework/face/__init__.py b/src/python/grpcio/grpc/framework/face/__init__.py
deleted file mode 100644
index bff74be2c7..0000000000
--- a/src/python/grpcio/grpc/framework/face/__init__.py
+++ /dev/null
@@ -1,35 +0,0 @@
-# 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.
-
-import warnings
-
-warnings.simplefilter('always', DeprecationWarning)
-warnings.warn('the alpha API (includes this package) is deprecated, '
- 'unmaintained, and no longer tested. Please migrate to the beta '
- 'API.', DeprecationWarning, stacklevel=2)
diff --git a/src/python/grpcio/grpc/framework/face/_calls.py b/src/python/grpcio/grpc/framework/face/_calls.py
deleted file mode 100644
index 87edeb0f0e..0000000000
--- a/src/python/grpcio/grpc/framework/face/_calls.py
+++ /dev/null
@@ -1,422 +0,0 @@
-# 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.
-
-"""Utility functions for invoking RPCs."""
-
-import sys
-import threading
-
-from grpc.framework.base import interfaces as base_interfaces
-from grpc.framework.base import util as base_util
-from grpc.framework.face import _control
-from grpc.framework.face import interfaces
-from grpc.framework.foundation import callable_util
-from grpc.framework.foundation import future
-
-_ITERATOR_EXCEPTION_LOG_MESSAGE = 'Exception iterating over requests!'
-_DONE_CALLBACK_LOG_MESSAGE = 'Exception calling Future "done" callback!'
-
-
-class _RendezvousServicedIngestor(base_interfaces.ServicedIngestor):
-
- def __init__(self, rendezvous):
- self._rendezvous = rendezvous
-
- def consumer(self, operation_context):
- return self._rendezvous
-
-
-class _EventServicedIngestor(base_interfaces.ServicedIngestor):
-
- def __init__(self, result_consumer, abortion_callback):
- self._result_consumer = result_consumer
- self._abortion_callback = abortion_callback
-
- def consumer(self, operation_context):
- operation_context.add_termination_callback(
- _control.as_operation_termination_callback(self._abortion_callback))
- return self._result_consumer
-
-
-def _rendezvous_subscription(rendezvous):
- return base_util.full_serviced_subscription(
- _RendezvousServicedIngestor(rendezvous))
-
-
-def _unary_event_subscription(completion_callback, abortion_callback):
- return base_util.full_serviced_subscription(
- _EventServicedIngestor(
- _control.UnaryConsumer(completion_callback), abortion_callback))
-
-
-def _stream_event_subscription(result_consumer, abortion_callback):
- return base_util.full_serviced_subscription(
- _EventServicedIngestor(result_consumer, abortion_callback))
-
-
-# NOTE(nathaniel): This class has some extremely special semantics around
-# cancellation that allow it to be used by both "blocking" APIs and "futures"
-# APIs.
-#
-# Since futures.Future defines its own exception for cancellation, we want these
-# objects, when returned by methods of a returning-Futures-from-other-methods
-# object, to raise the same exception for cancellation. But that's weird in a
-# blocking API - why should this object, also returned by methods of blocking
-# APIs, raise exceptions from the "future" module? Should we do something like
-# have this class be parameterized by the type of exception that it raises in
-# cancellation circumstances?
-#
-# We don't have to take such a dramatic step: since blocking APIs define no
-# cancellation semantics whatsoever, there is no supported way for
-# blocking-API-users of these objects to cancel RPCs, and thus no supported way
-# for them to see an exception the type of which would be weird to them.
-#
-# Bonus: in both blocking and futures APIs, this object still properly raises
-# exceptions.CancellationError for any *server-side cancellation* of an RPC.
-class _OperationCancellableIterator(interfaces.CancellableIterator):
- """An interfaces.CancellableIterator for response-streaming operations."""
-
- def __init__(self, rendezvous, operation):
- self._lock = threading.Lock()
- self._rendezvous = rendezvous
- self._operation = operation
- self._cancelled = False
-
- def __iter__(self):
- return self
-
- def next(self):
- with self._lock:
- if self._cancelled:
- raise future.CancelledError()
- return next(self._rendezvous)
-
- def cancel(self):
- with self._lock:
- self._cancelled = True
- self._operation.cancel()
- self._rendezvous.set_outcome(base_interfaces.Outcome.CANCELLED)
-
-
-class _OperationFuture(future.Future):
- """A future.Future interface to an operation."""
-
- def __init__(self, rendezvous, operation):
- self._condition = threading.Condition()
- self._rendezvous = rendezvous
- self._operation = operation
-
- self._cancelled = False
- self._computed = False
- self._payload = None
- self._exception = None
- self._traceback = None
- self._callbacks = []
-
- def cancel(self):
- """See future.Future.cancel for specification."""
- with self._condition:
- if not self._cancelled and not self._computed:
- self._operation.cancel()
- self._cancelled = True
- self._condition.notify_all()
- return False
-
- def cancelled(self):
- """See future.Future.cancelled for specification."""
- with self._condition:
- return self._cancelled
-
- def running(self):
- """See future.Future.running for specification."""
- with self._condition:
- return not self._cancelled and not self._computed
-
- def done(self):
- """See future.Future.done for specification."""
- with self._condition:
- return self._cancelled or self._computed
-
- def result(self, timeout=None):
- """See future.Future.result for specification."""
- with self._condition:
- if self._cancelled:
- raise future.CancelledError()
- if self._computed:
- if self._payload is None:
- raise self._exception # pylint: disable=raising-bad-type
- else:
- return self._payload
-
- condition = threading.Condition()
- def notify_condition(unused_future):
- with condition:
- condition.notify()
- self._callbacks.append(notify_condition)
-
- with condition:
- condition.wait(timeout=timeout)
-
- with self._condition:
- if self._cancelled:
- raise future.CancelledError()
- elif self._computed:
- if self._payload is None:
- raise self._exception # pylint: disable=raising-bad-type
- else:
- return self._payload
- else:
- raise future.TimeoutError()
-
- def exception(self, timeout=None):
- """See future.Future.exception for specification."""
- with self._condition:
- if self._cancelled:
- raise future.CancelledError()
- if self._computed:
- return self._exception
-
- condition = threading.Condition()
- def notify_condition(unused_future):
- with condition:
- condition.notify()
- self._callbacks.append(notify_condition)
-
- with condition:
- condition.wait(timeout=timeout)
-
- with self._condition:
- if self._cancelled:
- raise future.CancelledError()
- elif self._computed:
- return self._exception
- else:
- raise future.TimeoutError()
-
- def traceback(self, timeout=None):
- """See future.Future.traceback for specification."""
- with self._condition:
- if self._cancelled:
- raise future.CancelledError()
- if self._computed:
- return self._traceback
-
- condition = threading.Condition()
- def notify_condition(unused_future):
- with condition:
- condition.notify()
- self._callbacks.append(notify_condition)
-
- with condition:
- condition.wait(timeout=timeout)
-
- with self._condition:
- if self._cancelled:
- raise future.CancelledError()
- elif self._computed:
- return self._traceback
- else:
- raise future.TimeoutError()
-
- def add_done_callback(self, fn):
- """See future.Future.add_done_callback for specification."""
- with self._condition:
- if self._callbacks is not None:
- self._callbacks.append(fn)
- return
-
- callable_util.call_logging_exceptions(fn, _DONE_CALLBACK_LOG_MESSAGE, self)
-
- def on_operation_termination(self, operation_outcome):
- """Indicates to this object that the operation has terminated.
-
- Args:
- operation_outcome: A base_interfaces.Outcome value indicating the
- outcome of the operation.
- """
- with self._condition:
- cancelled = self._cancelled
- if cancelled:
- callbacks = list(self._callbacks)
- self._callbacks = None
- else:
- rendezvous = self._rendezvous
-
- if not cancelled:
- payload = None
- exception = None
- traceback = None
- if operation_outcome == base_interfaces.Outcome.COMPLETED:
- try:
- payload = next(rendezvous)
- except Exception as e: # pylint: disable=broad-except
- exception = e
- traceback = sys.exc_info()[2]
- else:
- try:
- # We raise and then immediately catch in order to create a traceback.
- raise _control.abortion_outcome_to_exception(operation_outcome)
- except Exception as e: # pylint: disable=broad-except
- exception = e
- traceback = sys.exc_info()[2]
- with self._condition:
- if not self._cancelled:
- self._computed = True
- self._payload = payload
- self._exception = exception
- self._traceback = traceback
- callbacks = list(self._callbacks)
- self._callbacks = None
-
- for callback in callbacks:
- callable_util.call_logging_exceptions(
- callback, _DONE_CALLBACK_LOG_MESSAGE, self)
-
-
-class _Call(interfaces.Call):
-
- def __init__(self, operation):
- self._operation = operation
- self.context = _control.RpcContext(operation.context)
-
- def cancel(self):
- self._operation.cancel()
-
-
-def blocking_value_in_value_out(front, name, payload, timeout, trace_id):
- """Services in a blocking fashion a value-in value-out servicer method."""
- rendezvous = _control.Rendezvous()
- subscription = _rendezvous_subscription(rendezvous)
- operation = front.operate(
- name, payload, True, timeout, subscription, trace_id)
- operation.context.add_termination_callback(rendezvous.set_outcome)
- return next(rendezvous)
-
-
-def future_value_in_value_out(front, name, payload, timeout, trace_id):
- """Services a value-in value-out servicer method by returning a Future."""
- rendezvous = _control.Rendezvous()
- subscription = _rendezvous_subscription(rendezvous)
- operation = front.operate(
- name, payload, True, timeout, subscription, trace_id)
- operation.context.add_termination_callback(rendezvous.set_outcome)
- operation_future = _OperationFuture(rendezvous, operation)
- operation.context.add_termination_callback(
- operation_future.on_operation_termination)
- return operation_future
-
-
-def inline_value_in_stream_out(front, name, payload, timeout, trace_id):
- """Services a value-in stream-out servicer method."""
- rendezvous = _control.Rendezvous()
- subscription = _rendezvous_subscription(rendezvous)
- operation = front.operate(
- name, payload, True, timeout, subscription, trace_id)
- operation.context.add_termination_callback(rendezvous.set_outcome)
- return _OperationCancellableIterator(rendezvous, operation)
-
-
-def blocking_stream_in_value_out(
- front, name, payload_iterator, timeout, trace_id):
- """Services in a blocking fashion a stream-in value-out servicer method."""
- rendezvous = _control.Rendezvous()
- subscription = _rendezvous_subscription(rendezvous)
- operation = front.operate(name, None, False, timeout, subscription, trace_id)
- operation.context.add_termination_callback(rendezvous.set_outcome)
- for payload in payload_iterator:
- operation.consumer.consume(payload)
- operation.consumer.terminate()
- return next(rendezvous)
-
-
-def future_stream_in_value_out(
- front, name, payload_iterator, timeout, trace_id, pool):
- """Services a stream-in value-out servicer method by returning a Future."""
- rendezvous = _control.Rendezvous()
- subscription = _rendezvous_subscription(rendezvous)
- operation = front.operate(name, None, False, timeout, subscription, trace_id)
- operation.context.add_termination_callback(rendezvous.set_outcome)
- pool.submit(
- callable_util.with_exceptions_logged(
- _control.pipe_iterator_to_consumer, _ITERATOR_EXCEPTION_LOG_MESSAGE),
- payload_iterator, operation.consumer, lambda: True, True)
- operation_future = _OperationFuture(rendezvous, operation)
- operation.context.add_termination_callback(
- operation_future.on_operation_termination)
- return operation_future
-
-
-def inline_stream_in_stream_out(
- front, name, payload_iterator, timeout, trace_id, pool):
- """Services a stream-in stream-out servicer method."""
- rendezvous = _control.Rendezvous()
- subscription = _rendezvous_subscription(rendezvous)
- operation = front.operate(name, None, False, timeout, subscription, trace_id)
- operation.context.add_termination_callback(rendezvous.set_outcome)
- pool.submit(
- callable_util.with_exceptions_logged(
- _control.pipe_iterator_to_consumer, _ITERATOR_EXCEPTION_LOG_MESSAGE),
- payload_iterator, operation.consumer, lambda: True, True)
- return _OperationCancellableIterator(rendezvous, operation)
-
-
-def event_value_in_value_out(
- front, name, payload, completion_callback, abortion_callback, timeout,
- trace_id):
- subscription = _unary_event_subscription(
- completion_callback, abortion_callback)
- operation = front.operate(
- name, payload, True, timeout, subscription, trace_id)
- return _Call(operation)
-
-
-def event_value_in_stream_out(
- front, name, payload, result_payload_consumer, abortion_callback, timeout,
- trace_id):
- subscription = _stream_event_subscription(
- result_payload_consumer, abortion_callback)
- operation = front.operate(
- name, payload, True, timeout, subscription, trace_id)
- return _Call(operation)
-
-
-def event_stream_in_value_out(
- front, name, completion_callback, abortion_callback, timeout, trace_id):
- subscription = _unary_event_subscription(
- completion_callback, abortion_callback)
- operation = front.operate(name, None, False, timeout, subscription, trace_id)
- return _Call(operation), operation.consumer
-
-
-def event_stream_in_stream_out(
- front, name, result_payload_consumer, abortion_callback, timeout, trace_id):
- subscription = _stream_event_subscription(
- result_payload_consumer, abortion_callback)
- operation = front.operate(name, None, False, timeout, subscription, trace_id)
- return _Call(operation), operation.consumer
diff --git a/src/python/grpcio/grpc/framework/face/_control.py b/src/python/grpcio/grpc/framework/face/_control.py
deleted file mode 100644
index 539615efa1..0000000000
--- a/src/python/grpcio/grpc/framework/face/_control.py
+++ /dev/null
@@ -1,201 +0,0 @@
-# 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.
-
-"""State and behavior for translating between sync and async control flow."""
-
-import threading
-
-from grpc.framework.base import interfaces as base_interfaces
-from grpc.framework.face import exceptions
-from grpc.framework.face import interfaces
-from grpc.framework.foundation import abandonment
-from grpc.framework.foundation import stream
-
-INTERNAL_ERROR_LOG_MESSAGE = ':-( RPC Framework (Face) Internal Error! :-('
-
-_OPERATION_OUTCOME_TO_RPC_ABORTION = {
- base_interfaces.Outcome.CANCELLED: interfaces.Abortion.CANCELLED,
- base_interfaces.Outcome.EXPIRED: interfaces.Abortion.EXPIRED,
- base_interfaces.Outcome.RECEPTION_FAILURE:
- interfaces.Abortion.NETWORK_FAILURE,
- base_interfaces.Outcome.TRANSMISSION_FAILURE:
- interfaces.Abortion.NETWORK_FAILURE,
- base_interfaces.Outcome.SERVICED_FAILURE:
- interfaces.Abortion.SERVICED_FAILURE,
- base_interfaces.Outcome.SERVICER_FAILURE:
- interfaces.Abortion.SERVICER_FAILURE,
-}
-
-
-def _as_operation_termination_callback(rpc_abortion_callback):
- def operation_termination_callback(operation_outcome):
- rpc_abortion = _OPERATION_OUTCOME_TO_RPC_ABORTION.get(
- operation_outcome, None)
- if rpc_abortion is not None:
- rpc_abortion_callback(rpc_abortion)
- return operation_termination_callback
-
-
-def _abortion_outcome_to_exception(abortion_outcome):
- if abortion_outcome == base_interfaces.Outcome.CANCELLED:
- return exceptions.CancellationError()
- elif abortion_outcome == base_interfaces.Outcome.EXPIRED:
- return exceptions.ExpirationError()
- elif abortion_outcome == base_interfaces.Outcome.SERVICER_FAILURE:
- return exceptions.ServicerError()
- elif abortion_outcome == base_interfaces.Outcome.SERVICED_FAILURE:
- return exceptions.ServicedError()
- else:
- return exceptions.NetworkError()
-
-
-class UnaryConsumer(stream.Consumer):
- """A stream.Consumer that should only ever be passed one value."""
-
- def __init__(self, on_termination):
- self._on_termination = on_termination
- self._value = None
-
- def consume(self, value):
- self._value = value
-
- def terminate(self):
- self._on_termination(self._value)
-
- def consume_and_terminate(self, value):
- self._on_termination(value)
-
-
-class Rendezvous(stream.Consumer):
- """A rendez-vous with stream.Consumer and iterator interfaces."""
-
- def __init__(self):
- self._condition = threading.Condition()
- self._values = []
- self._values_completed = False
- self._abortion = None
-
- def consume(self, value):
- with self._condition:
- self._values.append(value)
- self._condition.notify()
-
- def terminate(self):
- with self._condition:
- self._values_completed = True
- self._condition.notify()
-
- def consume_and_terminate(self, value):
- with self._condition:
- self._values.append(value)
- self._values_completed = True
- self._condition.notify()
-
- def __iter__(self):
- return self
-
- def __next__(self):
- return self.next()
-
- def next(self):
- with self._condition:
- while ((self._abortion is None) and
- (not self._values) and
- (not self._values_completed)):
- self._condition.wait()
- if self._abortion is not None:
- raise _abortion_outcome_to_exception(self._abortion)
- elif self._values:
- return self._values.pop(0)
- elif self._values_completed:
- raise StopIteration()
- else:
- raise AssertionError('Unreachable code reached!')
-
- def set_outcome(self, outcome):
- with self._condition:
- if outcome is not base_interfaces.Outcome.COMPLETED:
- self._abortion = outcome
- self._condition.notify()
-
-
-class RpcContext(interfaces.RpcContext):
- """A wrapped base_interfaces.OperationContext."""
-
- def __init__(self, operation_context):
- self._operation_context = operation_context
-
- def is_active(self):
- return self._operation_context.is_active()
-
- def time_remaining(self):
- return self._operation_context.time_remaining()
-
- def add_abortion_callback(self, abortion_callback):
- self._operation_context.add_termination_callback(
- _as_operation_termination_callback(abortion_callback))
-
-
-def pipe_iterator_to_consumer(iterator, consumer, active, terminate):
- """Pipes values emitted from an iterator to a stream.Consumer.
-
- Args:
- iterator: An iterator from which values will be emitted.
- consumer: A stream.Consumer to which values will be passed.
- active: A no-argument callable that returns True if the work being done by
- this function is still valid and should not be abandoned and False if the
- work being done by this function should be abandoned.
- terminate: A boolean indicating whether or not this function should
- terminate the given consumer after passing to it all values emitted by the
- given iterator.
-
- Raises:
- abandonment.Abandoned: If this function quits early after seeing False
- returned by the active function passed to it.
- Exception: This function raises whatever exceptions are raised by iterating
- over the given iterator.
- """
- for element in iterator:
- if not active():
- raise abandonment.Abandoned()
-
- consumer.consume(element)
-
- if not active():
- raise abandonment.Abandoned()
- if terminate:
- consumer.terminate()
-
-
-def abortion_outcome_to_exception(abortion_outcome):
- return _abortion_outcome_to_exception(abortion_outcome)
-
-
-def as_operation_termination_callback(rpc_abortion_callback):
- return _as_operation_termination_callback(rpc_abortion_callback)
diff --git a/src/python/grpcio/grpc/framework/face/_service.py b/src/python/grpcio/grpc/framework/face/_service.py
deleted file mode 100644
index cdf413356a..0000000000
--- a/src/python/grpcio/grpc/framework/face/_service.py
+++ /dev/null
@@ -1,187 +0,0 @@
-# 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.
-
-"""Behaviors for servicing RPCs."""
-
-# base_interfaces and interfaces are referenced from specification in this
-# module.
-from grpc.framework.base import interfaces as base_interfaces # pylint: disable=unused-import
-from grpc.framework.face import _control
-from grpc.framework.face import exceptions
-from grpc.framework.face import interfaces # pylint: disable=unused-import
-from grpc.framework.foundation import abandonment
-from grpc.framework.foundation import callable_util
-from grpc.framework.foundation import stream
-from grpc.framework.foundation import stream_util
-
-
-class _ValueInStreamOutConsumer(stream.Consumer):
- """A stream.Consumer that maps inputs one-to-many onto outputs."""
-
- def __init__(self, behavior, context, downstream):
- """Constructor.
-
- Args:
- behavior: A callable that takes a single value and an
- interfaces.RpcContext and returns a generator of arbitrarily many
- values.
- context: An interfaces.RpcContext.
- downstream: A stream.Consumer to which to pass the values generated by the
- given behavior.
- """
- self._behavior = behavior
- self._context = context
- self._downstream = downstream
-
- def consume(self, value):
- _control.pipe_iterator_to_consumer(
- self._behavior(value, self._context), self._downstream,
- self._context.is_active, False)
-
- def terminate(self):
- self._downstream.terminate()
-
- def consume_and_terminate(self, value):
- _control.pipe_iterator_to_consumer(
- self._behavior(value, self._context), self._downstream,
- self._context.is_active, True)
-
-
-def _pool_wrap(behavior, operation_context):
- """Wraps an operation-related behavior so that it may be called in a pool.
-
- Args:
- behavior: A callable related to carrying out an operation.
- operation_context: A base_interfaces.OperationContext for the operation.
-
- Returns:
- A callable that when called carries out the behavior of the given callable
- and handles whatever exceptions it raises appropriately.
- """
- def translation(*args):
- try:
- behavior(*args)
- except (
- abandonment.Abandoned,
- exceptions.ExpirationError,
- exceptions.CancellationError,
- exceptions.ServicedError,
- exceptions.NetworkError) as e:
- if operation_context.is_active():
- operation_context.fail(e)
- except Exception as e:
- operation_context.fail(e)
- return callable_util.with_exceptions_logged(
- translation, _control.INTERNAL_ERROR_LOG_MESSAGE)
-
-
-def adapt_inline_value_in_value_out(method):
- def adaptation(response_consumer, operation_context):
- rpc_context = _control.RpcContext(operation_context)
- return stream_util.TransformingConsumer(
- lambda request: method(request, rpc_context), response_consumer)
- return adaptation
-
-
-def adapt_inline_value_in_stream_out(method):
- def adaptation(response_consumer, operation_context):
- rpc_context = _control.RpcContext(operation_context)
- return _ValueInStreamOutConsumer(method, rpc_context, response_consumer)
- return adaptation
-
-
-def adapt_inline_stream_in_value_out(method, pool):
- def adaptation(response_consumer, operation_context):
- rendezvous = _control.Rendezvous()
- operation_context.add_termination_callback(rendezvous.set_outcome)
- def in_pool_thread():
- response_consumer.consume_and_terminate(
- method(rendezvous, _control.RpcContext(operation_context)))
- pool.submit(_pool_wrap(in_pool_thread, operation_context))
- return rendezvous
- return adaptation
-
-
-def adapt_inline_stream_in_stream_out(method, pool):
- """Adapts an interfaces.InlineStreamInStreamOutMethod for use with Consumers.
-
- RPCs may be serviced by calling the return value of this function, passing
- request values to the stream.Consumer returned from that call, and receiving
- response values from the stream.Consumer passed to that call.
-
- Args:
- method: An interfaces.InlineStreamInStreamOutMethod.
- pool: A thread pool.
-
- Returns:
- A callable that takes a stream.Consumer and a
- base_interfaces.OperationContext and returns a stream.Consumer.
- """
- def adaptation(response_consumer, operation_context):
- rendezvous = _control.Rendezvous()
- operation_context.add_termination_callback(rendezvous.set_outcome)
- def in_pool_thread():
- _control.pipe_iterator_to_consumer(
- method(rendezvous, _control.RpcContext(operation_context)),
- response_consumer, operation_context.is_active, True)
- pool.submit(_pool_wrap(in_pool_thread, operation_context))
- return rendezvous
- return adaptation
-
-
-def adapt_event_value_in_value_out(method):
- def adaptation(response_consumer, operation_context):
- def on_payload(payload):
- method(
- payload, response_consumer.consume_and_terminate,
- _control.RpcContext(operation_context))
- return _control.UnaryConsumer(on_payload)
- return adaptation
-
-
-def adapt_event_value_in_stream_out(method):
- def adaptation(response_consumer, operation_context):
- def on_payload(payload):
- method(
- payload, response_consumer, _control.RpcContext(operation_context))
- return _control.UnaryConsumer(on_payload)
- return adaptation
-
-
-def adapt_event_stream_in_value_out(method):
- def adaptation(response_consumer, operation_context):
- rpc_context = _control.RpcContext(operation_context)
- return method(response_consumer.consume_and_terminate, rpc_context)
- return adaptation
-
-
-def adapt_event_stream_in_stream_out(method):
- def adaptation(response_consumer, operation_context):
- return method(response_consumer, _control.RpcContext(operation_context))
- return adaptation
diff --git a/src/python/grpcio/grpc/framework/face/demonstration.py b/src/python/grpcio/grpc/framework/face/demonstration.py
deleted file mode 100644
index f6b4b609ff..0000000000
--- a/src/python/grpcio/grpc/framework/face/demonstration.py
+++ /dev/null
@@ -1,118 +0,0 @@
-# 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.
-
-"""Demonstration-suitable implementation of the face layer of RPC Framework."""
-
-from grpc.framework.base import util as _base_util
-from grpc.framework.base import implementations as _base_implementations
-from grpc.framework.face import implementations
-from grpc.framework.foundation import logging_pool
-
-_POOL_SIZE_LIMIT = 5
-
-_MAXIMUM_TIMEOUT = 90
-
-
-class LinkedPair(object):
- """A Server and Stub that are linked to one another.
-
- Attributes:
- server: A Server.
- stub: A Stub.
- """
-
- def shut_down(self):
- """Shuts down this object and releases its resources."""
- raise NotImplementedError()
-
-
-class _LinkedPair(LinkedPair):
-
- def __init__(self, server, stub, front, back, pools):
- self.server = server
- self.stub = stub
- self._front = front
- self._back = back
- self._pools = pools
-
- def shut_down(self):
- _base_util.wait_for_idle(self._front)
- _base_util.wait_for_idle(self._back)
-
- for pool in self._pools:
- pool.shutdown(wait=True)
-
-
-def server_and_stub(
- default_timeout,
- inline_value_in_value_out_methods=None,
- inline_value_in_stream_out_methods=None,
- inline_stream_in_value_out_methods=None,
- inline_stream_in_stream_out_methods=None,
- event_value_in_value_out_methods=None,
- event_value_in_stream_out_methods=None,
- event_stream_in_value_out_methods=None,
- event_stream_in_stream_out_methods=None,
- multi_method=None):
- """Creates a Server and Stub linked together for use."""
- front_work_pool = logging_pool.pool(_POOL_SIZE_LIMIT)
- front_transmission_pool = logging_pool.pool(_POOL_SIZE_LIMIT)
- front_utility_pool = logging_pool.pool(_POOL_SIZE_LIMIT)
- back_work_pool = logging_pool.pool(_POOL_SIZE_LIMIT)
- back_transmission_pool = logging_pool.pool(_POOL_SIZE_LIMIT)
- back_utility_pool = logging_pool.pool(_POOL_SIZE_LIMIT)
- stub_pool = logging_pool.pool(_POOL_SIZE_LIMIT)
- pools = (
- front_work_pool, front_transmission_pool, front_utility_pool,
- back_work_pool, back_transmission_pool, back_utility_pool,
- stub_pool)
-
- servicer = implementations.servicer(
- back_work_pool,
- inline_value_in_value_out_methods=inline_value_in_value_out_methods,
- inline_value_in_stream_out_methods=inline_value_in_stream_out_methods,
- inline_stream_in_value_out_methods=inline_stream_in_value_out_methods,
- inline_stream_in_stream_out_methods=inline_stream_in_stream_out_methods,
- event_value_in_value_out_methods=event_value_in_value_out_methods,
- event_value_in_stream_out_methods=event_value_in_stream_out_methods,
- event_stream_in_value_out_methods=event_stream_in_value_out_methods,
- event_stream_in_stream_out_methods=event_stream_in_stream_out_methods,
- multi_method=multi_method)
-
- front = _base_implementations.front_link(
- front_work_pool, front_transmission_pool, front_utility_pool)
- back = _base_implementations.back_link(
- servicer, back_work_pool, back_transmission_pool, back_utility_pool,
- default_timeout, _MAXIMUM_TIMEOUT)
- front.join_rear_link(back)
- back.join_fore_link(front)
-
- stub = implementations.stub(front, stub_pool)
-
- return _LinkedPair(implementations.server(), stub, front, back, pools)
diff --git a/src/python/grpcio/grpc/framework/face/implementations.py b/src/python/grpcio/grpc/framework/face/implementations.py
deleted file mode 100644
index 96055b4130..0000000000
--- a/src/python/grpcio/grpc/framework/face/implementations.py
+++ /dev/null
@@ -1,320 +0,0 @@
-# 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.
-
-"""Entry points into the Face layer of RPC Framework."""
-
-import six
-
-from grpc.framework.common import cardinality
-from grpc.framework.common import style
-from grpc.framework.base import exceptions as _base_exceptions
-from grpc.framework.base import interfaces as base_interfaces
-from grpc.framework.face import _calls
-from grpc.framework.face import _service
-from grpc.framework.face import exceptions
-from grpc.framework.face import interfaces
-
-
-class _BaseServicer(base_interfaces.Servicer):
-
- def __init__(self, methods, multi_method):
- self._methods = methods
- self._multi_method = multi_method
-
- def service(self, name, context, output_consumer):
- method = self._methods.get(name, None)
- if method is not None:
- return method(output_consumer, context)
- elif self._multi_method is not None:
- try:
- return self._multi_method.service(name, output_consumer, context)
- except exceptions.NoSuchMethodError:
- raise _base_exceptions.NoSuchMethodError()
- else:
- raise _base_exceptions.NoSuchMethodError()
-
-
-class _UnaryUnaryMultiCallable(interfaces.UnaryUnaryMultiCallable):
-
- def __init__(self, front, name):
- self._front = front
- self._name = name
-
- def __call__(self, request, timeout):
- return _calls.blocking_value_in_value_out(
- self._front, self._name, request, timeout, 'unused trace ID')
-
- def future(self, request, timeout):
- return _calls.future_value_in_value_out(
- self._front, self._name, request, timeout, 'unused trace ID')
-
- def event(self, request, response_callback, abortion_callback, timeout):
- return _calls.event_value_in_value_out(
- self._front, self._name, request, response_callback, abortion_callback,
- timeout, 'unused trace ID')
-
-
-class _UnaryStreamMultiCallable(interfaces.UnaryStreamMultiCallable):
-
- def __init__(self, front, name):
- self._front = front
- self._name = name
-
- def __call__(self, request, timeout):
- return _calls.inline_value_in_stream_out(
- self._front, self._name, request, timeout, 'unused trace ID')
-
- def event(self, request, response_consumer, abortion_callback, timeout):
- return _calls.event_value_in_stream_out(
- self._front, self._name, request, response_consumer, abortion_callback,
- timeout, 'unused trace ID')
-
-
-class _StreamUnaryMultiCallable(interfaces.StreamUnaryMultiCallable):
-
- def __init__(self, front, name, pool):
- self._front = front
- self._name = name
- self._pool = pool
-
- def __call__(self, request_iterator, timeout):
- return _calls.blocking_stream_in_value_out(
- self._front, self._name, request_iterator, timeout, 'unused trace ID')
-
- def future(self, request_iterator, timeout):
- return _calls.future_stream_in_value_out(
- self._front, self._name, request_iterator, timeout, 'unused trace ID',
- self._pool)
-
- def event(self, response_callback, abortion_callback, timeout):
- return _calls.event_stream_in_value_out(
- self._front, self._name, response_callback, abortion_callback, timeout,
- 'unused trace ID')
-
-
-class _StreamStreamMultiCallable(interfaces.StreamStreamMultiCallable):
-
- def __init__(self, front, name, pool):
- self._front = front
- self._name = name
- self._pool = pool
-
- def __call__(self, request_iterator, timeout):
- return _calls.inline_stream_in_stream_out(
- self._front, self._name, request_iterator, timeout, 'unused trace ID',
- self._pool)
-
- def event(self, response_consumer, abortion_callback, timeout):
- return _calls.event_stream_in_stream_out(
- self._front, self._name, response_consumer, abortion_callback, timeout,
- 'unused trace ID')
-
-
-class _GenericStub(interfaces.GenericStub):
- """An interfaces.GenericStub implementation."""
-
- def __init__(self, front, pool):
- self._front = front
- self._pool = pool
-
- def blocking_value_in_value_out(self, name, request, timeout):
- return _calls.blocking_value_in_value_out(
- self._front, name, request, timeout, 'unused trace ID')
-
- def future_value_in_value_out(self, name, request, timeout):
- return _calls.future_value_in_value_out(
- self._front, name, request, timeout, 'unused trace ID')
-
- def inline_value_in_stream_out(self, name, request, timeout):
- return _calls.inline_value_in_stream_out(
- self._front, name, request, timeout, 'unused trace ID')
-
- def blocking_stream_in_value_out(self, name, request_iterator, timeout):
- return _calls.blocking_stream_in_value_out(
- self._front, name, request_iterator, timeout, 'unused trace ID')
-
- def future_stream_in_value_out(self, name, request_iterator, timeout):
- return _calls.future_stream_in_value_out(
- self._front, name, request_iterator, timeout, 'unused trace ID',
- self._pool)
-
- def inline_stream_in_stream_out(self, name, request_iterator, timeout):
- return _calls.inline_stream_in_stream_out(
- self._front, name, request_iterator, timeout, 'unused trace ID',
- self._pool)
-
- def event_value_in_value_out(
- self, name, request, response_callback, abortion_callback, timeout):
- return _calls.event_value_in_value_out(
- self._front, name, request, response_callback, abortion_callback,
- timeout, 'unused trace ID')
-
- def event_value_in_stream_out(
- self, name, request, response_consumer, abortion_callback, timeout):
- return _calls.event_value_in_stream_out(
- self._front, name, request, response_consumer, abortion_callback,
- timeout, 'unused trace ID')
-
- def event_stream_in_value_out(
- self, name, response_callback, abortion_callback, timeout):
- return _calls.event_stream_in_value_out(
- self._front, name, response_callback, abortion_callback, timeout,
- 'unused trace ID')
-
- def event_stream_in_stream_out(
- self, name, response_consumer, abortion_callback, timeout):
- return _calls.event_stream_in_stream_out(
- self._front, name, response_consumer, abortion_callback, timeout,
- 'unused trace ID')
-
- def unary_unary_multi_callable(self, name):
- return _UnaryUnaryMultiCallable(self._front, name)
-
- def unary_stream_multi_callable(self, name):
- return _UnaryStreamMultiCallable(self._front, name)
-
- def stream_unary_multi_callable(self, name):
- return _StreamUnaryMultiCallable(self._front, name, self._pool)
-
- def stream_stream_multi_callable(self, name):
- return _StreamStreamMultiCallable(self._front, name, self._pool)
-
-
-class _DynamicStub(interfaces.DynamicStub):
- """An interfaces.DynamicStub implementation."""
-
- def __init__(self, cardinalities, front, pool):
- self._cardinalities = cardinalities
- self._front = front
- self._pool = pool
-
- def __getattr__(self, attr):
- method_cardinality = self._cardinalities.get(attr)
- if method_cardinality is cardinality.Cardinality.UNARY_UNARY:
- return _UnaryUnaryMultiCallable(self._front, attr)
- elif method_cardinality is cardinality.Cardinality.UNARY_STREAM:
- return _UnaryStreamMultiCallable(self._front, attr)
- elif method_cardinality is cardinality.Cardinality.STREAM_UNARY:
- return _StreamUnaryMultiCallable(self._front, attr, self._pool)
- elif method_cardinality is cardinality.Cardinality.STREAM_STREAM:
- return _StreamStreamMultiCallable(self._front, attr, self._pool)
- else:
- raise AttributeError('_DynamicStub object has no attribute "%s"!' % attr)
-
-
-def _adapt_method_implementations(method_implementations, pool):
- adapted_implementations = {}
- for name, method_implementation in six.iteritems(method_implementations):
- if method_implementation.style is style.Service.INLINE:
- if method_implementation.cardinality is cardinality.Cardinality.UNARY_UNARY:
- adapted_implementations[name] = _service.adapt_inline_value_in_value_out(
- method_implementation.unary_unary_inline)
- elif method_implementation.cardinality is cardinality.Cardinality.UNARY_STREAM:
- adapted_implementations[name] = _service.adapt_inline_value_in_stream_out(
- method_implementation.unary_stream_inline)
- elif method_implementation.cardinality is cardinality.Cardinality.STREAM_UNARY:
- adapted_implementations[name] = _service.adapt_inline_stream_in_value_out(
- method_implementation.stream_unary_inline, pool)
- elif method_implementation.cardinality is cardinality.Cardinality.STREAM_STREAM:
- adapted_implementations[name] = _service.adapt_inline_stream_in_stream_out(
- method_implementation.stream_stream_inline, pool)
- elif method_implementation.style is style.Service.EVENT:
- if method_implementation.cardinality is cardinality.Cardinality.UNARY_UNARY:
- adapted_implementations[name] = _service.adapt_event_value_in_value_out(
- method_implementation.unary_unary_event)
- elif method_implementation.cardinality is cardinality.Cardinality.UNARY_STREAM:
- adapted_implementations[name] = _service.adapt_event_value_in_stream_out(
- method_implementation.unary_stream_event)
- elif method_implementation.cardinality is cardinality.Cardinality.STREAM_UNARY:
- adapted_implementations[name] = _service.adapt_event_stream_in_value_out(
- method_implementation.stream_unary_event)
- elif method_implementation.cardinality is cardinality.Cardinality.STREAM_STREAM:
- adapted_implementations[name] = _service.adapt_event_stream_in_stream_out(
- method_implementation.stream_stream_event)
- return adapted_implementations
-
-
-def servicer(pool, method_implementations, multi_method_implementation):
- """Creates a base_interfaces.Servicer.
-
- It is guaranteed that any passed interfaces.MultiMethodImplementation will
- only be called to service an RPC if there is no
- interfaces.MethodImplementation for the RPC method in the passed
- method_implementations dictionary.
-
- Args:
- pool: A thread pool.
- method_implementations: A dictionary from RPC method name to
- interfaces.MethodImplementation object to be used to service the named
- RPC method.
- multi_method_implementation: An interfaces.MultiMethodImplementation to be
- used to service any RPCs not serviced by the
- interfaces.MethodImplementations given in the method_implementations
- dictionary, or None.
-
- Returns:
- A base_interfaces.Servicer that services RPCs via the given implementations.
- """
- adapted_implementations = _adapt_method_implementations(
- method_implementations, pool)
- return _BaseServicer(adapted_implementations, multi_method_implementation)
-
-
-def generic_stub(front, pool):
- """Creates an interfaces.GenericStub.
-
- Args:
- front: A base_interfaces.Front.
- pool: A futures.ThreadPoolExecutor.
-
- Returns:
- An interfaces.GenericStub that performs RPCs via the given
- base_interfaces.Front.
- """
- return _GenericStub(front, pool)
-
-
-def dynamic_stub(cardinalities, front, pool, prefix):
- """Creates an interfaces.DynamicStub.
-
- Args:
- cardinalities: A dict from RPC method name to cardinality.Cardinality
- value identifying the cardinality of every RPC method to be supported by
- the created interfaces.DynamicStub.
- front: A base_interfaces.Front.
- pool: A futures.ThreadPoolExecutor.
- prefix: A string to prepend when mapping requested attribute name to RPC
- method name during attribute access on the created
- interfaces.DynamicStub.
-
- Returns:
- An interfaces.DynamicStub that performs RPCs via the given
- base_interfaces.Front.
- """
- return _DynamicStub(cardinalities, front, pool)
diff --git a/src/python/grpcio/grpc/framework/face/interfaces.py b/src/python/grpcio/grpc/framework/face/interfaces.py
deleted file mode 100644
index e9a25c17e1..0000000000
--- a/src/python/grpcio/grpc/framework/face/interfaces.py
+++ /dev/null
@@ -1,634 +0,0 @@
-# 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 for the face layer of RPC Framework."""
-
-import abc
-import enum
-
-import six
-
-# cardinality, style, exceptions, 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.face import exceptions # 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
-
-
-@enum.unique
-class Abortion(enum.Enum):
- """Categories of RPC abortion."""
- CANCELLED = 'cancelled'
- EXPIRED = 'expired'
- NETWORK_FAILURE = 'network failure'
- SERVICED_FAILURE = 'serviced failure'
- SERVICER_FAILURE = 'servicer failure'
-
-
-class CancellableIterator(six.with_metaclass(abc.ABCMeta)):
- """Implements the Iterator protocol and affords a cancel method."""
-
- @abc.abstractmethod
- def __iter__(self):
- """Returns the self object in accordance with the Iterator protocol."""
- raise NotImplementedError()
-
- def __next__(self):
- return self.next()
-
- @abc.abstractmethod
- def next(self):
- """Returns a value or raises StopIteration per the Iterator protocol."""
- raise NotImplementedError()
-
- @abc.abstractmethod
- def cancel(self):
- """Requests cancellation of whatever computation underlies this iterator."""
- raise NotImplementedError()
-
-
-class RpcContext(six.with_metaclass(abc.ABCMeta)):
- """Provides RPC-related information and action."""
-
- @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()
-
-
-class Call(six.with_metaclass(abc.ABCMeta)):
- """Invocation-side representation of an RPC.
-
- Attributes:
- context: An RpcContext affording information about the RPC.
- """
-
- @abc.abstractmethod
- def cancel(self):
- """Requests cancellation of the RPC."""
- raise NotImplementedError()
-
-
-class UnaryUnaryMultiCallable(six.with_metaclass(abc.ABCMeta)):
- """Affords invoking a unary-unary RPC in any call style."""
-
- @abc.abstractmethod
- def __call__(self, request, timeout):
- """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.
-
- Returns:
- The response value for the RPC.
-
- Raises:
- exceptions.RpcError: Indicating that the RPC was aborted.
- """
- raise NotImplementedError()
-
- @abc.abstractmethod
- def future(self, request, timeout):
- """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.
-
- Returns:
- A future.Future representing the RPC. In the event of RPC completion, the
- returned 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 exceptions.RpcError.
- """
- raise NotImplementedError()
-
- @abc.abstractmethod
- def event(self, request, response_callback, abortion_callback, timeout):
- """Asynchronously invokes the underlying RPC.
-
- Args:
- request: The request value for the RPC.
- response_callback: A callback to be called to accept the restponse value
- 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.
-
- Returns:
- A Call object for the RPC.
- """
- raise NotImplementedError()
-
-
-class UnaryStreamMultiCallable(six.with_metaclass(abc.ABCMeta)):
- """Affords invoking a unary-stream RPC in any call style."""
-
- @abc.abstractmethod
- def __call__(self, request, timeout):
- """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.
-
- Returns:
- A CancellableIterator that yields the response values of the RPC and
- affords RPC cancellation. Drawing response values from the returned
- CancellableIterator may raise exceptions.RpcError indicating abortion
- of the RPC.
- """
- raise NotImplementedError()
-
- @abc.abstractmethod
- def event(self, request, response_consumer, abortion_callback, timeout):
- """Asynchronously invokes the underlying RPC.
-
- Args:
- request: The request value for the RPC.
- response_consumer: A stream.Consumer to be called to accept the restponse
- values 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.
-
- Returns:
- A Call object for the RPC.
- """
- raise NotImplementedError()
-
-
-class StreamUnaryMultiCallable(six.with_metaclass(abc.ABCMeta)):
- """Affords invoking a stream-unary RPC in any call style."""
-
- @abc.abstractmethod
- def __call__(self, request_iterator, timeout):
- """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.
-
- Returns:
- The response value for the RPC.
-
- Raises:
- exceptions.RpcError: Indicating that the RPC was aborted.
- """
- raise NotImplementedError()
-
- @abc.abstractmethod
- def future(self, request_iterator, timeout):
- """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.
-
- Returns:
- A future.Future representing the RPC. In the event of RPC completion, the
- returned 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 exceptions.RpcError.
- """
- raise NotImplementedError()
-
- @abc.abstractmethod
- def event(self, response_callback, abortion_callback, timeout):
- """Asynchronously invokes the underlying RPC.
-
- Args:
- request: The request value for the RPC.
- response_callback: A callback to be called to accept the restponse value
- 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.
-
- 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()
-
-
-class StreamStreamMultiCallable(six.with_metaclass(abc.ABCMeta)):
- """Affords invoking a stream-stream RPC in any call style."""
-
- @abc.abstractmethod
- def __call__(self, request_iterator, timeout):
- """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.
-
- Returns:
- A CancellableIterator that yields the response values of the RPC and
- affords RPC cancellation. Drawing response values from the returned
- CancellableIterator may raise exceptions.RpcError indicating abortion
- of the RPC.
- """
- raise NotImplementedError()
-
- @abc.abstractmethod
- def event(self, response_consumer, abortion_callback, timeout):
- """Asynchronously invokes the underlying RPC.
-
-l Args:
- response_consumer: A stream.Consumer to be called to accept the restponse
- values 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.
-
- 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()
-
-
-class MethodImplementation(six.with_metaclass(abc.ABCMeta)):
- """A sum type that describes an RPC method implementation.
-
- Attributes:
- cardinality: A cardinality.Cardinality value.
- style: A style.Service value.
- unary_unary_inline: The implementation of the RPC method as a callable
- value that takes a request value and an RpcContext 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 RPC method as a callable
- value that takes a request value and an RpcContext 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 RPC method as a callable
- value that takes an iterator of request values and an RpcContext 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 RPC method as a callable
- value that takes an iterator of request values and an RpcContext 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 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 RpcContext. Only non-None if
- cardinality is cardinality.Cardinality.UNARY_UNARY and style is
- style.Service.EVENT.
- unary_stream_event: The implementation of the 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 RpcContext. Only non-None if
- cardinality is cardinality.Cardinality.UNARY_STREAM and style is
- style.Service.EVENT.
- stream_unary_event: The implementation of the RPC method as a callable
- value that takes a response callback to which to pass the response value
- of the RPC and an RpcContext 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 RPC method as a callable
- value that takes a stream.Consumer to which to pass the response values
- of the RPC and an RpcContext 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.
- """
-
-
-class MultiMethodImplementation(six.with_metaclass(abc.ABCMeta)):
- """A general type able to service many RPC methods."""
-
- @abc.abstractmethod
- def service(self, name, response_consumer, context):
- """Services an RPC.
-
- Args:
- name: The RPC method name.
- response_consumer: A stream.Consumer to be called to accept the response
- values of the RPC.
- context: An RpcContext 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.
- exceptions.NoSuchMethodError: If this MultiMethod does not recognize the
- given RPC method name and is not able to service the RPC.
- """
- raise NotImplementedError()
-
-
-class GenericStub(six.with_metaclass(abc.ABCMeta)):
- """Affords RPC methods to callers."""
-
- @abc.abstractmethod
- def blocking_value_in_value_out(self, name, request, timeout):
- """Invokes a unary-request-unary-response RPC 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:
- name: The RPC method name.
- request: The request value for the RPC.
- timeout: A duration of time in seconds to allow for the RPC.
-
- Returns:
- The response value for the RPC.
-
- Raises:
- exceptions.RpcError: Indicating that the RPC was aborted.
- """
- raise NotImplementedError()
-
- @abc.abstractmethod
- def future_value_in_value_out(self, name, request, timeout):
- """Invokes a unary-request-unary-response RPC method.
-
- Args:
- name: The RPC method name.
- request: The request value for the RPC.
- timeout: A duration of time in seconds to allow for the RPC.
-
- Returns:
- A future.Future representing the RPC. In the event of RPC completion, the
- returned Future will return an outcome indicating that the RPC returned
- the response value of the RPC. In the event of RPC abortion, the
- returned Future will return an outcome indicating that the RPC raised
- an exceptions.RpcError.
- """
- raise NotImplementedError()
-
- @abc.abstractmethod
- def inline_value_in_stream_out(self, name, request, timeout):
- """Invokes a unary-request-stream-response RPC method.
-
- Args:
- name: The RPC method name.
- request: The request value for the RPC.
- timeout: A duration of time in seconds to allow for the RPC.
-
- Returns:
- A CancellableIterator that yields the response values of the RPC and
- affords RPC cancellation. Drawing response values from the returned
- CancellableIterator may raise exceptions.RpcError indicating abortion of
- the RPC.
- """
- raise NotImplementedError()
-
- @abc.abstractmethod
- def blocking_stream_in_value_out(self, name, request_iterator, timeout):
- """Invokes a stream-request-unary-response RPC 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:
- name: The RPC method name.
- request_iterator: An iterator that yields the request values of the RPC.
- timeout: A duration of time in seconds to allow for the RPC.
-
- Returns:
- The response value for the RPC.
-
- Raises:
- exceptions.RpcError: Indicating that the RPC was aborted.
- """
- raise NotImplementedError()
-
- @abc.abstractmethod
- def future_stream_in_value_out(self, name, request_iterator, timeout):
- """Invokes a stream-request-unary-response RPC method.
-
- Args:
- name: The RPC method name.
- request_iterator: An iterator that yields the request values of the RPC.
- timeout: A duration of time in seconds to allow for the RPC.
-
- Returns:
- A future.Future representing the RPC. In the event of RPC completion, the
- returned Future will return an outcome indicating that the RPC returned
- the response value of the RPC. In the event of RPC abortion, the
- returned Future will return an outcome indicating that the RPC raised
- an exceptions.RpcError.
- """
- raise NotImplementedError()
-
- @abc.abstractmethod
- def inline_stream_in_stream_out(self, name, request_iterator, timeout):
- """Invokes a stream-request-stream-response RPC method.
-
- Args:
- name: The RPC method name.
- request_iterator: An iterator that yields the request values of the RPC.
- timeout: A duration of time in seconds to allow for the RPC.
-
- Returns:
- A CancellableIterator that yields the response values of the RPC and
- affords RPC cancellation. Drawing response values from the returned
- CancellableIterator may raise exceptions.RpcError indicating abortion of
- the RPC.
- """
- raise NotImplementedError()
-
- @abc.abstractmethod
- def event_value_in_value_out(
- self, name, request, response_callback, abortion_callback, timeout):
- """Event-driven invocation of a unary-request-unary-response RPC method.
-
- Args:
- name: The RPC method name.
- request: The request value for the RPC.
- response_callback: A callback to be called to accept the response value
- 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.
-
- Returns:
- A Call object for the RPC.
- """
- raise NotImplementedError()
-
- @abc.abstractmethod
- def event_value_in_stream_out(
- self, name, request, response_consumer, abortion_callback, timeout):
- """Event-driven invocation of a unary-request-stream-response RPC method.
-
- Args:
- name: The RPC method name.
- request: The request value for the RPC.
- response_consumer: A stream.Consumer to be called to accept the response
- values 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.
-
- Returns:
- A Call object for the RPC.
- """
- raise NotImplementedError()
-
- @abc.abstractmethod
- def event_stream_in_value_out(
- self, name, response_callback, abortion_callback, timeout):
- """Event-driven invocation of a unary-request-unary-response RPC method.
-
- Args:
- name: The RPC method name.
- response_callback: A callback to be called to accept the response value
- 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.
-
- 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_in_stream_out(
- self, name, response_consumer, abortion_callback, timeout):
- """Event-driven invocation of a unary-request-stream-response RPC method.
-
- Args:
- name: The RPC method name.
- response_consumer: A stream.Consumer to be called to accept the response
- values 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.
-
- 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_multi_callable(self, name):
- """Creates a UnaryUnaryMultiCallable for a unary-unary RPC method.
-
- Args:
- name: The RPC method name.
-
- Returns:
- A UnaryUnaryMultiCallable value for the named unary-unary RPC method.
- """
- raise NotImplementedError()
-
- @abc.abstractmethod
- def unary_stream_multi_callable(self, name):
- """Creates a UnaryStreamMultiCallable for a unary-stream RPC method.
-
- Args:
- name: The RPC method name.
-
- Returns:
- A UnaryStreamMultiCallable value for the name unary-stream RPC method.
- """
- raise NotImplementedError()
-
- @abc.abstractmethod
- def stream_unary_multi_callable(self, name):
- """Creates a StreamUnaryMultiCallable for a stream-unary RPC method.
-
- Args:
- name: The RPC method name.
-
- Returns:
- A StreamUnaryMultiCallable value for the named stream-unary RPC method.
- """
- raise NotImplementedError()
-
- @abc.abstractmethod
- def stream_stream_multi_callable(self, name):
- """Creates a StreamStreamMultiCallable for a stream-stream RPC method.
-
- Args:
- name: The RPC method name.
-
- Returns:
- A StreamStreamMultiCallable value for the named stream-stream RPC method.
- """
- raise NotImplementedError()
-
-
-class DynamicStub(six.with_metaclass(abc.ABCMeta)):
- """A stub with RPC-method-bound multi-callable attributes.
-
- Instances of this type responsd to attribute access as follows: if the
- requested attribute is the name of a unary-unary RPC method, the value of the
- attribute will be a UnaryUnaryMultiCallable with which to invoke the RPC
- method; if the requested attribute is the name of a unary-stream RPC method,
- the value of the attribute will be a UnaryStreamMultiCallable with which to
- invoke the RPC method; if the requested attribute is the name of a
- stream-unary RPC method, the value of the attribute will be a
- StreamUnaryMultiCallable with which to invoke the RPC method; and if the
- requested attribute is the name of a stream-stream RPC method, the value of
- the attribute will be a StreamStreamMultiCallable with which to invoke the
- RPC method.
- """
diff --git a/src/python/grpcio/grpc/framework/face/utilities.py b/src/python/grpcio/grpc/framework/face/utilities.py
deleted file mode 100644
index a63fe8c60d..0000000000
--- a/src/python/grpcio/grpc/framework/face/utilities.py
+++ /dev/null
@@ -1,177 +0,0 @@
-# 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 layer."""
-
-import collections
-
-from grpc.framework.common import cardinality
-from grpc.framework.common import style
-from grpc.framework.face import interfaces
-from grpc.framework.foundation import stream
-
-
-class _MethodImplementation(
- interfaces.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 interfaces.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 interfaces.RpcContext object and
- returns a response value.
-
- Returns:
- An interfaces.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 interfaces.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 interfaces.RpcContext object and
- returns an iterator of response values.
-
- Returns:
- An interfaces.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 interfaces.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
- interfaces.RpcContext object and returns a response value.
-
- Returns:
- An interfaces.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 interfaces.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
- interfaces.RpcContext object and returns an iterator of response values.
-
- Returns:
- An interfaces.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 interfaces.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 interfaces.RpcContext.
-
- Returns:
- An interfaces.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 interfaces.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 interfaces.RpcContext.
-
- Returns:
- An interfaces.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 interfaces.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 interfaces.RpcContext and returns a stream.Consumer to
- which the request values of the RPC should be passed.
-
- Returns:
- An interfaces.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 interfaces.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 interfaces.RpcContext and returns a stream.Consumer to
- which the request values of the RPC should be passed.
-
- Returns:
- An interfaces.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/tests/protoc_plugin/beta_python_plugin_test.py b/src/python/grpcio/tests/protoc_plugin/beta_python_plugin_test.py
index 6fba3d4271..3dc3042e38 100644
--- a/src/python/grpcio/tests/protoc_plugin/beta_python_plugin_test.py
+++ b/src/python/grpcio/tests/protoc_plugin/beta_python_plugin_test.py
@@ -45,6 +45,7 @@ import unittest
from six import moves
from grpc.beta import implementations
+from grpc.beta import interfaces
from grpc.framework.foundation import future
from grpc.framework.interfaces.face import face
from tests.unit.framework.common import test_constants
@@ -178,6 +179,36 @@ def _CreateService(test_pb2):
server.stop(0)
+@contextlib.contextmanager
+def _CreateIncompleteService(test_pb2):
+ """Provides a servicer backend that fails to implement methods and its stub.
+
+ The servicer is just the implementation of the actual servicer passed to the
+ face player of the python RPC implementation; the two are detached.
+
+ Args:
+ test_pb2: The test_pb2 module generated by this test.
+
+ Yields:
+ A (servicer_methods, stub) pair where servicer_methods is the back-end of
+ the service bound to the stub and and stub is the stub on which to invoke
+ RPCs.
+ """
+ servicer_methods = _ServicerMethods(test_pb2)
+
+ class Servicer(getattr(test_pb2, SERVICER_IDENTIFIER)):
+ pass
+
+ servicer = Servicer()
+ server = getattr(test_pb2, SERVER_FACTORY_IDENTIFIER)(servicer)
+ port = server.add_insecure_port('[::]:0')
+ server.start()
+ channel = implementations.insecure_channel('localhost', port)
+ stub = getattr(test_pb2, STUB_FACTORY_IDENTIFIER)(channel)
+ yield servicer_methods, stub
+ server.stop(0)
+
+
def _streaming_input_request_iterator(test_pb2):
for _ in range(3):
request = test_pb2.StreamingInputCallRequest()
@@ -264,6 +295,16 @@ class PythonPluginTest(unittest.TestCase):
with _CreateService(test_pb2) as (servicer, stub):
request = test_pb2.SimpleRequest(response_size=13)
+ def testIncompleteServicer(self):
+ import protoc_plugin_test_pb2 as test_pb2
+ moves.reload_module(test_pb2)
+ with _CreateIncompleteService(test_pb2) as (servicer, stub):
+ request = test_pb2.SimpleRequest(response_size=13)
+ try:
+ response = stub.UnaryCall(request, test_constants.LONG_TIMEOUT)
+ except face.AbortionError as error:
+ self.assertEqual(interfaces.StatusCode.UNIMPLEMENTED, error.code)
+
def testUnaryCall(self):
import protoc_plugin_test_pb2 as test_pb2 # pylint: disable=g-import-not-at-top
moves.reload_module(test_pb2)
diff --git a/src/python/grpcio/tests/unit/framework/face/__init__.py b/src/python/grpcio/tests/qps/__init__.py
index 7086519106..100a624dc9 100644
--- a/src/python/grpcio/tests/unit/framework/face/__init__.py
+++ b/src/python/grpcio/tests/qps/__init__.py
@@ -1,4 +1,4 @@
-# Copyright 2015, Google Inc.
+# Copyright 2016, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -26,5 +26,3 @@
# 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/tests/qps/benchmark_client.py b/src/python/grpcio/tests/qps/benchmark_client.py
new file mode 100644
index 0000000000..eed0b0c6da
--- /dev/null
+++ b/src/python/grpcio/tests/qps/benchmark_client.py
@@ -0,0 +1,186 @@
+# Copyright 2016, 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.
+
+"""Defines test client behaviors (UNARY/STREAMING) (SYNC/ASYNC)."""
+
+import abc
+import time
+try:
+ import Queue as queue # Python 2.x
+except ImportError:
+ import queue # Python 3
+
+from concurrent import futures
+
+from grpc.beta import implementations
+from src.proto.grpc.testing import messages_pb2
+from src.proto.grpc.testing import services_pb2
+from tests.unit import resources
+from tests.unit.beta import test_utilities
+
+_TIMEOUT = 60 * 60 * 24
+
+
+class BenchmarkClient:
+ """Benchmark client interface that exposes a non-blocking send_request()."""
+
+ __metaclass__ = abc.ABCMeta
+
+ def __init__(self, server, config, hist):
+ # Create the stub
+ host, port = server.split(':')
+ port = int(port)
+ if config.HasField('security_params'):
+ creds = implementations.ssl_channel_credentials(
+ resources.test_root_certificates())
+ channel = test_utilities.not_really_secure_channel(
+ host, port, creds, config.security_params.server_host_override)
+ else:
+ channel = implementations.insecure_channel(host, port)
+
+ if config.payload_config.WhichOneof('payload') == 'simple_params':
+ self._generic = False
+ self._stub = services_pb2.beta_create_BenchmarkService_stub(channel)
+ payload = messages_pb2.Payload(
+ body='\0' * config.payload_config.simple_params.req_size)
+ self._request = messages_pb2.SimpleRequest(
+ payload=payload,
+ response_size=config.payload_config.simple_params.resp_size)
+ else:
+ self._generic = True
+ self._stub = implementations.generic_stub(channel)
+ self._request = '\0' * config.payload_config.bytebuf_params.req_size
+
+ self._hist = hist
+ self._response_callbacks = []
+
+ def add_response_callback(self, callback):
+ self._response_callbacks.append(callback)
+
+ @abc.abstractmethod
+ def send_request(self):
+ """Non-blocking wrapper for a client's request operation."""
+ raise NotImplementedError()
+
+ def start(self):
+ pass
+
+ def stop(self):
+ pass
+
+ def _handle_response(self, query_time):
+ self._hist.add(query_time * 1e9) # Report times in nanoseconds
+ for callback in self._response_callbacks:
+ callback(query_time)
+
+
+class UnarySyncBenchmarkClient(BenchmarkClient):
+
+ def __init__(self, server, config, hist):
+ super(UnarySyncBenchmarkClient, self).__init__(server, config, hist)
+ self._pool = futures.ThreadPoolExecutor(
+ max_workers=config.outstanding_rpcs_per_channel)
+
+ def send_request(self):
+ # Send requests in seperate threads to support multiple outstanding rpcs
+ # (See src/proto/grpc/testing/control.proto)
+ self._pool.submit(self._dispatch_request)
+
+ def stop(self):
+ self._pool.shutdown(wait=True)
+ self._stub = None
+
+ def _dispatch_request(self):
+ start_time = time.time()
+ self._stub.UnaryCall(self._request, _TIMEOUT)
+ end_time = time.time()
+ self._handle_response(end_time - start_time)
+
+
+class UnaryAsyncBenchmarkClient(BenchmarkClient):
+
+ def send_request(self):
+ # Use the Future callback api to support multiple outstanding rpcs
+ start_time = time.time()
+ response_future = self._stub.UnaryCall.future(self._request, _TIMEOUT)
+ response_future.add_done_callback(
+ lambda resp: self._response_received(start_time, resp))
+
+ def _response_received(self, start_time, resp):
+ resp.result()
+ end_time = time.time()
+ self._handle_response(end_time - start_time)
+
+ def stop(self):
+ self._stub = None
+
+
+class StreamingAsyncBenchmarkClient(BenchmarkClient):
+
+ def __init__(self, server, config, hist):
+ super(StreamingAsyncBenchmarkClient, self).__init__(server, config, hist)
+ self._is_streaming = False
+ self._pool = futures.ThreadPoolExecutor(max_workers=1)
+ # Use a thread-safe queue to put requests on the stream
+ self._request_queue = queue.Queue()
+ self._send_time_queue = queue.Queue()
+
+ def send_request(self):
+ self._send_time_queue.put(time.time())
+ self._request_queue.put(self._request)
+
+ def start(self):
+ self._is_streaming = True
+ self._pool.submit(self._request_stream)
+
+ def stop(self):
+ self._is_streaming = False
+ self._pool.shutdown(wait=True)
+ self._stub = None
+
+ def _request_stream(self):
+ self._is_streaming = True
+ if self._generic:
+ response_stream = self._stub.inline_stream_stream(
+ 'grpc.testing.BenchmarkService', 'StreamingCall',
+ self._request_generator(), _TIMEOUT)
+ else:
+ response_stream = self._stub.StreamingCall(self._request_generator(),
+ _TIMEOUT)
+ for _ in response_stream:
+ end_time = time.time()
+ self._handle_response(end_time - self._send_time_queue.get_nowait())
+
+ def _request_generator(self):
+ while self._is_streaming:
+ try:
+ request = self._request_queue.get(block=True, timeout=1.0)
+ yield request
+ except queue.Empty:
+ pass
diff --git a/src/python/grpcio/grpc/framework/base/exceptions.py b/src/python/grpcio/tests/qps/benchmark_server.py
index b8f4752184..8cbf480d58 100644
--- a/src/python/grpcio/grpc/framework/base/exceptions.py
+++ b/src/python/grpcio/tests/qps/benchmark_server.py
@@ -1,4 +1,4 @@
-# Copyright 2015, Google Inc.
+# Copyright 2016, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -27,8 +27,32 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-"""Exceptions defined and used by the base layer of RPC Framework."""
+from src.proto.grpc.testing import messages_pb2
+from src.proto.grpc.testing import services_pb2
-class NoSuchMethodError(Exception):
- """Indicates that an operation with an unrecognized name has been called."""
+class BenchmarkServer(services_pb2.BetaBenchmarkServiceServicer):
+ """Synchronous Server implementation for the Benchmark service."""
+
+ def UnaryCall(self, request, context):
+ payload = messages_pb2.Payload(body='\0' * request.response_size)
+ return messages_pb2.SimpleResponse(payload=payload)
+
+ def StreamingCall(self, request_iterator, context):
+ for request in request_iterator:
+ payload = messages_pb2.Payload(body='\0' * request.response_size)
+ yield messages_pb2.SimpleResponse(payload=payload)
+
+
+class GenericBenchmarkServer(services_pb2.BetaBenchmarkServiceServicer):
+ """Generic Server implementation for the Benchmark service."""
+
+ def __init__(self, resp_size):
+ self._response = '\0' * resp_size
+
+ def UnaryCall(self, request, context):
+ return self._response
+
+ def StreamingCall(self, request_iterator, context):
+ for request in request_iterator:
+ yield self._response
diff --git a/src/python/grpcio/tests/qps/client_runner.py b/src/python/grpcio/tests/qps/client_runner.py
new file mode 100644
index 0000000000..a36c30ccc0
--- /dev/null
+++ b/src/python/grpcio/tests/qps/client_runner.py
@@ -0,0 +1,104 @@
+# Copyright 2016, 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.
+
+"""Defines behavior for WHEN clients send requests.
+
+Each client exposes a non-blocking send_request() method that the
+ClientRunner invokes either periodically or in response to some event.
+"""
+
+import abc
+import thread
+import time
+
+
+class ClientRunner:
+ """Abstract interface for sending requests from clients."""
+
+ __metaclass__ = abc.ABCMeta
+
+ def __init__(self, client):
+ self._client = client
+
+ @abc.abstractmethod
+ def start(self):
+ raise NotImplementedError()
+
+ @abc.abstractmethod
+ def stop(self):
+ raise NotImplementedError()
+
+
+class OpenLoopClientRunner(ClientRunner):
+
+ def __init__(self, client, interval_generator):
+ super(OpenLoopClientRunner, self).__init__(client)
+ self._is_running = False
+ self._interval_generator = interval_generator
+
+ def start(self):
+ self._is_running = True
+ self._client.start()
+ thread.start_new_thread(self._dispatch_requests, ())
+
+ def stop(self):
+ self._is_running = False
+ self._client.stop()
+ self._client = None
+
+ def _dispatch_requests(self):
+ while self._is_running:
+ self._client.send_request()
+ time.sleep(next(self._interval_generator))
+
+
+class ClosedLoopClientRunner(ClientRunner):
+
+ def __init__(self, client, request_count):
+ super(ClosedLoopClientRunner, self).__init__(client)
+ self._is_running = False
+ self._request_count = request_count
+ # Send a new request on each response for closed loop
+ self._client.add_response_callback(self._send_request)
+
+ def start(self):
+ self._is_running = True
+ for _ in xrange(self._request_count):
+ self._client.send_request()
+ self._client.start()
+
+ def stop(self):
+ self._is_running = False
+ self._client.stop()
+ self._client = None
+
+ def _send_request(self, response_time):
+ if self._is_running:
+ self._client.send_request()
+
diff --git a/src/python/grpcio/grpc/framework/base/_cancellation.py b/src/python/grpcio/tests/qps/histogram.py
index ffbc90668f..9a7b5eb2ba 100644
--- a/src/python/grpcio/grpc/framework/base/_cancellation.py
+++ b/src/python/grpcio/tests/qps/histogram.py
@@ -1,4 +1,4 @@
-# Copyright 2015, Google Inc.
+# Copyright 2016, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -27,38 +27,59 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-"""State and behavior for operation cancellation."""
+import math
+import threading
-from grpc.framework.base import _interfaces
-from grpc.framework.base import interfaces
+from src.proto.grpc.testing import stats_pb2
-class CancellationManager(_interfaces.CancellationManager):
- """An implementation of _interfaces.CancellationManager."""
+class Histogram(object):
+ """Histogram class used for recording performance testing data.
- def __init__(
- self, lock, termination_manager, transmission_manager, ingestion_manager,
- expiration_manager):
- """Constructor.
+ This class is thread safe.
+ """
- Args:
- lock: The operation-wide lock.
- termination_manager: The _interfaces.TerminationManager for the operation.
- transmission_manager: The _interfaces.TransmissionManager for the
- operation.
- ingestion_manager: The _interfaces.IngestionManager for the operation.
- expiration_manager: The _interfaces.ExpirationManager for the operation.
- """
- self._lock = lock
- self._termination_manager = termination_manager
- self._transmission_manager = transmission_manager
- self._ingestion_manager = ingestion_manager
- self._expiration_manager = expiration_manager
+ def __init__(self, resolution, max_possible):
+ self._lock = threading.Lock()
+ self._resolution = resolution
+ self._max_possible = max_possible
+ self._sum = 0
+ self._sum_of_squares = 0
+ self.multiplier = 1.0 + self._resolution
+ self._count = 0
+ self._min = self._max_possible
+ self._max = 0
+ self._buckets = [0] * (self._bucket_for(self._max_possible) + 1)
- def cancel(self):
- """See _interfaces.CancellationManager.cancel for specification."""
+ def reset(self):
with self._lock:
- self._termination_manager.abort(interfaces.Outcome.CANCELLED)
- self._transmission_manager.abort(interfaces.Outcome.CANCELLED)
- self._ingestion_manager.abort()
- self._expiration_manager.abort()
+ self._sum = 0
+ self._sum_of_squares = 0
+ self._count = 0
+ self._min = self._max_possible
+ self._max = 0
+ self._buckets = [0] * (self._bucket_for(self._max_possible) + 1)
+
+ def add(self, val):
+ with self._lock:
+ self._sum += val
+ self._sum_of_squares += val * val
+ self._count += 1
+ self._min = min(self._min, val)
+ self._max = max(self._max, val)
+ self._buckets[self._bucket_for(val)] += 1
+
+ def get_data(self):
+ with self._lock:
+ data = stats_pb2.HistogramData()
+ data.bucket.extend(self._buckets)
+ data.min_seen = self._min
+ data.max_seen = self._max
+ data.sum = self._sum
+ data.sum_of_squares = self._sum_of_squares
+ data.count = self._count
+ return data
+
+ def _bucket_for(self, val):
+ val = min(val, self._max_possible)
+ return int(math.log(val, self.multiplier))
diff --git a/src/python/grpcio/grpc/framework/base/null.py b/src/python/grpcio/tests/qps/qps_worker.py
index 1e30d4557b..3dda718638 100644
--- a/src/python/grpcio/grpc/framework/base/null.py
+++ b/src/python/grpcio/tests/qps/qps_worker.py
@@ -1,4 +1,4 @@
-# Copyright 2015, Google Inc.
+# Copyright 2016, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -27,30 +27,34 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-"""Null links that ignore tickets passed to them."""
+"""The entry point for the qps worker."""
-from grpc.framework.base import interfaces
+import argparse
+import time
+from src.proto.grpc.testing import services_pb2
-class _NullForeLink(interfaces.ForeLink):
- """A do-nothing ForeLink."""
+from tests.qps import worker_server
- def accept_back_to_front_ticket(self, ticket):
- pass
- def join_rear_link(self, rear_link):
- raise NotImplementedError()
+def run_worker_server(port):
+ servicer = worker_server.WorkerServer()
+ server = services_pb2.beta_create_WorkerService_server(servicer)
+ server.add_insecure_port('[::]:{}'.format(port))
+ server.start()
+ servicer.wait_for_quit()
+ # Drain outstanding requests for clean exit
+ time.sleep(2)
+ server.stop(0)
-class _NullRearLink(interfaces.RearLink):
- """A do-nothing RearLink."""
+if __name__ == '__main__':
+ parser = argparse.ArgumentParser(
+ description='gRPC Python performance testing worker')
+ parser.add_argument('--driver_port',
+ type=int,
+ dest='port',
+ help='The port the worker should listen on')
+ args = parser.parse_args()
- def accept_front_to_back_ticket(self, ticket):
- pass
-
- def join_fore_link(self, fore_link):
- raise NotImplementedError()
-
-
-NULL_FORE_LINK = _NullForeLink()
-NULL_REAR_LINK = _NullRearLink()
+ run_worker_server(args.port)
diff --git a/src/python/grpcio/tests/qps/worker_server.py b/src/python/grpcio/tests/qps/worker_server.py
new file mode 100644
index 0000000000..0b3acc14e7
--- /dev/null
+++ b/src/python/grpcio/tests/qps/worker_server.py
@@ -0,0 +1,184 @@
+# Copyright 2016, 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.
+
+import multiprocessing
+import random
+import threading
+import time
+
+from grpc.beta import implementations
+from grpc.framework.interfaces.face import utilities
+from src.proto.grpc.testing import control_pb2
+from src.proto.grpc.testing import services_pb2
+from src.proto.grpc.testing import stats_pb2
+
+from tests.qps import benchmark_client
+from tests.qps import benchmark_server
+from tests.qps import client_runner
+from tests.qps import histogram
+from tests.unit import resources
+
+
+class WorkerServer(services_pb2.BetaWorkerServiceServicer):
+ """Python Worker Server implementation."""
+
+ def __init__(self):
+ self._quit_event = threading.Event()
+
+ def RunServer(self, request_iterator, context):
+ config = next(request_iterator).setup
+ server, port = self._create_server(config)
+ cores = multiprocessing.cpu_count()
+ server.start()
+ start_time = time.time()
+ yield self._get_server_status(start_time, start_time, port, cores)
+
+ for request in request_iterator:
+ end_time = time.time()
+ status = self._get_server_status(start_time, end_time, port, cores)
+ if request.mark.reset:
+ start_time = end_time
+ yield status
+ server.stop(0)
+
+ def _get_server_status(self, start_time, end_time, port, cores):
+ end_time = time.time()
+ elapsed_time = end_time - start_time
+ stats = stats_pb2.ServerStats(time_elapsed=elapsed_time,
+ time_user=elapsed_time,
+ time_system=elapsed_time)
+ return control_pb2.ServerStatus(stats=stats, port=port, cores=cores)
+
+ def _create_server(self, config):
+ if config.server_type == control_pb2.SYNC_SERVER:
+ servicer = benchmark_server.BenchmarkServer()
+ server = services_pb2.beta_create_BenchmarkService_server(servicer)
+ elif config.server_type == control_pb2.ASYNC_GENERIC_SERVER:
+ resp_size = config.payload_config.bytebuf_params.resp_size
+ servicer = benchmark_server.GenericBenchmarkServer(resp_size)
+ method_implementations = {
+ ('grpc.testing.BenchmarkService', 'StreamingCall'):
+ utilities.stream_stream_inline(servicer.StreamingCall),
+ ('grpc.testing.BenchmarkService', 'UnaryCall'):
+ utilities.unary_unary_inline(servicer.UnaryCall),
+ }
+ server = implementations.server(method_implementations)
+ else:
+ raise Exception('Unsupported server type {}'.format(config.server_type))
+
+ if config.HasField('security_params'): # Use SSL
+ server_creds = implementations.ssl_server_credentials([(
+ resources.private_key(), resources.certificate_chain())])
+ port = server.add_secure_port('[::]:{}'.format(config.port), server_creds)
+ else:
+ port = server.add_insecure_port('[::]:{}'.format(config.port))
+
+ return (server, port)
+
+ def RunClient(self, request_iterator, context):
+ config = next(request_iterator).setup
+ client_runners = []
+ qps_data = histogram.Histogram(config.histogram_params.resolution,
+ config.histogram_params.max_possible)
+ start_time = time.time()
+
+ # Create a client for each channel
+ for i in xrange(config.client_channels):
+ server = config.server_targets[i % len(config.server_targets)]
+ runner = self._create_client_runner(server, config, qps_data)
+ client_runners.append(runner)
+ runner.start()
+
+ end_time = time.time()
+ yield self._get_client_status(start_time, end_time, qps_data)
+
+ # Respond to stat requests
+ for request in request_iterator:
+ end_time = time.time()
+ status = self._get_client_status(start_time, end_time, qps_data)
+ if request.mark.reset:
+ qps_data.reset()
+ start_time = time.time()
+ yield status
+
+ # Cleanup the clients
+ for runner in client_runners:
+ runner.stop()
+
+ def _get_client_status(self, start_time, end_time, qps_data):
+ latencies = qps_data.get_data()
+ end_time = time.time()
+ elapsed_time = end_time - start_time
+ stats = stats_pb2.ClientStats(latencies=latencies,
+ time_elapsed=elapsed_time,
+ time_user=elapsed_time,
+ time_system=elapsed_time)
+ return control_pb2.ClientStatus(stats=stats)
+
+ def _create_client_runner(self, server, config, qps_data):
+ if config.client_type == control_pb2.SYNC_CLIENT:
+ if config.rpc_type == control_pb2.UNARY:
+ client = benchmark_client.UnarySyncBenchmarkClient(
+ server, config, qps_data)
+ else:
+ raise Exception('STREAMING SYNC client not supported')
+ elif config.client_type == control_pb2.ASYNC_CLIENT:
+ if config.rpc_type == control_pb2.UNARY:
+ client = benchmark_client.UnaryAsyncBenchmarkClient(
+ server, config, qps_data)
+ elif config.rpc_type == control_pb2.STREAMING:
+ client = benchmark_client.StreamingAsyncBenchmarkClient(
+ server, config, qps_data)
+ else:
+ raise Exception('Unsupported client type {}'.format(config.client_type))
+
+ # In multi-channel tests, we split the load across all channels
+ load_factor = float(config.client_channels)
+ if config.load_params.WhichOneof('load') == 'closed_loop':
+ runner = client_runner.ClosedLoopClientRunner(
+ client, config.outstanding_rpcs_per_channel)
+ else: # Open loop Poisson
+ alpha = config.load_params.poisson.offered_load / load_factor
+ def poisson():
+ while True:
+ yield random.expovariate(alpha)
+
+ runner = client_runner.OpenLoopClientRunner(client, poisson())
+
+ return runner
+
+ def CoreCount(self, request, context):
+ return control_pb2.CoreResponse(cores=multiprocessing.cpu_count())
+
+ def QuitWorker(self, request, context):
+ self._quit_event.set()
+ return control_pb2.Void()
+
+ def wait_for_quit(self):
+ self._quit_event.wait()
diff --git a/src/python/grpcio/tests/unit/framework/face/testing/__init__.py b/src/python/grpcio/tests/stress/__init__.py
index 7086519106..100a624dc9 100644
--- a/src/python/grpcio/tests/unit/framework/face/testing/__init__.py
+++ b/src/python/grpcio/tests/stress/__init__.py
@@ -1,4 +1,4 @@
-# Copyright 2015, Google Inc.
+# Copyright 2016, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -26,5 +26,3 @@
# 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/tests/stress/client.py b/src/python/grpcio/tests/stress/client.py
new file mode 100644
index 0000000000..a733741b73
--- /dev/null
+++ b/src/python/grpcio/tests/stress/client.py
@@ -0,0 +1,132 @@
+# Copyright 2016, 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.
+
+"""Entry point for running stress tests."""
+
+import argparse
+import Queue
+import threading
+
+from grpc.beta import implementations
+from src.proto.grpc.testing import metrics_pb2
+from src.proto.grpc.testing import test_pb2
+
+from tests.interop import methods
+from tests.qps import histogram
+from tests.stress import metrics_server
+from tests.stress import test_runner
+
+
+def _args():
+ parser = argparse.ArgumentParser(description='gRPC Python stress test client')
+ parser.add_argument(
+ '--server_addresses',
+ help='comma seperated list of hostname:port to run servers on',
+ default='localhost:8080', type=str)
+ parser.add_argument(
+ '--test_cases',
+ help='comma seperated list of testcase:weighting of tests to run',
+ default='large_unary:100',
+ type=str)
+ parser.add_argument(
+ '--test_duration_secs',
+ help='number of seconds to run the stress test',
+ default=-1, type=int)
+ parser.add_argument(
+ '--num_channels_per_server',
+ help='number of channels per server',
+ default=1, type=int)
+ parser.add_argument(
+ '--num_stubs_per_channel',
+ help='number of stubs to create per channel',
+ default=1, type=int)
+ parser.add_argument(
+ '--metrics_port',
+ help='the port to listen for metrics requests on',
+ default=8081, type=int)
+ return parser.parse_args()
+
+
+def _test_case_from_arg(test_case_arg):
+ for test_case in methods.TestCase:
+ if test_case_arg == test_case.value:
+ return test_case
+ else:
+ raise ValueError('No test case {}!'.format(test_case_arg))
+
+
+def _parse_weighted_test_cases(test_case_args):
+ weighted_test_cases = {}
+ for test_case_arg in test_case_args.split(','):
+ name, weight = test_case_arg.split(':', 1)
+ test_case = _test_case_from_arg(name)
+ weighted_test_cases[test_case] = int(weight)
+ return weighted_test_cases
+
+
+def run_test(args):
+ test_cases = _parse_weighted_test_cases(args.test_cases)
+ test_servers = args.server_addresses.split(',')
+ # Propagate any client exceptions with a queue
+ exception_queue = Queue.Queue()
+ stop_event = threading.Event()
+ hist = histogram.Histogram(1, 1)
+ runners = []
+
+ server = metrics_pb2.beta_create_MetricsService_server(
+ metrics_server.MetricsServer(hist))
+ server.add_insecure_port('[::]:{}'.format(args.metrics_port))
+ server.start()
+
+ for test_server in test_servers:
+ host, port = test_server.split(':', 1)
+ for _ in xrange(args.num_channels_per_server):
+ channel = implementations.insecure_channel(host, int(port))
+ for _ in xrange(args.num_stubs_per_channel):
+ stub = test_pb2.beta_create_TestService_stub(channel)
+ runner = test_runner.TestRunner(stub, test_cases, hist,
+ exception_queue, stop_event)
+ runners.append(runner)
+
+ for runner in runners:
+ runner.start()
+ try:
+ raise exception_queue.get(block=True, timeout=args.test_duration_secs)
+ except Queue.Empty:
+ # No exceptions thrown, success
+ pass
+ finally:
+ stop_event.set()
+ for runner in runners:
+ runner.join()
+ runner = None
+ server.stop(0)
+
+if __name__ == '__main__':
+ run_test(_args())
diff --git a/src/python/grpcio/grpc/framework/alpha/exceptions.py b/src/python/grpcio/tests/stress/metrics_server.py
index 09359c5e94..b994e4643e 100644
--- a/src/python/grpcio/grpc/framework/alpha/exceptions.py
+++ b/src/python/grpcio/tests/stress/metrics_server.py
@@ -1,4 +1,4 @@
-# Copyright 2015, Google Inc.
+# Copyright 2016, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -27,21 +27,34 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-"""Exceptions raised by GRPC.
+"""MetricsService for publishing stress test qps data."""
-Only GRPC should instantiate and raise these exceptions.
-"""
-import abc
+import time
-import six
+from src.proto.grpc.testing import metrics_pb2
-class RpcError(six.with_metaclass(abc.ABCMeta, Exception)):
- """Common super type for all exceptions raised by GRPC."""
+GAUGE_NAME = 'python_overall_qps'
-class CancellationError(RpcError):
- """Indicates that an RPC has been cancelled."""
+class MetricsServer(metrics_pb2.BetaMetricsServiceServicer):
+ def __init__(self, histogram):
+ self._start_time = time.time()
+ self._histogram = histogram
-class ExpirationError(RpcError):
- """Indicates that an RPC has expired ("timed out")."""
+ def _get_qps(self):
+ count = self._histogram.get_data().count
+ delta = time.time() - self._start_time
+ self._histogram.reset()
+ self._start_time = time.time()
+ return int(count/delta)
+
+ def GetAllGauges(self, request, context):
+ qps = self._get_qps()
+ return [metrics_pb2.GaugeResponse(name=GAUGE_NAME, long_value=qps)]
+
+ def GetGauge(self, request, context):
+ if request.name != GAUGE_NAME:
+ raise Exception('Gauge {} does not exist'.format(request.name))
+ qps = self._get_qps()
+ return metrics_pb2.GaugeResponse(name=GAUGE_NAME, long_value=qps)
diff --git a/src/python/grpcio/grpc/framework/face/exceptions.py b/src/python/grpcio/tests/stress/test_runner.py
index f95455604d..88f13727e3 100644
--- a/src/python/grpcio/grpc/framework/face/exceptions.py
+++ b/src/python/grpcio/tests/stress/test_runner.py
@@ -1,4 +1,4 @@
-# Copyright 2015, Google Inc.
+# Copyright 2016, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -27,52 +27,47 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-"""Exceptions used in the Face layer of RPC Framework."""
-
-import abc
-
-import six
-
-
-class NoSuchMethodError(Exception):
- """Raised by customer code to indicate an unrecognized RPC method name.
-
- Attributes:
- name: The unrecognized name.
- """
-
- def __init__(self, name):
- """Constructor.
-
- Args:
- name: The unrecognized RPC method name.
- """
- super(NoSuchMethodError, self).__init__()
- self.name = name
-
-
-class RpcError(six.with_metaclass(abc.ABCMeta, Exception)):
- """Common super type for all exceptions raised by the Face layer.
-
- Only RPC Framework should instantiate and raise these exceptions.
- """
-
-
-class CancellationError(RpcError):
- """Indicates that an RPC has been cancelled."""
-
-
-class ExpirationError(RpcError):
- """Indicates that an RPC has expired ("timed out")."""
-
-
-class NetworkError(RpcError):
- """Indicates that some error occurred on the network."""
-
-
-class ServicedError(RpcError):
- """Indicates that the Serviced failed in the course of an RPC."""
-
-
-class ServicerError(RpcError):
- """Indicates that the Servicer failed in the course of servicing an RPC."""
+"""Thread that sends random weighted requests on a TestService stub."""
+
+import random
+import threading
+import time
+import traceback
+
+
+def _weighted_test_case_generator(weighted_cases):
+ weight_sum = sum(weighted_cases.itervalues())
+
+ while True:
+ val = random.uniform(0, weight_sum)
+ partial_sum = 0
+ for case in weighted_cases:
+ partial_sum += weighted_cases[case]
+ if val <= partial_sum:
+ yield case
+ break
+
+
+class TestRunner(threading.Thread):
+
+ def __init__(self, stub, test_cases, hist, exception_queue, stop_event):
+ super(TestRunner, self).__init__()
+ self._exception_queue = exception_queue
+ self._stop_event = stop_event
+ self._stub = stub
+ self._test_cases = _weighted_test_case_generator(test_cases)
+ self._histogram = hist
+
+ def run(self):
+ while not self._stop_event.is_set():
+ try:
+ test_case = next(self._test_cases)
+ start_time = time.time()
+ test_case.test_interoperability(self._stub, None)
+ end_time = time.time()
+ self._histogram.add((end_time - start_time)*1e9)
+ except Exception as e:
+ traceback.print_exc()
+ self._exception_queue.put(
+ Exception("An exception occured during test {}"
+ .format(test_case), e))
diff --git a/src/python/grpcio/tests/unit/framework/face/testing/base_util.py b/src/python/grpcio/tests/unit/framework/face/testing/base_util.py
deleted file mode 100644
index 59652b3e90..0000000000
--- a/src/python/grpcio/tests/unit/framework/face/testing/base_util.py
+++ /dev/null
@@ -1,102 +0,0 @@
-# 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 creating Base-layer objects for use in Face-layer tests."""
-
-import abc
-
-import six
-
-# interfaces is referenced from specification in this module.
-from grpc.framework.base import util as _base_util
-from grpc.framework.base import implementations
-from grpc.framework.base import in_memory
-from grpc.framework.base import interfaces # pylint: disable=unused-import
-from grpc.framework.foundation import logging_pool
-
-_POOL_SIZE_LIMIT = 5
-
-_MAXIMUM_TIMEOUT = 90
-
-
-class LinkedPair(six.with_metaclass(abc.ABCMeta)):
- """A Front and Back that are linked to one another.
-
- Attributes:
- front: An interfaces.Front.
- back: An interfaces.Back.
- """
-
- @abc.abstractmethod
- def shut_down(self):
- """Shuts down this object and releases its resources."""
- raise NotImplementedError()
-
-
-class _LinkedPair(LinkedPair):
-
- def __init__(self, front, back, pools):
- self.front = front
- self.back = back
- self._pools = pools
-
- def shut_down(self):
- _base_util.wait_for_idle(self.front)
- _base_util.wait_for_idle(self.back)
-
- for pool in self._pools:
- pool.shutdown(wait=True)
-
-
-def linked_pair(servicer, default_timeout):
- """Creates a Server and Stub linked together for use."""
- link_pool = logging_pool.pool(_POOL_SIZE_LIMIT)
- front_work_pool = logging_pool.pool(_POOL_SIZE_LIMIT)
- front_transmission_pool = logging_pool.pool(_POOL_SIZE_LIMIT)
- front_utility_pool = logging_pool.pool(_POOL_SIZE_LIMIT)
- back_work_pool = logging_pool.pool(_POOL_SIZE_LIMIT)
- back_transmission_pool = logging_pool.pool(_POOL_SIZE_LIMIT)
- back_utility_pool = logging_pool.pool(_POOL_SIZE_LIMIT)
- pools = (
- link_pool,
- front_work_pool, front_transmission_pool, front_utility_pool,
- back_work_pool, back_transmission_pool, back_utility_pool)
-
- link = in_memory.Link(link_pool)
- front = implementations.front_link(
- front_work_pool, front_transmission_pool, front_utility_pool)
- back = implementations.back_link(
- servicer, back_work_pool, back_transmission_pool, back_utility_pool,
- default_timeout, _MAXIMUM_TIMEOUT)
- front.join_rear_link(link)
- link.join_fore_link(front)
- back.join_fore_link(link)
- link.join_rear_link(back)
-
- return _LinkedPair(front, back, pools)
diff --git a/src/python/grpcio/tests/unit/framework/face/testing/blocking_invocation_inline_service_test_case.py b/src/python/grpcio/tests/unit/framework/face/testing/blocking_invocation_inline_service_test_case.py
deleted file mode 100644
index 2ebe1a32a4..0000000000
--- a/src/python/grpcio/tests/unit/framework/face/testing/blocking_invocation_inline_service_test_case.py
+++ /dev/null
@@ -1,224 +0,0 @@
-# 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.
-
-"""A test to verify an implementation of the Face layer of RPC Framework."""
-
-# unittest is referenced from specification in this module.
-import abc
-import unittest # pylint: disable=unused-import
-
-import six
-
-from grpc.framework.face import exceptions
-from tests.unit.framework.common import test_constants
-from tests.unit.framework.face.testing import control
-from tests.unit.framework.face.testing import coverage
-from tests.unit.framework.face.testing import digest
-from tests.unit.framework.face.testing import stock_service
-from tests.unit.framework.face.testing import test_case
-
-
-class BlockingInvocationInlineServiceTestCase(
- six.with_metaclass(abc.ABCMeta,
- test_case.FaceTestCase, coverage.BlockingCoverage)):
- """A test of the Face layer of RPC Framework.
-
- Concrete subclasses must also extend unittest.TestCase.
- """
-
- def setUp(self):
- """See unittest.TestCase.setUp for full specification.
-
- Overriding implementations must call this implementation.
- """
- self.control = control.PauseFailControl()
- self.digest = digest.digest(
- stock_service.STOCK_TEST_SERVICE, self.control, None)
-
- self.stub, self.memo = self.set_up_implementation(
- self.digest.name, self.digest.methods,
- self.digest.inline_method_implementations, None)
-
- def tearDown(self):
- """See unittest.TestCase.tearDown for full specification.
-
- Overriding implementations must call this implementation.
- """
- self.tear_down_implementation(self.memo)
-
- def testSuccessfulUnaryRequestUnaryResponse(self):
- for name, test_messages_sequence in (
- six.iteritems(self.digest.unary_unary_messages_sequences)):
- for test_messages in test_messages_sequence:
- request = test_messages.request()
-
- response = self.stub.blocking_value_in_value_out(
- name, request, test_constants.LONG_TIMEOUT)
-
- test_messages.verify(request, response, self)
-
- def testSuccessfulUnaryRequestStreamResponse(self):
- for name, test_messages_sequence in (
- six.iteritems(self.digest.unary_stream_messages_sequences)):
- for test_messages in test_messages_sequence:
- request = test_messages.request()
-
- response_iterator = self.stub.inline_value_in_stream_out(
- name, request, test_constants.LONG_TIMEOUT)
- responses = list(response_iterator)
-
- test_messages.verify(request, responses, self)
-
- def testSuccessfulStreamRequestUnaryResponse(self):
- for name, test_messages_sequence in (
- six.iteritems(self.digest.stream_unary_messages_sequences)):
- for test_messages in test_messages_sequence:
- requests = test_messages.requests()
-
- response = self.stub.blocking_stream_in_value_out(
- name, iter(requests), test_constants.LONG_TIMEOUT)
-
- test_messages.verify(requests, response, self)
-
- def testSuccessfulStreamRequestStreamResponse(self):
- for name, test_messages_sequence in (
- six.iteritems(self.digest.stream_stream_messages_sequences)):
- for test_messages in test_messages_sequence:
- requests = test_messages.requests()
-
- response_iterator = self.stub.inline_stream_in_stream_out(
- name, iter(requests), test_constants.LONG_TIMEOUT)
- responses = list(response_iterator)
-
- test_messages.verify(requests, responses, self)
-
- def testSequentialInvocations(self):
- for name, test_messages_sequence in (
- six.iteritems(self.digest.unary_unary_messages_sequences)):
- for test_messages in test_messages_sequence:
- first_request = test_messages.request()
- second_request = test_messages.request()
-
- first_response = self.stub.blocking_value_in_value_out(
- name, first_request, test_constants.SHORT_TIMEOUT)
-
- test_messages.verify(first_request, first_response, self)
-
- second_response = self.stub.blocking_value_in_value_out(
- name, second_request, test_constants.SHORT_TIMEOUT)
-
- test_messages.verify(second_request, second_response, self)
-
- def testExpiredUnaryRequestUnaryResponse(self):
- for name, test_messages_sequence in (
- six.iteritems(self.digest.unary_unary_messages_sequences)):
- for test_messages in test_messages_sequence:
- request = test_messages.request()
-
- with self.control.pause(), self.assertRaises(
- exceptions.ExpirationError):
- multi_callable = self.stub.unary_unary_multi_callable(name)
- multi_callable(request, test_constants.SHORT_TIMEOUT)
-
- def testExpiredUnaryRequestStreamResponse(self):
- for name, test_messages_sequence in (
- six.iteritems(self.digest.unary_stream_messages_sequences)):
- for test_messages in test_messages_sequence:
- request = test_messages.request()
-
- with self.control.pause(), self.assertRaises(
- exceptions.ExpirationError):
- response_iterator = self.stub.inline_value_in_stream_out(
- name, request, test_constants.SHORT_TIMEOUT)
- list(response_iterator)
-
- def testExpiredStreamRequestUnaryResponse(self):
- for name, test_messages_sequence in (
- six.iteritems(self.digest.stream_unary_messages_sequences)):
- for test_messages in test_messages_sequence:
- requests = test_messages.requests()
-
- with self.control.pause(), self.assertRaises(
- exceptions.ExpirationError):
- multi_callable = self.stub.stream_unary_multi_callable(name)
- multi_callable(iter(requests), test_constants.SHORT_TIMEOUT)
-
- def testExpiredStreamRequestStreamResponse(self):
- for name, test_messages_sequence in (
- six.iteritems(self.digest.stream_stream_messages_sequences)):
- for test_messages in test_messages_sequence:
- requests = test_messages.requests()
-
- with self.control.pause(), self.assertRaises(
- exceptions.ExpirationError):
- response_iterator = self.stub.inline_stream_in_stream_out(
- name, iter(requests), test_constants.SHORT_TIMEOUT)
- list(response_iterator)
-
- def testFailedUnaryRequestUnaryResponse(self):
- for name, test_messages_sequence in (
- six.iteritems(self.digest.unary_unary_messages_sequences)):
- for test_messages in test_messages_sequence:
- request = test_messages.request()
-
- with self.control.fail(), self.assertRaises(exceptions.ServicerError):
- self.stub.blocking_value_in_value_out(name, request,
- test_constants.SHORT_TIMEOUT)
-
- def testFailedUnaryRequestStreamResponse(self):
- for name, test_messages_sequence in (
- six.iteritems(self.digest.unary_stream_messages_sequences)):
- for test_messages in test_messages_sequence:
- request = test_messages.request()
-
- with self.control.fail(), self.assertRaises(exceptions.ServicerError):
- response_iterator = self.stub.inline_value_in_stream_out(
- name, request, test_constants.SHORT_TIMEOUT)
- list(response_iterator)
-
- def testFailedStreamRequestUnaryResponse(self):
- for name, test_messages_sequence in (
- six.iteritems(self.digest.stream_unary_messages_sequences)):
- for test_messages in test_messages_sequence:
- requests = test_messages.requests()
-
- with self.control.fail(), self.assertRaises(exceptions.ServicerError):
- self.stub.blocking_stream_in_value_out(name, iter(requests),
- test_constants.SHORT_TIMEOUT)
-
- def testFailedStreamRequestStreamResponse(self):
- for name, test_messages_sequence in (
- six.iteritems(self.digest.stream_stream_messages_sequences)):
- for test_messages in test_messages_sequence:
- requests = test_messages.requests()
-
- with self.control.fail(), self.assertRaises(exceptions.ServicerError):
- response_iterator = self.stub.inline_stream_in_stream_out(
- name, iter(requests), test_constants.SHORT_TIMEOUT)
- list(response_iterator)
diff --git a/src/python/grpcio/tests/unit/framework/face/testing/callback.py b/src/python/grpcio/tests/unit/framework/face/testing/callback.py
deleted file mode 100644
index d0e63c8c56..0000000000
--- a/src/python/grpcio/tests/unit/framework/face/testing/callback.py
+++ /dev/null
@@ -1,94 +0,0 @@
-# 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.
-
-"""A utility useful in tests of asynchronous, event-driven interfaces."""
-
-import threading
-
-from grpc.framework.foundation import stream
-
-
-class Callback(stream.Consumer):
- """A utility object useful in tests of asynchronous code."""
-
- def __init__(self):
- self._condition = threading.Condition()
- self._unary_response = None
- self._streamed_responses = []
- self._completed = False
- self._abortion = None
-
- def abort(self, abortion):
- with self._condition:
- self._abortion = abortion
- self._condition.notify_all()
-
- def complete(self, unary_response):
- with self._condition:
- self._unary_response = unary_response
- self._completed = True
- self._condition.notify_all()
-
- def consume(self, streamed_response):
- with self._condition:
- self._streamed_responses.append(streamed_response)
-
- def terminate(self):
- with self._condition:
- self._completed = True
- self._condition.notify_all()
-
- def consume_and_terminate(self, streamed_response):
- with self._condition:
- self._streamed_responses.append(streamed_response)
- self._completed = True
- self._condition.notify_all()
-
- def block_until_terminated(self):
- with self._condition:
- while self._abortion is None and not self._completed:
- self._condition.wait()
-
- def response(self):
- with self._condition:
- if self._abortion is None:
- return self._unary_response
- else:
- raise AssertionError('Aborted with abortion "%s"!' % self._abortion)
-
- def responses(self):
- with self._condition:
- if self._abortion is None:
- return list(self._streamed_responses)
- else:
- raise AssertionError('Aborted with abortion "%s"!' % self._abortion)
-
- def abortion(self):
- with self._condition:
- return self._abortion
diff --git a/src/python/grpcio/tests/unit/framework/face/testing/control.py b/src/python/grpcio/tests/unit/framework/face/testing/control.py
deleted file mode 100644
index 8425affcc9..0000000000
--- a/src/python/grpcio/tests/unit/framework/face/testing/control.py
+++ /dev/null
@@ -1,87 +0,0 @@
-# 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.
-
-"""Code for instructing systems under test to block or fail."""
-
-import abc
-import contextlib
-import threading
-
-import six
-
-
-class Control(six.with_metaclass(abc.ABCMeta)):
- """An object that accepts program control from a system under test.
-
- Systems under test passed a Control should call its control() method
- frequently during execution. The control() method may block, raise an
- exception, or do nothing, all according to the enclosing test's desire for
- the system under test to simulate hanging, failing, or functioning.
- """
-
- @abc.abstractmethod
- def control(self):
- """Potentially does anything."""
- raise NotImplementedError()
-
-
-class PauseFailControl(Control):
- """A Control that can be used to pause or fail code under control."""
-
- def __init__(self):
- self._condition = threading.Condition()
- self._paused = False
- self._fail = False
-
- def control(self):
- with self._condition:
- if self._fail:
- raise ValueError()
-
- while self._paused:
- self._condition.wait()
-
- @contextlib.contextmanager
- def pause(self):
- """Pauses code under control while controlling code is in context."""
- with self._condition:
- self._paused = True
- yield
- with self._condition:
- self._paused = False
- self._condition.notify_all()
-
- @contextlib.contextmanager
- def fail(self):
- """Fails code under control while controlling code is in context."""
- with self._condition:
- self._fail = True
- yield
- with self._condition:
- self._fail = False
diff --git a/src/python/grpcio/tests/unit/framework/face/testing/coverage.py b/src/python/grpcio/tests/unit/framework/face/testing/coverage.py
deleted file mode 100644
index 3c88b7841a..0000000000
--- a/src/python/grpcio/tests/unit/framework/face/testing/coverage.py
+++ /dev/null
@@ -1,121 +0,0 @@
-# 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.
-
-"""Governs coverage for the tests of the Face layer of RPC Framework."""
-
-import abc
-
-import six
-
-# These classes are only valid when inherited by unittest.TestCases.
-# pylint: disable=invalid-name
-
-
-class BlockingCoverage(six.with_metaclass(abc.ABCMeta)):
- """Specification of test coverage for blocking behaviors."""
-
- @abc.abstractmethod
- def testSuccessfulUnaryRequestUnaryResponse(self):
- raise NotImplementedError()
-
- @abc.abstractmethod
- def testSuccessfulUnaryRequestStreamResponse(self):
- raise NotImplementedError()
-
- @abc.abstractmethod
- def testSuccessfulStreamRequestUnaryResponse(self):
- raise NotImplementedError()
-
- @abc.abstractmethod
- def testSuccessfulStreamRequestStreamResponse(self):
- raise NotImplementedError()
-
- @abc.abstractmethod
- def testSequentialInvocations(self):
- raise NotImplementedError()
-
- @abc.abstractmethod
- def testExpiredUnaryRequestUnaryResponse(self):
- raise NotImplementedError()
-
- @abc.abstractmethod
- def testExpiredUnaryRequestStreamResponse(self):
- raise NotImplementedError()
-
- @abc.abstractmethod
- def testExpiredStreamRequestUnaryResponse(self):
- raise NotImplementedError()
-
- @abc.abstractmethod
- def testExpiredStreamRequestStreamResponse(self):
- raise NotImplementedError()
-
- @abc.abstractmethod
- def testFailedUnaryRequestUnaryResponse(self):
- raise NotImplementedError()
-
- @abc.abstractmethod
- def testFailedUnaryRequestStreamResponse(self):
- raise NotImplementedError()
-
- @abc.abstractmethod
- def testFailedStreamRequestUnaryResponse(self):
- raise NotImplementedError()
-
- @abc.abstractmethod
- def testFailedStreamRequestStreamResponse(self):
- raise NotImplementedError()
-
-
-class FullCoverage(six.with_metaclass(abc.ABCMeta, BlockingCoverage)):
- """Specification of test coverage for non-blocking behaviors."""
-
- @abc.abstractmethod
- def testParallelInvocations(self):
- raise NotImplementedError()
-
- @abc.abstractmethod
- def testWaitingForSomeButNotAllParallelInvocations(self):
- raise NotImplementedError()
-
- @abc.abstractmethod
- def testCancelledUnaryRequestUnaryResponse(self):
- raise NotImplementedError()
-
- @abc.abstractmethod
- def testCancelledUnaryRequestStreamResponse(self):
- raise NotImplementedError()
-
- @abc.abstractmethod
- def testCancelledStreamRequestUnaryResponse(self):
- raise NotImplementedError()
-
- @abc.abstractmethod
- def testCancelledStreamRequestStreamResponse(self):
- raise NotImplementedError()
diff --git a/src/python/grpcio/tests/unit/framework/face/testing/digest.py b/src/python/grpcio/tests/unit/framework/face/testing/digest.py
deleted file mode 100644
index 2b45aded20..0000000000
--- a/src/python/grpcio/tests/unit/framework/face/testing/digest.py
+++ /dev/null
@@ -1,452 +0,0 @@
-# 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.
-
-"""Code for making a service.TestService more amenable to use in tests."""
-
-import collections
-import threading
-
-import six
-
-# testing_control, interfaces, and testing_service are referenced from
-# specification in this module.
-from grpc.framework.common import cardinality
-from grpc.framework.common import style
-from grpc.framework.face import exceptions
-from grpc.framework.face import interfaces as face_interfaces
-from grpc.framework.foundation import stream
-from grpc.framework.foundation import stream_util
-from tests.unit.framework.face.testing import control as testing_control # pylint: disable=unused-import
-from tests.unit.framework.face.testing import interfaces # pylint: disable=unused-import
-from tests.unit.framework.face.testing import service as testing_service # pylint: disable=unused-import
-
-_IDENTITY = lambda x: x
-
-
-class TestServiceDigest(
- collections.namedtuple(
- 'TestServiceDigest',
- ['name',
- 'methods',
- 'inline_method_implementations',
- 'event_method_implementations',
- 'multi_method_implementation',
- 'unary_unary_messages_sequences',
- 'unary_stream_messages_sequences',
- 'stream_unary_messages_sequences',
- 'stream_stream_messages_sequences'])):
- """A transformation of a service.TestService.
-
- Attributes:
- name: The RPC service name to be used in the test.
- methods: A sequence of interfaces.Method objects describing the RPC
- methods that will be called during the test.
- inline_method_implementations: A dict from RPC method name to
- face_interfaces.MethodImplementation object to be used in tests of
- in-line calls to behaviors under test.
- event_method_implementations: A dict from RPC method name to
- face_interfaces.MethodImplementation object to be used in tests of
- event-driven calls to behaviors under test.
- multi_method_implementation: A face_interfaces.MultiMethodImplementation to
- be used in tests of generic calls to behaviors under test.
- unary_unary_messages_sequences: A dict from method name to sequence of
- service.UnaryUnaryTestMessages objects to be used to test the method
- with the given name.
- unary_stream_messages_sequences: A dict from method name to sequence of
- service.UnaryStreamTestMessages objects to be used to test the method
- with the given name.
- stream_unary_messages_sequences: A dict from method name to sequence of
- service.StreamUnaryTestMessages objects to be used to test the method
- with the given name.
- stream_stream_messages_sequences: A dict from method name to sequence of
- service.StreamStreamTestMessages objects to be used to test the
- method with the given name.
- serialization: A serial.Serialization object describing serialization
- behaviors for all the RPC methods.
- """
-
-
-class _BufferingConsumer(stream.Consumer):
- """A trivial Consumer that dumps what it consumes in a user-mutable buffer."""
-
- def __init__(self):
- self.consumed = []
- self.terminated = False
-
- def consume(self, value):
- self.consumed.append(value)
-
- def terminate(self):
- self.terminated = True
-
- def consume_and_terminate(self, value):
- self.consumed.append(value)
- self.terminated = True
-
-
-class _InlineUnaryUnaryMethod(face_interfaces.MethodImplementation):
-
- def __init__(self, unary_unary_test_method, control):
- self._test_method = unary_unary_test_method
- self._control = control
-
- self.cardinality = cardinality.Cardinality.UNARY_UNARY
- self.style = style.Service.INLINE
-
- def unary_unary_inline(self, request, context):
- response_list = []
- self._test_method.service(
- request, response_list.append, context, self._control)
- return response_list.pop(0)
-
-
-class _EventUnaryUnaryMethod(face_interfaces.MethodImplementation):
-
- def __init__(self, unary_unary_test_method, control, pool):
- self._test_method = unary_unary_test_method
- self._control = control
- self._pool = pool
-
- self.cardinality = cardinality.Cardinality.UNARY_UNARY
- self.style = style.Service.EVENT
-
- def unary_unary_event(self, request, response_callback, context):
- if self._pool is None:
- self._test_method.service(
- request, response_callback, context, self._control)
- else:
- self._pool.submit(
- self._test_method.service, request, response_callback, context,
- self._control)
-
-
-class _InlineUnaryStreamMethod(face_interfaces.MethodImplementation):
-
- def __init__(self, unary_stream_test_method, control):
- self._test_method = unary_stream_test_method
- self._control = control
-
- self.cardinality = cardinality.Cardinality.UNARY_STREAM
- self.style = style.Service.INLINE
-
- def unary_stream_inline(self, request, context):
- response_consumer = _BufferingConsumer()
- self._test_method.service(
- request, response_consumer, context, self._control)
- for response in response_consumer.consumed:
- yield response
-
-
-class _EventUnaryStreamMethod(face_interfaces.MethodImplementation):
-
- def __init__(self, unary_stream_test_method, control, pool):
- self._test_method = unary_stream_test_method
- self._control = control
- self._pool = pool
-
- self.cardinality = cardinality.Cardinality.UNARY_STREAM
- self.style = style.Service.EVENT
-
- def unary_stream_event(self, request, response_consumer, context):
- if self._pool is None:
- self._test_method.service(
- request, response_consumer, context, self._control)
- else:
- self._pool.submit(
- self._test_method.service, request, response_consumer, context,
- self._control)
-
-
-class _InlineStreamUnaryMethod(face_interfaces.MethodImplementation):
-
- def __init__(self, stream_unary_test_method, control):
- self._test_method = stream_unary_test_method
- self._control = control
-
- self.cardinality = cardinality.Cardinality.STREAM_UNARY
- self.style = style.Service.INLINE
-
- def stream_unary_inline(self, request_iterator, context):
- response_list = []
- request_consumer = self._test_method.service(
- response_list.append, context, self._control)
- for request in request_iterator:
- request_consumer.consume(request)
- request_consumer.terminate()
- return response_list.pop(0)
-
-
-class _EventStreamUnaryMethod(face_interfaces.MethodImplementation):
-
- def __init__(self, stream_unary_test_method, control, pool):
- self._test_method = stream_unary_test_method
- self._control = control
- self._pool = pool
-
- self.cardinality = cardinality.Cardinality.STREAM_UNARY
- self.style = style.Service.EVENT
-
- def stream_unary_event(self, response_callback, context):
- request_consumer = self._test_method.service(
- response_callback, context, self._control)
- if self._pool is None:
- return request_consumer
- else:
- return stream_util.ThreadSwitchingConsumer(request_consumer, self._pool)
-
-
-class _InlineStreamStreamMethod(face_interfaces.MethodImplementation):
-
- def __init__(self, stream_stream_test_method, control):
- self._test_method = stream_stream_test_method
- self._control = control
-
- self.cardinality = cardinality.Cardinality.STREAM_STREAM
- self.style = style.Service.INLINE
-
- def stream_stream_inline(self, request_iterator, context):
- response_consumer = _BufferingConsumer()
- request_consumer = self._test_method.service(
- response_consumer, context, self._control)
-
- for request in request_iterator:
- request_consumer.consume(request)
- while response_consumer.consumed:
- yield response_consumer.consumed.pop(0)
- response_consumer.terminate()
-
-
-class _EventStreamStreamMethod(face_interfaces.MethodImplementation):
-
- def __init__(self, stream_stream_test_method, control, pool):
- self._test_method = stream_stream_test_method
- self._control = control
- self._pool = pool
-
- self.cardinality = cardinality.Cardinality.STREAM_STREAM
- self.style = style.Service.EVENT
-
- def stream_stream_event(self, response_consumer, context):
- request_consumer = self._test_method.service(
- response_consumer, context, self._control)
- if self._pool is None:
- return request_consumer
- else:
- return stream_util.ThreadSwitchingConsumer(request_consumer, self._pool)
-
-
-class _UnaryConsumer(stream.Consumer):
- """A Consumer that only allows consumption of exactly one value."""
-
- def __init__(self, action):
- self._lock = threading.Lock()
- self._action = action
- self._consumed = False
- self._terminated = False
-
- def consume(self, value):
- with self._lock:
- if self._consumed:
- raise ValueError('Unary consumer already consumed!')
- elif self._terminated:
- raise ValueError('Unary consumer already terminated!')
- else:
- self._consumed = True
-
- self._action(value)
-
- def terminate(self):
- with self._lock:
- if not self._consumed:
- raise ValueError('Unary consumer hasn\'t yet consumed!')
- elif self._terminated:
- raise ValueError('Unary consumer already terminated!')
- else:
- self._terminated = True
-
- def consume_and_terminate(self, value):
- with self._lock:
- if self._consumed:
- raise ValueError('Unary consumer already consumed!')
- elif self._terminated:
- raise ValueError('Unary consumer already terminated!')
- else:
- self._consumed = True
- self._terminated = True
-
- self._action(value)
-
-
-class _UnaryUnaryAdaptation(object):
-
- def __init__(self, unary_unary_test_method):
- self._method = unary_unary_test_method
-
- def service(self, response_consumer, context, control):
- def action(request):
- self._method.service(
- request, response_consumer.consume_and_terminate, context, control)
- return _UnaryConsumer(action)
-
-
-class _UnaryStreamAdaptation(object):
-
- def __init__(self, unary_stream_test_method):
- self._method = unary_stream_test_method
-
- def service(self, response_consumer, context, control):
- def action(request):
- self._method.service(request, response_consumer, context, control)
- return _UnaryConsumer(action)
-
-
-class _StreamUnaryAdaptation(object):
-
- def __init__(self, stream_unary_test_method):
- self._method = stream_unary_test_method
-
- def service(self, response_consumer, context, control):
- return self._method.service(
- response_consumer.consume_and_terminate, context, control)
-
-
-class _MultiMethodImplementation(face_interfaces.MultiMethodImplementation):
-
- def __init__(self, methods, control, pool):
- self._methods = methods
- self._control = control
- self._pool = pool
-
- def service(self, name, response_consumer, context):
- method = self._methods.get(name, None)
- if method is None:
- raise exceptions.NoSuchMethodError(name)
- elif self._pool is None:
- return method(response_consumer, context, self._control)
- else:
- request_consumer = method(response_consumer, context, self._control)
- return stream_util.ThreadSwitchingConsumer(request_consumer, self._pool)
-
-
-class _Assembly(
- collections.namedtuple(
- '_Assembly',
- ['methods', 'inlines', 'events', 'adaptations', 'messages'])):
- """An intermediate structure created when creating a TestServiceDigest."""
-
-
-def _assemble(
- scenarios, names, inline_method_constructor, event_method_constructor,
- adapter, control, pool):
- """Creates an _Assembly from the given scenarios."""
- methods = []
- inlines = {}
- events = {}
- adaptations = {}
- messages = {}
- for name, scenario in six.iteritems(scenarios):
- if name in names:
- raise ValueError('Repeated name "%s"!' % name)
-
- test_method = scenario[0]
- inline_method = inline_method_constructor(test_method, control)
- event_method = event_method_constructor(test_method, control, pool)
- adaptation = adapter(test_method)
-
- methods.append(test_method)
- inlines[name] = inline_method
- events[name] = event_method
- adaptations[name] = adaptation
- messages[name] = scenario[1]
-
- return _Assembly(methods, inlines, events, adaptations, messages)
-
-
-def digest(service, control, pool):
- """Creates a TestServiceDigest from a TestService.
-
- Args:
- service: A testing_service.TestService.
- control: A testing_control.Control.
- pool: If RPC methods should be serviced in a separate thread, a thread pool.
- None if RPC methods should be serviced in the thread belonging to the
- run-time that calls for their service.
-
- Returns:
- A TestServiceDigest synthesized from the given service.TestService.
- """
- names = set()
-
- unary_unary = _assemble(
- service.unary_unary_scenarios(), names, _InlineUnaryUnaryMethod,
- _EventUnaryUnaryMethod, _UnaryUnaryAdaptation, control, pool)
- names.update(set(unary_unary.inlines))
-
- unary_stream = _assemble(
- service.unary_stream_scenarios(), names, _InlineUnaryStreamMethod,
- _EventUnaryStreamMethod, _UnaryStreamAdaptation, control, pool)
- names.update(set(unary_stream.inlines))
-
- stream_unary = _assemble(
- service.stream_unary_scenarios(), names, _InlineStreamUnaryMethod,
- _EventStreamUnaryMethod, _StreamUnaryAdaptation, control, pool)
- names.update(set(stream_unary.inlines))
-
- stream_stream = _assemble(
- service.stream_stream_scenarios(), names, _InlineStreamStreamMethod,
- _EventStreamStreamMethod, _IDENTITY, control, pool)
- names.update(set(stream_stream.inlines))
-
- methods = list(unary_unary.methods)
- methods.extend(unary_stream.methods)
- methods.extend(stream_unary.methods)
- methods.extend(stream_stream.methods)
- adaptations = dict(unary_unary.adaptations)
- adaptations.update(unary_stream.adaptations)
- adaptations.update(stream_unary.adaptations)
- adaptations.update(stream_stream.adaptations)
- inlines = dict(unary_unary.inlines)
- inlines.update(unary_stream.inlines)
- inlines.update(stream_unary.inlines)
- inlines.update(stream_stream.inlines)
- events = dict(unary_unary.events)
- events.update(unary_stream.events)
- events.update(stream_unary.events)
- events.update(stream_stream.events)
-
- return TestServiceDigest(
- service.name(),
- methods,
- inlines,
- events,
- _MultiMethodImplementation(adaptations, control, pool),
- unary_unary.messages,
- unary_stream.messages,
- stream_unary.messages,
- stream_stream.messages)
diff --git a/src/python/grpcio/tests/unit/framework/face/testing/event_invocation_synchronous_event_service_test_case.py b/src/python/grpcio/tests/unit/framework/face/testing/event_invocation_synchronous_event_service_test_case.py
deleted file mode 100644
index 98b61e492c..0000000000
--- a/src/python/grpcio/tests/unit/framework/face/testing/event_invocation_synchronous_event_service_test_case.py
+++ /dev/null
@@ -1,378 +0,0 @@
-# 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.
-
-"""A test to verify an implementation of the Face layer of RPC Framework."""
-
-import abc
-import unittest
-
-import six
-
-from grpc.framework.face import interfaces
-from tests.unit.framework.common import test_constants
-from tests.unit.framework.face.testing import callback as testing_callback
-from tests.unit.framework.face.testing import control
-from tests.unit.framework.face.testing import coverage
-from tests.unit.framework.face.testing import digest
-from tests.unit.framework.face.testing import stock_service
-from tests.unit.framework.face.testing import test_case
-
-
-class EventInvocationSynchronousEventServiceTestCase(
- six.with_metaclass(abc.ABCMeta,
- test_case.FaceTestCase, coverage.FullCoverage)):
- """A test of the Face layer of RPC Framework.
-
- Concrete subclasses must also extend unittest.TestCase.
- """
-
- def setUp(self):
- """See unittest.TestCase.setUp for full specification.
-
- Overriding implementations must call this implementation.
- """
- self.control = control.PauseFailControl()
- self.digest = digest.digest(
- stock_service.STOCK_TEST_SERVICE, self.control, None)
-
- self.stub, self.memo = self.set_up_implementation(
- self.digest.name, self.digest.methods,
- self.digest.event_method_implementations, None)
-
- def tearDown(self):
- """See unittest.TestCase.tearDown for full specification.
-
- Overriding implementations must call this implementation.
- """
- self.tear_down_implementation(self.memo)
-
- def testSuccessfulUnaryRequestUnaryResponse(self):
- for name, test_messages_sequence in (
- six.iteritems(self.digest.unary_unary_messages_sequences)):
- for test_messages in test_messages_sequence:
- request = test_messages.request()
- callback = testing_callback.Callback()
-
- self.stub.event_value_in_value_out(
- name, request, callback.complete, callback.abort,
- test_constants.SHORT_TIMEOUT)
- callback.block_until_terminated()
- response = callback.response()
-
- test_messages.verify(request, response, self)
-
- def testSuccessfulUnaryRequestStreamResponse(self):
- for name, test_messages_sequence in (
- six.iteritems(self.digest.unary_stream_messages_sequences)):
- for test_messages in test_messages_sequence:
- request = test_messages.request()
- callback = testing_callback.Callback()
-
- self.stub.event_value_in_stream_out(
- name, request, callback, callback.abort,
- test_constants.SHORT_TIMEOUT)
- callback.block_until_terminated()
- responses = callback.responses()
-
- test_messages.verify(request, responses, self)
-
- def testSuccessfulStreamRequestUnaryResponse(self):
- for name, test_messages_sequence in (
- six.iteritems(self.digest.stream_unary_messages_sequences)):
- for test_messages in test_messages_sequence:
- requests = test_messages.requests()
- callback = testing_callback.Callback()
-
- unused_call, request_consumer = self.stub.event_stream_in_value_out(
- name, callback.complete, callback.abort,
- test_constants.SHORT_TIMEOUT)
- for request in requests:
- request_consumer.consume(request)
- request_consumer.terminate()
- callback.block_until_terminated()
- response = callback.response()
-
- test_messages.verify(requests, response, self)
-
- def testSuccessfulStreamRequestStreamResponse(self):
- for name, test_messages_sequence in (
- six.iteritems(self.digest.stream_stream_messages_sequences)):
- for test_messages in test_messages_sequence:
- requests = test_messages.requests()
- callback = testing_callback.Callback()
-
- unused_call, request_consumer = self.stub.event_stream_in_stream_out(
- name, callback, callback.abort, test_constants.SHORT_TIMEOUT)
- for request in requests:
- request_consumer.consume(request)
- request_consumer.terminate()
- callback.block_until_terminated()
- responses = callback.responses()
-
- test_messages.verify(requests, responses, self)
-
- def testSequentialInvocations(self):
- # pylint: disable=cell-var-from-loop
- for name, test_messages_sequence in (
- six.iteritems(self.digest.unary_unary_messages_sequences)):
- for test_messages in test_messages_sequence:
- first_request = test_messages.request()
- second_request = test_messages.request()
- first_callback = testing_callback.Callback()
- second_callback = testing_callback.Callback()
-
- def make_second_invocation(first_response):
- first_callback.complete(first_response)
- self.stub.event_value_in_value_out(
- name, second_request, second_callback.complete,
- second_callback.abort, test_constants.SHORT_TIMEOUT)
-
- self.stub.event_value_in_value_out(
- name, first_request, make_second_invocation, first_callback.abort,
- test_constants.SHORT_TIMEOUT)
- second_callback.block_until_terminated()
-
- first_response = first_callback.response()
- second_response = second_callback.response()
- test_messages.verify(first_request, first_response, self)
- test_messages.verify(second_request, second_response, self)
-
- def testExpiredUnaryRequestUnaryResponse(self):
- for name, test_messages_sequence in (
- six.iteritems(self.digest.unary_unary_messages_sequences)):
- for test_messages in test_messages_sequence:
- request = test_messages.request()
- callback = testing_callback.Callback()
-
- with self.control.pause():
- self.stub.event_value_in_value_out(
- name, request, callback.complete, callback.abort,
- test_constants.SHORT_TIMEOUT)
- callback.block_until_terminated()
-
- self.assertEqual(interfaces.Abortion.EXPIRED, callback.abortion())
-
- def testExpiredUnaryRequestStreamResponse(self):
- for name, test_messages_sequence in (
- six.iteritems(self.digest.unary_stream_messages_sequences)):
- for test_messages in test_messages_sequence:
- request = test_messages.request()
- callback = testing_callback.Callback()
-
- with self.control.pause():
- self.stub.event_value_in_stream_out(
- name, request, callback, callback.abort,
- test_constants.SHORT_TIMEOUT)
- callback.block_until_terminated()
-
- self.assertEqual(interfaces.Abortion.EXPIRED, callback.abortion())
-
- def testExpiredStreamRequestUnaryResponse(self):
- for name, test_messages_sequence in (
- six.iteritems(self.digest.stream_unary_messages_sequences)):
- for unused_test_messages in test_messages_sequence:
- callback = testing_callback.Callback()
-
- self.stub.event_stream_in_value_out(
- name, callback.complete, callback.abort,
- test_constants.SHORT_TIMEOUT)
- callback.block_until_terminated()
-
- self.assertEqual(interfaces.Abortion.EXPIRED, callback.abortion())
-
- def testExpiredStreamRequestStreamResponse(self):
- for name, test_messages_sequence in (
- six.iteritems(self.digest.stream_stream_messages_sequences)):
- for test_messages in test_messages_sequence:
- requests = test_messages.requests()
- callback = testing_callback.Callback()
-
- unused_call, request_consumer = self.stub.event_stream_in_stream_out(
- name, callback, callback.abort, test_constants.SHORT_TIMEOUT)
- for request in requests:
- request_consumer.consume(request)
- callback.block_until_terminated()
-
- self.assertEqual(interfaces.Abortion.EXPIRED, callback.abortion())
-
- def testFailedUnaryRequestUnaryResponse(self):
- for name, test_messages_sequence in (
- six.iteritems(self.digest.unary_unary_messages_sequences)):
- for test_messages in test_messages_sequence:
- request = test_messages.request()
- callback = testing_callback.Callback()
-
- with self.control.fail():
- self.stub.event_value_in_value_out(
- name, request, callback.complete, callback.abort,
- test_constants.SHORT_TIMEOUT)
- callback.block_until_terminated()
-
- self.assertEqual(interfaces.Abortion.SERVICER_FAILURE,
- callback.abortion())
-
- def testFailedUnaryRequestStreamResponse(self):
- for name, test_messages_sequence in (
- six.iteritems(self.digest.unary_stream_messages_sequences)):
- for test_messages in test_messages_sequence:
- request = test_messages.request()
- callback = testing_callback.Callback()
-
- with self.control.fail():
- self.stub.event_value_in_stream_out(
- name, request, callback, callback.abort,
- test_constants.SHORT_TIMEOUT)
- callback.block_until_terminated()
-
- self.assertEqual(interfaces.Abortion.SERVICER_FAILURE,
- callback.abortion())
-
- def testFailedStreamRequestUnaryResponse(self):
- for name, test_messages_sequence in (
- six.iteritems(self.digest.stream_unary_messages_sequences)):
- for test_messages in test_messages_sequence:
- requests = test_messages.requests()
- callback = testing_callback.Callback()
-
- with self.control.fail():
- unused_call, request_consumer = self.stub.event_stream_in_value_out(
- name, callback.complete, callback.abort,
- test_constants.SHORT_TIMEOUT)
- for request in requests:
- request_consumer.consume(request)
- request_consumer.terminate()
- callback.block_until_terminated()
-
- self.assertEqual(interfaces.Abortion.SERVICER_FAILURE,
- callback.abortion())
-
- def testFailedStreamRequestStreamResponse(self):
- for name, test_messages_sequence in (
- six.iteritems(self.digest.stream_stream_messages_sequences)):
- for test_messages in test_messages_sequence:
- requests = test_messages.requests()
- callback = testing_callback.Callback()
-
- with self.control.fail():
- unused_call, request_consumer = self.stub.event_stream_in_stream_out(
- name, callback, callback.abort, test_constants.SHORT_TIMEOUT)
- for request in requests:
- request_consumer.consume(request)
- request_consumer.terminate()
- callback.block_until_terminated()
-
- self.assertEqual(interfaces.Abortion.SERVICER_FAILURE, callback.abortion())
-
- def testParallelInvocations(self):
- for name, test_messages_sequence in (
- six.iteritems(self.digest.unary_unary_messages_sequences)):
- for test_messages in test_messages_sequence:
- first_request = test_messages.request()
- first_callback = testing_callback.Callback()
- second_request = test_messages.request()
- second_callback = testing_callback.Callback()
-
- self.stub.event_value_in_value_out(
- name, first_request, first_callback.complete, first_callback.abort,
- test_constants.SHORT_TIMEOUT)
- self.stub.event_value_in_value_out(
- name, second_request, second_callback.complete,
- second_callback.abort, test_constants.SHORT_TIMEOUT)
- first_callback.block_until_terminated()
- second_callback.block_until_terminated()
-
- first_response = first_callback.response()
- second_response = second_callback.response()
- test_messages.verify(first_request, first_response, self)
- test_messages.verify(second_request, second_response, self)
-
- @unittest.skip('TODO(nathaniel): implement.')
- def testWaitingForSomeButNotAllParallelInvocations(self):
- raise NotImplementedError()
-
- def testCancelledUnaryRequestUnaryResponse(self):
- for name, test_messages_sequence in (
- six.iteritems(self.digest.unary_unary_messages_sequences)):
- for test_messages in test_messages_sequence:
- request = test_messages.request()
- callback = testing_callback.Callback()
-
- with self.control.pause():
- call = self.stub.event_value_in_value_out(
- name, request, callback.complete, callback.abort,
- test_constants.SHORT_TIMEOUT)
- call.cancel()
- callback.block_until_terminated()
-
- self.assertEqual(interfaces.Abortion.CANCELLED, callback.abortion())
-
- def testCancelledUnaryRequestStreamResponse(self):
- for name, test_messages_sequence in (
- six.iteritems(self.digest.unary_stream_messages_sequences)):
- for test_messages in test_messages_sequence:
- request = test_messages.request()
- callback = testing_callback.Callback()
-
- call = self.stub.event_value_in_stream_out(
- name, request, callback, callback.abort,
- test_constants.SHORT_TIMEOUT)
- call.cancel()
- callback.block_until_terminated()
-
- self.assertEqual(interfaces.Abortion.CANCELLED, callback.abortion())
-
- def testCancelledStreamRequestUnaryResponse(self):
- for name, test_messages_sequence in (
- six.iteritems(self.digest.stream_unary_messages_sequences)):
- for test_messages in test_messages_sequence:
- requests = test_messages.requests()
- callback = testing_callback.Callback()
-
- call, request_consumer = self.stub.event_stream_in_value_out(
- name, callback.complete, callback.abort,
- test_constants.SHORT_TIMEOUT)
- for request in requests:
- request_consumer.consume(request)
- call.cancel()
- callback.block_until_terminated()
-
- self.assertEqual(interfaces.Abortion.CANCELLED, callback.abortion())
-
- def testCancelledStreamRequestStreamResponse(self):
- for name, test_messages_sequence in (
- six.iteritems(self.digest.stream_stream_messages_sequences)):
- for unused_test_messages in test_messages_sequence:
- callback = testing_callback.Callback()
-
- call, unused_request_consumer = self.stub.event_stream_in_stream_out(
- name, callback, callback.abort, test_constants.SHORT_TIMEOUT)
- call.cancel()
- callback.block_until_terminated()
-
- self.assertEqual(interfaces.Abortion.CANCELLED, callback.abortion())
diff --git a/src/python/grpcio/tests/unit/framework/face/testing/future_invocation_asynchronous_event_service_test_case.py b/src/python/grpcio/tests/unit/framework/face/testing/future_invocation_asynchronous_event_service_test_case.py
deleted file mode 100644
index cae791af97..0000000000
--- a/src/python/grpcio/tests/unit/framework/face/testing/future_invocation_asynchronous_event_service_test_case.py
+++ /dev/null
@@ -1,384 +0,0 @@
-# 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.
-
-"""A test to verify an implementation of the Face layer of RPC Framework."""
-
-import abc
-import contextlib
-import threading
-import unittest
-
-import six
-
-from grpc.framework.face import exceptions
-from grpc.framework.foundation import future
-from grpc.framework.foundation import logging_pool
-from tests.unit.framework.common import test_constants
-from tests.unit.framework.face.testing import control
-from tests.unit.framework.face.testing import coverage
-from tests.unit.framework.face.testing import digest
-from tests.unit.framework.face.testing import stock_service
-from tests.unit.framework.face.testing import test_case
-
-_MAXIMUM_POOL_SIZE = 10
-
-
-class _PauseableIterator(object):
-
- def __init__(self, upstream):
- self._upstream = upstream
- self._condition = threading.Condition()
- self._paused = False
-
- @contextlib.contextmanager
- def pause(self):
- with self._condition:
- self._paused = True
- yield
- with self._condition:
- self._paused = False
- self._condition.notify_all()
-
- def __iter__(self):
- return self
-
- def __next__(self):
- return self.next()
-
- def next(self):
- with self._condition:
- while self._paused:
- self._condition.wait()
- return next(self._upstream)
-
-
-class FutureInvocationAsynchronousEventServiceTestCase(
- six.with_metaclass(abc.ABCMeta,
- test_case.FaceTestCase, coverage.FullCoverage)):
- """A test of the Face layer of RPC Framework.
-
- Concrete subclasses must also extend unittest.TestCase.
- """
-
- def setUp(self):
- """See unittest.TestCase.setUp for full specification.
-
- Overriding implementations must call this implementation.
- """
- self.control = control.PauseFailControl()
- self.digest_pool = logging_pool.pool(_MAXIMUM_POOL_SIZE)
- self.digest = digest.digest(
- stock_service.STOCK_TEST_SERVICE, self.control, self.digest_pool)
-
- self.stub, self.memo = self.set_up_implementation(
- self.digest.name, self.digest.methods,
- self.digest.event_method_implementations, None)
-
- def tearDown(self):
- """See unittest.TestCase.tearDown for full specification.
-
- Overriding implementations must call this implementation.
- """
- self.tear_down_implementation(self.memo)
- self.digest_pool.shutdown(wait=True)
-
- def testSuccessfulUnaryRequestUnaryResponse(self):
- for name, test_messages_sequence in (
- six.iteritems(self.digest.unary_unary_messages_sequences)):
- for test_messages in test_messages_sequence:
- request = test_messages.request()
-
- response_future = self.stub.future_value_in_value_out(
- name, request, test_constants.SHORT_TIMEOUT)
- response = response_future.result()
-
- test_messages.verify(request, response, self)
-
- def testSuccessfulUnaryRequestStreamResponse(self):
- for name, test_messages_sequence in (
- six.iteritems(self.digest.unary_stream_messages_sequences)):
- for test_messages in test_messages_sequence:
- request = test_messages.request()
-
- response_iterator = self.stub.inline_value_in_stream_out(
- name, request, test_constants.SHORT_TIMEOUT)
- responses = list(response_iterator)
-
- test_messages.verify(request, responses, self)
-
- def testSuccessfulStreamRequestUnaryResponse(self):
- for name, test_messages_sequence in (
- six.iteritems(self.digest.stream_unary_messages_sequences)):
- for test_messages in test_messages_sequence:
- requests = test_messages.requests()
- request_iterator = _PauseableIterator(iter(requests))
-
- # Use of a paused iterator of requests allows us to test that control is
- # returned to calling code before the iterator yields any requests.
- with request_iterator.pause():
- response_future = self.stub.future_stream_in_value_out(
- name, request_iterator, test_constants.SHORT_TIMEOUT)
- response = response_future.result()
-
- test_messages.verify(requests, response, self)
-
- def testSuccessfulStreamRequestStreamResponse(self):
- for name, test_messages_sequence in (
- six.iteritems(self.digest.stream_stream_messages_sequences)):
- for test_messages in test_messages_sequence:
- requests = test_messages.requests()
- request_iterator = _PauseableIterator(iter(requests))
-
- # Use of a paused iterator of requests allows us to test that control is
- # returned to calling code before the iterator yields any requests.
- with request_iterator.pause():
- response_iterator = self.stub.inline_stream_in_stream_out(
- name, request_iterator, test_constants.SHORT_TIMEOUT)
- responses = list(response_iterator)
-
- test_messages.verify(requests, responses, self)
-
- def testSequentialInvocations(self):
- for name, test_messages_sequence in (
- six.iteritems(self.digest.unary_unary_messages_sequences)):
- for test_messages in test_messages_sequence:
- first_request = test_messages.request()
- second_request = test_messages.request()
-
- first_response_future = self.stub.future_value_in_value_out(
- name, first_request, test_constants.SHORT_TIMEOUT)
- first_response = first_response_future.result()
-
- test_messages.verify(first_request, first_response, self)
-
- second_response_future = self.stub.future_value_in_value_out(
- name, second_request, test_constants.SHORT_TIMEOUT)
- second_response = second_response_future.result()
-
- test_messages.verify(second_request, second_response, self)
-
- def testExpiredUnaryRequestUnaryResponse(self):
- for name, test_messages_sequence in (
- six.iteritems(self.digest.unary_unary_messages_sequences)):
- for test_messages in test_messages_sequence:
- request = test_messages.request()
-
- with self.control.pause():
- multi_callable = self.stub.unary_unary_multi_callable(name)
- response_future = multi_callable.future(request,
- test_constants.SHORT_TIMEOUT)
- self.assertIsInstance(
- response_future.exception(), exceptions.ExpirationError)
- with self.assertRaises(exceptions.ExpirationError):
- response_future.result()
-
- def testExpiredUnaryRequestStreamResponse(self):
- for name, test_messages_sequence in (
- six.iteritems(self.digest.unary_stream_messages_sequences)):
- for test_messages in test_messages_sequence:
- request = test_messages.request()
-
- with self.control.pause():
- response_iterator = self.stub.inline_value_in_stream_out(
- name, request, test_constants.SHORT_TIMEOUT)
- with self.assertRaises(exceptions.ExpirationError):
- list(response_iterator)
-
- def testExpiredStreamRequestUnaryResponse(self):
- for name, test_messages_sequence in (
- six.iteritems(self.digest.stream_unary_messages_sequences)):
- for test_messages in test_messages_sequence:
- requests = test_messages.requests()
-
- with self.control.pause():
- multi_callable = self.stub.stream_unary_multi_callable(name)
- response_future = multi_callable.future(iter(requests),
- test_constants.SHORT_TIMEOUT)
- self.assertIsInstance(
- response_future.exception(), exceptions.ExpirationError)
- with self.assertRaises(exceptions.ExpirationError):
- response_future.result()
-
- def testExpiredStreamRequestStreamResponse(self):
- for name, test_messages_sequence in (
- six.iteritems(self.digest.stream_stream_messages_sequences)):
- for test_messages in test_messages_sequence:
- requests = test_messages.requests()
-
- with self.control.pause():
- response_iterator = self.stub.inline_stream_in_stream_out(
- name, iter(requests), test_constants.SHORT_TIMEOUT)
- with self.assertRaises(exceptions.ExpirationError):
- list(response_iterator)
-
- def testFailedUnaryRequestUnaryResponse(self):
- for name, test_messages_sequence in (
- six.iteritems(self.digest.unary_unary_messages_sequences)):
- for test_messages in test_messages_sequence:
- request = test_messages.request()
-
- with self.control.fail():
- response_future = self.stub.future_value_in_value_out(
- name, request, test_constants.SHORT_TIMEOUT)
-
- # Because the servicer fails outside of the thread from which the
- # servicer-side runtime called into it its failure is
- # indistinguishable from simply not having called its
- # response_callback before the expiration of the RPC.
- self.assertIsInstance(
- response_future.exception(), exceptions.ExpirationError)
- with self.assertRaises(exceptions.ExpirationError):
- response_future.result()
-
- def testFailedUnaryRequestStreamResponse(self):
- for name, test_messages_sequence in (
- six.iteritems(self.digest.unary_stream_messages_sequences)):
- for test_messages in test_messages_sequence:
- request = test_messages.request()
-
- # Because the servicer fails outside of the thread from which the
- # servicer-side runtime called into it its failure is indistinguishable
- # from simply not having called its response_consumer before the
- # expiration of the RPC.
- with self.control.fail(), self.assertRaises(exceptions.ExpirationError):
- response_iterator = self.stub.inline_value_in_stream_out(
- name, request, test_constants.SHORT_TIMEOUT)
- list(response_iterator)
-
- def testFailedStreamRequestUnaryResponse(self):
- for name, test_messages_sequence in (
- six.iteritems(self.digest.stream_unary_messages_sequences)):
- for test_messages in test_messages_sequence:
- requests = test_messages.requests()
-
- with self.control.fail():
- response_future = self.stub.future_stream_in_value_out(
- name, iter(requests), test_constants.SHORT_TIMEOUT)
-
- # Because the servicer fails outside of the thread from which the
- # servicer-side runtime called into it its failure is
- # indistinguishable from simply not having called its
- # response_callback before the expiration of the RPC.
- self.assertIsInstance(
- response_future.exception(), exceptions.ExpirationError)
- with self.assertRaises(exceptions.ExpirationError):
- response_future.result()
-
- def testFailedStreamRequestStreamResponse(self):
- for name, test_messages_sequence in (
- six.iteritems(self.digest.stream_stream_messages_sequences)):
- for test_messages in test_messages_sequence:
- requests = test_messages.requests()
-
- # Because the servicer fails outside of the thread from which the
- # servicer-side runtime called into it its failure is indistinguishable
- # from simply not having called its response_consumer before the
- # expiration of the RPC.
- with self.control.fail(), self.assertRaises(exceptions.ExpirationError):
- response_iterator = self.stub.inline_stream_in_stream_out(
- name, iter(requests), test_constants.SHORT_TIMEOUT)
- list(response_iterator)
-
- def testParallelInvocations(self):
- for name, test_messages_sequence in (
- six.iteritems(self.digest.unary_unary_messages_sequences)):
- for test_messages in test_messages_sequence:
- first_request = test_messages.request()
- second_request = test_messages.request()
-
- # TODO(bug 2039): use LONG_TIMEOUT instead
- first_response_future = self.stub.future_value_in_value_out(
- name, first_request, test_constants.SHORT_TIMEOUT)
- second_response_future = self.stub.future_value_in_value_out(
- name, second_request, test_constants.SHORT_TIMEOUT)
- first_response = first_response_future.result()
- second_response = second_response_future.result()
-
- test_messages.verify(first_request, first_response, self)
- test_messages.verify(second_request, second_response, self)
-
- @unittest.skip('TODO(nathaniel): implement.')
- def testWaitingForSomeButNotAllParallelInvocations(self):
- raise NotImplementedError()
-
- def testCancelledUnaryRequestUnaryResponse(self):
- for name, test_messages_sequence in (
- six.iteritems(self.digest.unary_unary_messages_sequences)):
- for test_messages in test_messages_sequence:
- request = test_messages.request()
-
- with self.control.pause():
- response_future = self.stub.future_value_in_value_out(
- name, request, test_constants.SHORT_TIMEOUT)
- cancel_method_return_value = response_future.cancel()
-
- self.assertFalse(cancel_method_return_value)
- self.assertTrue(response_future.cancelled())
-
- def testCancelledUnaryRequestStreamResponse(self):
- for name, test_messages_sequence in (
- six.iteritems(self.digest.unary_stream_messages_sequences)):
- for test_messages in test_messages_sequence:
- request = test_messages.request()
-
- with self.control.pause():
- response_iterator = self.stub.inline_value_in_stream_out(
- name, request, test_constants.SHORT_TIMEOUT)
- response_iterator.cancel()
-
- with self.assertRaises(future.CancelledError):
- next(response_iterator)
-
- def testCancelledStreamRequestUnaryResponse(self):
- for name, test_messages_sequence in (
- six.iteritems(self.digest.stream_unary_messages_sequences)):
- for test_messages in test_messages_sequence:
- requests = test_messages.requests()
-
- with self.control.pause():
- response_future = self.stub.future_stream_in_value_out(
- name, iter(requests), test_constants.SHORT_TIMEOUT)
- cancel_method_return_value = response_future.cancel()
-
- self.assertFalse(cancel_method_return_value)
- self.assertTrue(response_future.cancelled())
-
- def testCancelledStreamRequestStreamResponse(self):
- for name, test_messages_sequence in (
- six.iteritems(self.digest.stream_stream_messages_sequences)):
- for test_messages in test_messages_sequence:
- requests = test_messages.requests()
-
- with self.control.pause():
- response_iterator = self.stub.inline_stream_in_stream_out(
- name, iter(requests), test_constants.SHORT_TIMEOUT)
- response_iterator.cancel()
-
- with self.assertRaises(future.CancelledError):
- next(response_iterator)
diff --git a/src/python/grpcio/tests/unit/framework/face/testing/interfaces.py b/src/python/grpcio/tests/unit/framework/face/testing/interfaces.py
deleted file mode 100644
index 8a25f89c88..0000000000
--- a/src/python/grpcio/tests/unit/framework/face/testing/interfaces.py
+++ /dev/null
@@ -1,118 +0,0 @@
-# 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 implemented by data sets used in Face-layer tests."""
-
-import abc
-
-import six
-
-# cardinality is referenced from specification in this module.
-from grpc.framework.common import cardinality # pylint: disable=unused-import
-
-
-class Method(six.with_metaclass(abc.ABCMeta)):
- """An RPC method to be used in tests of RPC implementations."""
-
- @abc.abstractmethod
- def name(self):
- """Identify the name of the method.
-
- Returns:
- The name of the method.
- """
- raise NotImplementedError()
-
- @abc.abstractmethod
- def cardinality(self):
- """Identify the cardinality of the method.
-
- Returns:
- A cardinality.Cardinality value describing the streaming semantics of the
- method.
- """
- raise NotImplementedError()
-
- @abc.abstractmethod
- def request_class(self):
- """Identify the class used for the method's request objects.
-
- Returns:
- The class object of the class to which the method's request objects
- belong.
- """
- raise NotImplementedError()
-
- @abc.abstractmethod
- def response_class(self):
- """Identify the class used for the method's response objects.
-
- Returns:
- The class object of the class to which the method's response objects
- belong.
- """
- raise NotImplementedError()
-
- @abc.abstractmethod
- def serialize_request(self, request):
- """Serialize the given request object.
-
- Args:
- request: A request object appropriate for this method.
- """
- raise NotImplementedError()
-
- @abc.abstractmethod
- def deserialize_request(self, serialized_request):
- """Synthesize a request object from a given bytestring.
-
- Args:
- serialized_request: A bytestring deserializable into a request object
- appropriate for this method.
- """
- raise NotImplementedError()
-
- @abc.abstractmethod
- def serialize_response(self, response):
- """Serialize the given response object.
-
- Args:
- response: A response object appropriate for this method.
- """
- raise NotImplementedError()
-
- @abc.abstractmethod
- def deserialize_response(self, serialized_response):
- """Synthesize a response object from a given bytestring.
-
- Args:
- serialized_response: A bytestring deserializable into a response object
- appropriate for this method.
- """
- raise NotImplementedError()
diff --git a/src/python/grpcio/tests/unit/framework/face/testing/service.py b/src/python/grpcio/tests/unit/framework/face/testing/service.py
deleted file mode 100644
index 3e4228cc07..0000000000
--- a/src/python/grpcio/tests/unit/framework/face/testing/service.py
+++ /dev/null
@@ -1,321 +0,0 @@
-# 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.
-
-"""Private interfaces implemented by data sets used in Face-layer tests."""
-
-import abc
-
-import six
-
-# interfaces is referenced from specification in this module.
-from grpc.framework.face import interfaces as face_interfaces # pylint: disable=unused-import
-from tests.unit.framework.face.testing import interfaces
-
-
-class UnaryUnaryTestMethodImplementation(six.with_metaclass(abc.ABCMeta, interfaces.Method)):
- """A controllable implementation of a unary-unary RPC method."""
-
- @abc.abstractmethod
- def service(self, request, response_callback, context, control):
- """Services an RPC that accepts one message and produces one message.
-
- Args:
- request: The single request message for the RPC.
- response_callback: A callback to be called to accept the response message
- of the RPC.
- context: An face_interfaces.RpcContext object.
- control: A test_control.Control to control execution of this method.
-
- Raises:
- abandonment.Abandoned: May or may not be raised when the RPC has been
- aborted.
- """
- raise NotImplementedError()
-
-
-class UnaryUnaryTestMessages(six.with_metaclass(abc.ABCMeta)):
- """A type for unary-request-unary-response message pairings."""
-
- @abc.abstractmethod
- def request(self):
- """Affords a request message.
-
- Implementations of this method should return a different message with each
- call so that multiple test executions of the test method may be made with
- different inputs.
-
- Returns:
- A request message.
- """
- raise NotImplementedError()
-
- @abc.abstractmethod
- def verify(self, request, response, test_case):
- """Verifies that the computed response matches the given request.
-
- Args:
- request: A request message.
- response: A response message.
- test_case: A unittest.TestCase object affording useful assertion methods.
-
- Raises:
- AssertionError: If the request and response do not match, indicating that
- there was some problem executing the RPC under test.
- """
- raise NotImplementedError()
-
-
-class UnaryStreamTestMethodImplementation(six.with_metaclass(abc.ABCMeta, interfaces.Method)):
- """A controllable implementation of a unary-stream RPC method."""
-
- @abc.abstractmethod
- def service(self, request, response_consumer, context, control):
- """Services an RPC that takes one message and produces a stream of messages.
-
- Args:
- request: The single request message for the RPC.
- response_consumer: A stream.Consumer to be called to accept the response
- messages of the RPC.
- context: A face_interfaces.RpcContext object.
- control: A test_control.Control to control execution of this method.
-
- Raises:
- abandonment.Abandoned: May or may not be raised when the RPC has been
- aborted.
- """
- raise NotImplementedError()
-
-
-class UnaryStreamTestMessages(six.with_metaclass(abc.ABCMeta)):
- """A type for unary-request-stream-response message pairings."""
-
- @abc.abstractmethod
- def request(self):
- """Affords a request message.
-
- Implementations of this method should return a different message with each
- call so that multiple test executions of the test method may be made with
- different inputs.
-
- Returns:
- A request message.
- """
- raise NotImplementedError()
-
- @abc.abstractmethod
- def verify(self, request, responses, test_case):
- """Verifies that the computed responses match the given request.
-
- Args:
- request: A request message.
- responses: A sequence of response messages.
- test_case: A unittest.TestCase object affording useful assertion methods.
-
- Raises:
- AssertionError: If the request and responses do not match, indicating that
- there was some problem executing the RPC under test.
- """
- raise NotImplementedError()
-
-
-class StreamUnaryTestMethodImplementation(six.with_metaclass(abc.ABCMeta, interfaces.Method)):
- """A controllable implementation of a stream-unary RPC method."""
-
- @abc.abstractmethod
- def service(self, response_callback, context, control):
- """Services an RPC that takes a stream of messages and produces one message.
-
- Args:
- response_callback: A callback to be called to accept the response message
- of the RPC.
- context: A face_interfaces.RpcContext object.
- control: A test_control.Control to control execution of this method.
-
- Returns:
- A stream.Consumer with which to accept the request messages 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 messages 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.
- """
- raise NotImplementedError()
-
-
-class StreamUnaryTestMessages(six.with_metaclass(abc.ABCMeta)):
- """A type for stream-request-unary-response message pairings."""
-
- @abc.abstractmethod
- def requests(self):
- """Affords a sequence of request messages.
-
- Implementations of this method should return a different sequences with each
- call so that multiple test executions of the test method may be made with
- different inputs.
-
- Returns:
- A sequence of request messages.
- """
- raise NotImplementedError()
-
- @abc.abstractmethod
- def verify(self, requests, response, test_case):
- """Verifies that the computed response matches the given requests.
-
- Args:
- requests: A sequence of request messages.
- response: A response message.
- test_case: A unittest.TestCase object affording useful assertion methods.
-
- Raises:
- AssertionError: If the requests and response do not match, indicating that
- there was some problem executing the RPC under test.
- """
- raise NotImplementedError()
-
-
-class StreamStreamTestMethodImplementation(six.with_metaclass(abc.ABCMeta, interfaces.Method)):
- """A controllable implementation of a stream-stream RPC method."""
-
- @abc.abstractmethod
- def service(self, response_consumer, context, control):
- """Services an RPC that accepts and produces streams of messages.
-
- Args:
- response_consumer: A stream.Consumer to be called to accept the response
- messages of the RPC.
- context: A face_interfaces.RpcContext object.
- control: A test_control.Control to control execution of this method.
-
- Returns:
- A stream.Consumer with which to accept the request messages 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 messages 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.
- """
- raise NotImplementedError()
-
-
-class StreamStreamTestMessages(six.with_metaclass(abc.ABCMeta)):
- """A type for stream-request-stream-response message pairings."""
-
- @abc.abstractmethod
- def requests(self):
- """Affords a sequence of request messages.
-
- Implementations of this method should return a different sequences with each
- call so that multiple test executions of the test method may be made with
- different inputs.
-
- Returns:
- A sequence of request messages.
- """
- raise NotImplementedError()
-
- @abc.abstractmethod
- def verify(self, requests, responses, test_case):
- """Verifies that the computed response matches the given requests.
-
- Args:
- requests: A sequence of request messages.
- responses: A sequence of response messages.
- test_case: A unittest.TestCase object affording useful assertion methods.
-
- Raises:
- AssertionError: If the requests and responses do not match, indicating
- that there was some problem executing the RPC under test.
- """
- raise NotImplementedError()
-
-
-class TestService(six.with_metaclass(abc.ABCMeta)):
- """A specification of implemented RPC methods to use in tests."""
-
- @abc.abstractmethod
- def name(self):
- """Identifies the RPC service name used during the test.
-
- Returns:
- The RPC service name to be used for the test.
- """
- raise NotImplementedError()
-
- @abc.abstractmethod
- def unary_unary_scenarios(self):
- """Affords unary-request-unary-response test methods and their messages.
-
- Returns:
- A dict from method name to pair. The first element of the pair
- is a UnaryUnaryTestMethodImplementation object and the second element
- is a sequence of UnaryUnaryTestMethodMessages objects.
- """
- raise NotImplementedError()
-
- @abc.abstractmethod
- def unary_stream_scenarios(self):
- """Affords unary-request-stream-response test methods and their messages.
-
- Returns:
- A dict from method name to pair. The first element of the pair is a
- UnaryStreamTestMethodImplementation object and the second element is a
- sequence of UnaryStreamTestMethodMessages objects.
- """
- raise NotImplementedError()
-
- @abc.abstractmethod
- def stream_unary_scenarios(self):
- """Affords stream-request-unary-response test methods and their messages.
-
- Returns:
- A dict from method name to pair. The first element of the pair is a
- StreamUnaryTestMethodImplementation object and the second element is a
- sequence of StreamUnaryTestMethodMessages objects.
- """
- raise NotImplementedError()
-
- @abc.abstractmethod
- def stream_stream_scenarios(self):
- """Affords stream-request-stream-response test methods and their messages.
-
- Returns:
- A dict from method name to pair. The first element of the pair is a
- StreamStreamTestMethodImplementation object and the second element is a
- sequence of StreamStreamTestMethodMessages objects.
- """
- raise NotImplementedError()
diff --git a/src/python/grpcio/tests/unit/framework/face/testing/stock_service.py b/src/python/grpcio/tests/unit/framework/face/testing/stock_service.py
deleted file mode 100644
index 117c723f79..0000000000
--- a/src/python/grpcio/tests/unit/framework/face/testing/stock_service.py
+++ /dev/null
@@ -1,374 +0,0 @@
-# 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.
-
-"""Examples of Python implementations of the stock.proto Stock service."""
-
-from grpc.framework.common import cardinality
-from grpc.framework.foundation import abandonment
-from grpc.framework.foundation import stream
-from grpc.framework.foundation import stream_util
-from tests.unit.framework.face.testing import service
-from tests.unit._junkdrawer import stock_pb2
-
-SYMBOL_FORMAT = 'test symbol:%03d'
-STREAM_LENGTH = 400
-
-# A test-appropriate security-pricing function. :-P
-_price = lambda symbol_name: float(hash(symbol_name) % 4096)
-
-
-def _get_last_trade_price(stock_request, stock_reply_callback, control, active):
- """A unary-request, unary-response test method."""
- control.control()
- if active():
- stock_reply_callback(
- stock_pb2.StockReply(
- symbol=stock_request.symbol, price=_price(stock_request.symbol)))
- else:
- raise abandonment.Abandoned()
-
-
-def _get_last_trade_price_multiple(stock_reply_consumer, control, active):
- """A stream-request, stream-response test method."""
- def stock_reply_for_stock_request(stock_request):
- control.control()
- if active():
- return stock_pb2.StockReply(
- symbol=stock_request.symbol, price=_price(stock_request.symbol))
- else:
- raise abandonment.Abandoned()
- return stream_util.TransformingConsumer(
- stock_reply_for_stock_request, stock_reply_consumer)
-
-
-def _watch_future_trades(stock_request, stock_reply_consumer, control, active):
- """A unary-request, stream-response test method."""
- base_price = _price(stock_request.symbol)
- for index in range(stock_request.num_trades_to_watch):
- control.control()
- if active():
- stock_reply_consumer.consume(
- stock_pb2.StockReply(
- symbol=stock_request.symbol, price=base_price + index))
- else:
- raise abandonment.Abandoned()
- stock_reply_consumer.terminate()
-
-
-def _get_highest_trade_price(stock_reply_callback, control, active):
- """A stream-request, unary-response test method."""
-
- class StockRequestConsumer(stream.Consumer):
- """Keeps an ongoing record of the most valuable symbol yet consumed."""
-
- def __init__(self):
- self._symbol = None
- self._price = None
-
- def consume(self, stock_request):
- control.control()
- if active():
- if self._price is None:
- self._symbol = stock_request.symbol
- self._price = _price(stock_request.symbol)
- else:
- candidate_price = _price(stock_request.symbol)
- if self._price < candidate_price:
- self._symbol = stock_request.symbol
- self._price = candidate_price
-
- def terminate(self):
- control.control()
- if active():
- if self._symbol is None:
- raise ValueError()
- else:
- stock_reply_callback(
- stock_pb2.StockReply(symbol=self._symbol, price=self._price))
- self._symbol = None
- self._price = None
-
- def consume_and_terminate(self, stock_request):
- control.control()
- if active():
- if self._price is None:
- stock_reply_callback(
- stock_pb2.StockReply(
- symbol=stock_request.symbol,
- price=_price(stock_request.symbol)))
- else:
- candidate_price = _price(stock_request.symbol)
- if self._price < candidate_price:
- stock_reply_callback(
- stock_pb2.StockReply(
- symbol=stock_request.symbol, price=candidate_price))
- else:
- stock_reply_callback(
- stock_pb2.StockReply(
- symbol=self._symbol, price=self._price))
-
- self._symbol = None
- self._price = None
-
- return StockRequestConsumer()
-
-
-class GetLastTradePrice(service.UnaryUnaryTestMethodImplementation):
- """GetLastTradePrice for use in tests."""
-
- def name(self):
- return 'GetLastTradePrice'
-
- def cardinality(self):
- return cardinality.Cardinality.UNARY_UNARY
-
- def request_class(self):
- return stock_pb2.StockRequest
-
- def response_class(self):
- return stock_pb2.StockReply
-
- def serialize_request(self, request):
- return request.SerializeToString()
-
- def deserialize_request(self, serialized_request):
- return stock_pb2.StockRequest.FromString(serialized_request)
-
- def serialize_response(self, response):
- return response.SerializeToString()
-
- def deserialize_response(self, serialized_response):
- return stock_pb2.StockReply.FromString(serialized_response)
-
- def service(self, request, response_callback, context, control):
- _get_last_trade_price(
- request, response_callback, control, context.is_active)
-
-
-class GetLastTradePriceMessages(service.UnaryUnaryTestMessages):
-
- def __init__(self):
- self._index = 0
-
- def request(self):
- symbol = SYMBOL_FORMAT % self._index
- self._index += 1
- return stock_pb2.StockRequest(symbol=symbol)
-
- def verify(self, request, response, test_case):
- test_case.assertEqual(request.symbol, response.symbol)
- test_case.assertEqual(_price(request.symbol), response.price)
-
-
-class GetLastTradePriceMultiple(service.StreamStreamTestMethodImplementation):
- """GetLastTradePriceMultiple for use in tests."""
-
- def name(self):
- return 'GetLastTradePriceMultiple'
-
- def cardinality(self):
- return cardinality.Cardinality.STREAM_STREAM
-
- def request_class(self):
- return stock_pb2.StockRequest
-
- def response_class(self):
- return stock_pb2.StockReply
-
- def serialize_request(self, request):
- return request.SerializeToString()
-
- def deserialize_request(self, serialized_request):
- return stock_pb2.StockRequest.FromString(serialized_request)
-
- def serialize_response(self, response):
- return response.SerializeToString()
-
- def deserialize_response(self, serialized_response):
- return stock_pb2.StockReply.FromString(serialized_response)
-
- def service(self, response_consumer, context, control):
- return _get_last_trade_price_multiple(
- response_consumer, control, context.is_active)
-
-
-class GetLastTradePriceMultipleMessages(service.StreamStreamTestMessages):
- """Pairs of message streams for use with GetLastTradePriceMultiple."""
-
- def __init__(self):
- self._index = 0
-
- def requests(self):
- base_index = self._index
- self._index += 1
- return [
- stock_pb2.StockRequest(symbol=SYMBOL_FORMAT % (base_index + index))
- for index in range(STREAM_LENGTH)]
-
- def verify(self, requests, responses, test_case):
- test_case.assertEqual(len(requests), len(responses))
- for stock_request, stock_reply in zip(requests, responses):
- test_case.assertEqual(stock_request.symbol, stock_reply.symbol)
- test_case.assertEqual(_price(stock_request.symbol), stock_reply.price)
-
-
-class WatchFutureTrades(service.UnaryStreamTestMethodImplementation):
- """WatchFutureTrades for use in tests."""
-
- def name(self):
- return 'WatchFutureTrades'
-
- def cardinality(self):
- return cardinality.Cardinality.UNARY_STREAM
-
- def request_class(self):
- return stock_pb2.StockRequest
-
- def response_class(self):
- return stock_pb2.StockReply
-
- def serialize_request(self, request):
- return request.SerializeToString()
-
- def deserialize_request(self, serialized_request):
- return stock_pb2.StockRequest.FromString(serialized_request)
-
- def serialize_response(self, response):
- return response.SerializeToString()
-
- def deserialize_response(self, serialized_response):
- return stock_pb2.StockReply.FromString(serialized_response)
-
- def service(self, request, response_consumer, context, control):
- _watch_future_trades(request, response_consumer, control, context.is_active)
-
-
-class WatchFutureTradesMessages(service.UnaryStreamTestMessages):
- """Pairs of a single request message and a sequence of response messages."""
-
- def __init__(self):
- self._index = 0
-
- def request(self):
- symbol = SYMBOL_FORMAT % self._index
- self._index += 1
- return stock_pb2.StockRequest(
- symbol=symbol, num_trades_to_watch=STREAM_LENGTH)
-
- def verify(self, request, responses, test_case):
- test_case.assertEqual(STREAM_LENGTH, len(responses))
- base_price = _price(request.symbol)
- for index, response in enumerate(responses):
- test_case.assertEqual(base_price + index, response.price)
-
-
-class GetHighestTradePrice(service.StreamUnaryTestMethodImplementation):
- """GetHighestTradePrice for use in tests."""
-
- def name(self):
- return 'GetHighestTradePrice'
-
- def cardinality(self):
- return cardinality.Cardinality.STREAM_UNARY
-
- def request_class(self):
- return stock_pb2.StockRequest
-
- def response_class(self):
- return stock_pb2.StockReply
-
- def serialize_request(self, request):
- return request.SerializeToString()
-
- def deserialize_request(self, serialized_request):
- return stock_pb2.StockRequest.FromString(serialized_request)
-
- def serialize_response(self, response):
- return response.SerializeToString()
-
- def deserialize_response(self, serialized_response):
- return stock_pb2.StockReply.FromString(serialized_response)
-
- def service(self, response_callback, context, control):
- return _get_highest_trade_price(
- response_callback, control, context.is_active)
-
-
-class GetHighestTradePriceMessages(service.StreamUnaryTestMessages):
-
- def requests(self):
- return [
- stock_pb2.StockRequest(symbol=SYMBOL_FORMAT % index)
- for index in range(STREAM_LENGTH)]
-
- def verify(self, requests, response, test_case):
- price = None
- symbol = None
- for stock_request in requests:
- current_symbol = stock_request.symbol
- current_price = _price(current_symbol)
- if price is None or price < current_price:
- price = current_price
- symbol = current_symbol
- test_case.assertEqual(price, response.price)
- test_case.assertEqual(symbol, response.symbol)
-
-
-class StockTestService(service.TestService):
- """A corpus of test data with one method of each RPC cardinality."""
-
- def name(self):
- return 'Stock'
-
- def unary_unary_scenarios(self):
- return {
- 'GetLastTradePrice': (
- GetLastTradePrice(), [GetLastTradePriceMessages()]),
- }
-
- def unary_stream_scenarios(self):
- return {
- 'WatchFutureTrades': (
- WatchFutureTrades(), [WatchFutureTradesMessages()]),
- }
-
- def stream_unary_scenarios(self):
- return {
- 'GetHighestTradePrice': (
- GetHighestTradePrice(), [GetHighestTradePriceMessages()])
- }
-
- def stream_stream_scenarios(self):
- return {
- 'GetLastTradePriceMultiple': (
- GetLastTradePriceMultiple(), [GetLastTradePriceMultipleMessages()]),
- }
-
-
-STOCK_TEST_SERVICE = StockTestService()
diff --git a/src/python/grpcio/tests/unit/framework/face/testing/test_case.py b/src/python/grpcio/tests/unit/framework/face/testing/test_case.py
deleted file mode 100644
index f29d400844..0000000000
--- a/src/python/grpcio/tests/unit/framework/face/testing/test_case.py
+++ /dev/null
@@ -1,81 +0,0 @@
-# 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.
-
-"""Tools for creating tests of implementations of the Face layer."""
-
-import abc
-
-import six
-
-# face_interfaces and interfaces are referenced in specification in this module.
-from grpc.framework.face import interfaces as face_interfaces # pylint: disable=unused-import
-from tests.unit.framework.face.testing import interfaces # pylint: disable=unused-import
-
-
-class FaceTestCase(six.with_metaclass(abc.ABCMeta)):
- """Describes a test of the Face Layer of RPC Framework.
-
- Concrete subclasses must also inherit from unittest.TestCase and from at least
- one class that defines test methods.
- """
-
- @abc.abstractmethod
- def set_up_implementation(
- self, name, methods, method_implementations,
- multi_method_implementation):
- """Instantiates the Face Layer implementation under test.
-
- Args:
- name: The service name to be used in the test.
- methods: A sequence of interfaces.Method objects describing the RPC
- methods that will be called during the test.
- method_implementations: A dictionary from string RPC method name to
- face_interfaces.MethodImplementation object specifying
- implementation of an RPC method.
- multi_method_implementation: An face_interfaces.MultiMethodImplementation
- or None.
-
- Returns:
- A sequence of length two the first element of which is a
- face_interfaces.GenericStub (backed by the given method
- implementations), and the second element of which is an arbitrary memo
- object to be kept and passed to tearDownImplementation at the conclusion
- of the test.
- """
- raise NotImplementedError()
-
- @abc.abstractmethod
- def tear_down_implementation(self, memo):
- """Destroys the Face layer implementation under test.
-
- Args:
- memo: The object from the second position of the return value of
- set_up_implementation.
- """
- raise NotImplementedError()