1# Copyright 2019 The gRPC Authors 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14"""Abstract base classes for client-side Call objects. 15 16Call objects represents the RPC itself, and offer methods to access / modify 17its information. They also offer methods to manipulate the life-cycle of the 18RPC, e.g. cancellation. 19""" 20 21from abc import ABCMeta 22from abc import abstractmethod 23from typing import Any, AsyncIterator, Generator, Generic, Optional, Union 24 25import grpc 26 27from ._metadata import Metadata 28from ._typing import DoneCallbackType 29from ._typing import EOFType 30from ._typing import RequestType 31from ._typing import ResponseType 32 33__all__ = "RpcContext", "Call", "UnaryUnaryCall", "UnaryStreamCall" 34 35 36class RpcContext(metaclass=ABCMeta): 37 """Provides RPC-related information and action.""" 38 39 @abstractmethod 40 def cancelled(self) -> bool: 41 """Return True if the RPC is cancelled. 42 43 The RPC is cancelled when the cancellation was requested with cancel(). 44 45 Returns: 46 A bool indicates whether the RPC is cancelled or not. 47 """ 48 49 @abstractmethod 50 def done(self) -> bool: 51 """Return True if the RPC is done. 52 53 An RPC is done if the RPC is completed, cancelled or aborted. 54 55 Returns: 56 A bool indicates if the RPC is done. 57 """ 58 59 @abstractmethod 60 def time_remaining(self) -> Optional[float]: 61 """Describes the length of allowed time remaining for the RPC. 62 63 Returns: 64 A nonnegative float indicating the length of allowed time in seconds 65 remaining for the RPC to complete before it is considered to have 66 timed out, or None if no deadline was specified for the RPC. 67 """ 68 69 @abstractmethod 70 def cancel(self) -> bool: 71 """Cancels the RPC. 72 73 Idempotent and has no effect if the RPC has already terminated. 74 75 Returns: 76 A bool indicates if the cancellation is performed or not. 77 """ 78 79 @abstractmethod 80 def add_done_callback(self, callback: DoneCallbackType) -> None: 81 """Registers a callback to be called on RPC termination. 82 83 Args: 84 callback: A callable object will be called with the call object as 85 its only argument. 86 """ 87 88 89class Call(RpcContext, metaclass=ABCMeta): 90 """The abstract base class of an RPC on the client-side.""" 91 92 @abstractmethod 93 async def initial_metadata(self) -> Metadata: 94 """Accesses the initial metadata sent by the server. 95 96 Returns: 97 The initial :term:`metadata`. 98 """ 99 100 @abstractmethod 101 async def trailing_metadata(self) -> Metadata: 102 """Accesses the trailing metadata sent by the server. 103 104 Returns: 105 The trailing :term:`metadata`. 106 """ 107 108 @abstractmethod 109 async def code(self) -> grpc.StatusCode: 110 """Accesses the status code sent by the server. 111 112 Returns: 113 The StatusCode value for the RPC. 114 """ 115 116 @abstractmethod 117 async def details(self) -> str: 118 """Accesses the details sent by the server. 119 120 Returns: 121 The details string of the RPC. 122 """ 123 124 @abstractmethod 125 async def wait_for_connection(self) -> None: 126 """Waits until connected to peer and raises aio.AioRpcError if failed. 127 128 This is an EXPERIMENTAL method. 129 130 This method ensures the RPC has been successfully connected. Otherwise, 131 an AioRpcError will be raised to explain the reason of the connection 132 failure. 133 134 This method is recommended for building retry mechanisms. 135 """ 136 137 138class UnaryUnaryCall( 139 Generic[RequestType, ResponseType], Call, metaclass=ABCMeta 140): 141 """The abstract base class of an unary-unary RPC on the client-side.""" 142 143 @abstractmethod 144 def __await__(self) -> Generator[Any, None, ResponseType]: 145 """Await the response message to be ready. 146 147 Returns: 148 The response message of the RPC. 149 """ 150 151 152class UnaryStreamCall( 153 Generic[RequestType, ResponseType], Call, metaclass=ABCMeta 154): 155 @abstractmethod 156 def __aiter__(self) -> AsyncIterator[ResponseType]: 157 """Returns the async iterator representation that yields messages. 158 159 Under the hood, it is calling the "read" method. 160 161 Returns: 162 An async iterator object that yields messages. 163 """ 164 165 @abstractmethod 166 async def read(self) -> Union[EOFType, ResponseType]: 167 """Reads one message from the stream. 168 169 Read operations must be serialized when called from multiple 170 coroutines. 171 172 Note that the iterator and read/write APIs may not be mixed on 173 a single RPC. 174 175 Returns: 176 A response message, or an `grpc.aio.EOF` to indicate the end of the 177 stream. 178 """ 179 180 181class StreamUnaryCall( 182 Generic[RequestType, ResponseType], Call, metaclass=ABCMeta 183): 184 @abstractmethod 185 async def write(self, request: RequestType) -> None: 186 """Writes one message to the stream. 187 188 Note that the iterator and read/write APIs may not be mixed on 189 a single RPC. 190 191 Raises: 192 An RpcError exception if the write failed. 193 """ 194 195 @abstractmethod 196 async def done_writing(self) -> None: 197 """Notifies server that the client is done sending messages. 198 199 After done_writing is called, any additional invocation to the write 200 function will fail. This function is idempotent. 201 """ 202 203 @abstractmethod 204 def __await__(self) -> Generator[Any, None, ResponseType]: 205 """Await the response message to be ready. 206 207 Returns: 208 The response message of the stream. 209 """ 210 211 212class StreamStreamCall( 213 Generic[RequestType, ResponseType], Call, metaclass=ABCMeta 214): 215 @abstractmethod 216 def __aiter__(self) -> AsyncIterator[ResponseType]: 217 """Returns the async iterator representation that yields messages. 218 219 Under the hood, it is calling the "read" method. 220 221 Returns: 222 An async iterator object that yields messages. 223 """ 224 225 @abstractmethod 226 async def read(self) -> Union[EOFType, ResponseType]: 227 """Reads one message from the stream. 228 229 Read operations must be serialized when called from multiple 230 coroutines. 231 232 Note that the iterator and read/write APIs may not be mixed on 233 a single RPC. 234 235 Returns: 236 A response message, or an `grpc.aio.EOF` to indicate the end of the 237 stream. 238 """ 239 240 @abstractmethod 241 async def write(self, request: RequestType) -> None: 242 """Writes one message to the stream. 243 244 Note that the iterator and read/write APIs may not be mixed on 245 a single RPC. 246 247 Raises: 248 An RpcError exception if the write failed. 249 """ 250 251 @abstractmethod 252 async def done_writing(self) -> None: 253 """Notifies server that the client is done sending messages. 254 255 After done_writing is called, any additional invocation to the write 256 function will fail. This function is idempotent. 257 """ 258