# Copyright 2015 gRPC authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Interfaces defining the Face layer of RPC Framework."""
import abc
import collections
import enum
import six
# cardinality, style, abandonment, future, and stream are
# referenced from specification in this module.
from grpc.framework.common import cardinality # pylint: disable=unused-import
from grpc.framework.common import style # pylint: disable=unused-import
from grpc.framework.foundation import abandonment # pylint: disable=unused-import
from grpc.framework.foundation import future # pylint: disable=unused-import
from grpc.framework.foundation import stream # pylint: disable=unused-import
# pylint: disable=too-many-arguments
class NoSuchMethodError(Exception):
"""Raised by customer code to indicate an unrecognized method.
Attributes:
group: The group of the unrecognized method.
name: The name of the unrecognized method.
"""
def __init__(self, group, method):
"""Constructor.
Args:
group: The group identifier of the unrecognized RPC name.
method: The method identifier of the unrecognized RPC name.
"""
super(NoSuchMethodError, self).__init__()
self.group = group
self.method = method
def __repr__(self):
return 'face.NoSuchMethodError(%s, %s)' % (
self.group,
self.method,
)
class Abortion(
collections.namedtuple('Abortion', (
'kind',
'initial_metadata',
'terminal_metadata',
'code',
'details',
))):
"""A value describing RPC abortion.
Attributes:
kind: A Kind value identifying how the RPC failed.
initial_metadata: The initial metadata from the other side of the RPC or
None if no initial metadata value was received.
terminal_metadata: The terminal metadata from the other side of the RPC or
None if no terminal metadata value was received.
code: The code value from the other side of the RPC or None if no code value
was received.
details: The details value from the other side of the RPC or None if no
details value was received.
"""
@enum.unique
class Kind(enum.Enum):
"""Types of RPC abortion."""
CANCELLED = 'cancelled'
EXPIRED = 'expired'
LOCAL_SHUTDOWN = 'local shutdown'
REMOTE_SHUTDOWN = 'remote shutdown'
NETWORK_FAILURE = 'network failure'
LOCAL_FAILURE = 'local failure'
REMOTE_FAILURE = 'remote failure'
class AbortionError(six.with_metaclass(abc.ABCMeta, Exception)):
"""Common super type for exceptions indicating RPC abortion.
initial_metadata: The initial metadata from the other side of the RPC or
None if no initial metadata value was received.
terminal_metadata: The terminal metadata from the other side of the RPC or
None if no terminal metadata value was received.
code: The code value from the other side of the RPC or None if no code value
was received.
details: The details value from the other side of the RPC or None if no
details value was received.
"""
def __init__(self, initial_metadata, terminal_metadata, code, details):
super(AbortionError, self).__init__()
self.initial_metadata = initial_metadata
self.terminal_metadata = terminal_metadata
self.code = code
self.details = details
def __str__(self):
return '%s(code=%s, details="%s")' % (self.__class__.__name__,
self.code, self.details)
class CancellationError(AbortionError):
"""Indicates that an RPC has been cancelled."""
class ExpirationError(AbortionError):
"""Indicates that an RPC has expired ("timed out")."""
class LocalShutdownError(AbortionError):
"""Indicates that an RPC has terminated due to local shutdown of RPCs."""
class RemoteShutdownError(AbortionError):
"""Indicates that an RPC has terminated due to remote shutdown of RPCs."""
class NetworkError(AbortionError):
"""Indicates that some error occurred on the network."""
class LocalError(AbortionError):
"""Indicates that an RPC has terminated due to a local defect."""
class RemoteError(AbortionError):
"""Indicates that an RPC has terminated due to a remote defect."""
class RpcContext(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()
@abc.abstractmethod
def cancel(self):
"""Cancels the RPC.
Idempotent and has no effect if the RPC has already terminated.
"""
raise NotImplementedError()
@abc.abstractmethod
def protocol_context(self):
"""Accesses a custom object specified by an implementation provider.
Returns:
A value specified by the provider of a Face interface implementation
affording custom state and behavior.
"""
raise NotImplementedError()
class Call(six.with_metaclass(abc.ABCMeta, RpcContext)):
"""Invocation-side utility object for an RPC."""
@abc.abstractmethod
def initial_metadata(self):
"""Accesses the initial metadata from the service-side of the RPC.
This method blocks until the value is available or is known not to have been
emitted from the service-side of the RPC.
Returns:
The initial metadata object emitted by the service-side of the RPC, or
None if there was no such value.
"""
raise NotImplementedError()
@abc.abstractmethod
def terminal_metadata(self):
"""Accesses the terminal metadata from the service-side of the RPC.
This method blocks until the value is available or is known not to have been
emitted from the service-side of the RPC.
Returns:
The terminal metadata object emitted by the service-side of the RPC, or
None if there was no such value.
"""
raise NotImplementedError()
@abc.abstractmethod
def code(self):
"""Accesses the code emitted by the service-side of the RPC.
This method blocks until the value is available or is known not to have been
emitted from the service-side of the RPC.
Returns:
The code object emitted by the service-side of the RPC, or None if there
was no such value.
"""
raise NotImplementedError()
@abc.abstractmethod
def details(self):
"""Accesses the details value emitted by the service-side of the RPC.
This method blocks until the value is available or is known not to have been
emitted from the service-side of the RPC.
Returns:
The details value emitted by the service-side of the RPC, or None if there
was no such value.
"""
raise NotImplementedError()
class ServicerContext(six.with_metaclass(abc.ABCMeta, RpcContext)):
"""A context object passed to method implementations."""
@abc.abstractmethod
def invocation_metadata(self):
"""Accesses the metadata from the invocation-side of the RPC.
This method blocks until the value is available or is known not to have been
emitted from the invocation-side of the RPC.
Returns:
The metadata object emitted by the invocation-side of the RPC, or None if
there was no such value.
"""
raise NotImplementedError()
@abc.abstractmethod
def initial_metadata(self, initial_metadata):
"""Accepts the service-side initial metadata value of the RPC.
This method need not be called by method implementations if they have no
service-side initial metadata to transmit.
Args:
initial_metadata: The service-side initial metadata value of the RPC to
be transmitted to the invocation side of the RPC.
"""
raise NotImplementedError()
@abc.abstractmethod
def terminal_metadata(self, terminal_metadata):
"""Accepts the service-side terminal metadata value of the RPC.
This method need not be called by method implementations if they have no
service-side terminal metadata to transmit.
Args:
terminal_metadata: The service-side terminal metadata value of the RPC to
be transmitted to the invocation side of the RPC.
"""
raise NotImplementedError()
@abc.abstractmethod
def code(self, code):
"""Accepts the service-side code of the RPC.
This method need not be called by method implementations if they have no
code to transmit.
Args:
code: The code of the RPC to be transmitted to the invocation side of the
RPC.
"""
raise NotImplementedError()
@abc.abstractmethod
def details(self, details):
"""Accepts the service-side details of the RPC.
This method need not be called by method implementations if they have no
service-side details to transmit.
Args:
details: The service-side details value of the RPC to be transmitted to
the invocation side of the RPC.
"""
raise NotImplementedError()
class ResponseReceiver(six.with_metaclass(abc.ABCMeta)):
"""Invocation-side object used to accept the output of an RPC."""
@abc.abstractmethod
def initial_metadata(self, initial_metadata):
"""Receives the initial metadata from the service-side of the RPC.
Args:
initial_metadata: The initial metadata object emitted from the
service-side of the RPC.
"""
raise NotImplementedError()
@abc.abstractmethod
def response(self, response):
"""Receives a response from the service-side of the RPC.
Args:
response: A response object emitted from the service-side of the RPC.
"""
raise NotImplementedError()
@abc.abstractmethod
def complete(self, terminal_metadata, code, details):
"""Receives the completion values emitted from the service-side of the RPC.
Loading ...