def _options(options): if options is None: pairs = ((cygrpc.ChannelArgKey.primary_user_agent_string, _USER_AGENT),) else: pairs = list(options) + [(cygrpc.ChannelArgKey.primary_user_agent_string, _USER_AGENT)] encoded_pairs = [ (_common.encode(arg_name), arg_value) if isinstance(arg_value, int) else (_common.encode(arg_name), _common.encode(arg_value)) for arg_name, arg_value in pairs ] return cygrpc.ChannelArgs([cygrpc.ChannelArg(arg_name, arg_value) for arg_name, arg_value in encoded_pairs])
def _call_behavior(rpc_event, state, behavior, argument, request_deserializer, send_response_callback=None): from grpc import _create_servicer_context with _create_servicer_context(rpc_event, state, request_deserializer) as context: try: if send_response_callback is not None: return behavior(argument, context, send_response_callback), True else: return behavior(argument, context), True except Exception as exception: # pylint: disable=broad-except with state.condition: if state.aborted: _abort(state, rpc_event.call, cygrpc.StatusCode.unknown, b'RPC Aborted') elif exception not in state.rpc_errors: details = 'Exception calling application: {}'.format( exception) _LOGGER.exception(details) _abort(state, rpc_event.call, cygrpc.StatusCode.unknown, _common.encode(details)) return None, False
def unary_unary(self, method, request_serializer=None, response_deserializer=None): return _UnaryUnaryMultiCallable( self._channel, _channel_managed_call_management(self._call_state), _common.encode(method), request_serializer, response_deserializer)
def stream_stream(self, method, request_serializer=None, response_deserializer=None): return _StreamStreamMultiCallable( self._channel, _channel_managed_call_management(self._call_state), _common.encode(method), request_serializer, response_deserializer)
def unary_request(): with state.condition: if state.client is _CANCELLED or state.statused: return None else: start_server_batch_result = rpc_event.operation_call.start_server_batch( cygrpc.Operations( (cygrpc.operation_receive_message(_EMPTY_FLAGS),)), _receive_message( state, rpc_event.operation_call, request_deserializer)) state.due.add(_RECEIVE_MESSAGE_TOKEN) while True: state.condition.wait() if state.request is None: if state.client is _CLOSED: details = '"{}" requires exactly one request message.'.format( rpc_event.request_call_details.method) _abort( state, rpc_event.operation_call, cygrpc.StatusCode.unimplemented, _common.encode(details)) return None elif state.client is _CANCELLED: return None else: request = state.request state.request = None return request
def stream_stream(self, method, request_serializer=None, response_deserializer=None): return _StreamStreamMultiCallable(self.get_channel().channel, _common.encode(method), request_serializer, response_deserializer)
def unary_unary(self, method, request_serializer=None, response_deserializer=None): return UnaryUnaryMultiCallable(self._channel, _common.encode(method), request_serializer, response_deserializer)
def stream_unary(self, method, request_serializer=None, response_deserializer=None): return _StreamUnaryMultiCallable( self._channel, _create_channel_managed_call(self._call_state), _common.encode(method), request_serializer, response_deserializer, )
def __init__(self, target, options=None, credentials=None): options = options if options is not None else () self.target = target self.channel = channel = cygrpc.Channel(_common.encode(target), options, credentials) self.managed_call = _channel_managed_call_management( _ChannelCallState(channel)) self.connectivity_state = _ChannelConnectivityState(channel)
def stream_stream( self, method: Text, request_serializer: Optional[SerializingFunction] = None, response_deserializer: Optional[DeserializingFunction] = None ) -> StreamStreamMultiCallable: return StreamStreamMultiCallable(self._channel, _common.encode(method), request_serializer, response_deserializer, None)
def stream_unary( self, method: str, request_serializer: Optional[SerializingFunction] = None, response_deserializer: Optional[DeserializingFunction] = None ) -> StreamUnaryMultiCallable: return StreamUnaryMultiCallable(self._channel, _common.encode(method), request_serializer, response_deserializer, None, self._loop)
def unary_stream( self, method: Text, request_serializer: Optional[SerializingFunction] = None, response_deserializer: Optional[DeserializingFunction] = None ) -> UnaryStreamMultiCallable: return UnaryStreamMultiCallable(self._channel, self._ongoing_calls, _common.encode(method), request_serializer, response_deserializer, None, self._loop)
def _call_behavior(rpc_event, state, context, behavior, argument): try: return behavior(argument, context), True except Exception as e: # pylint: disable=broad-except with state.condition: if e not in state.rpc_errors: details = 'Exception calling application: {}'.format(e) logging.exception(details) _abort(state, rpc_event.operation_call, cygrpc.StatusCode.unknown, _common.encode(details)) return None, False
def __init__(self, target, options, credentials): """Constructor. Args: target: The target to which to connect. options: Configuration options for the channel. credentials: A cygrpc.ChannelCredentials or None. """ self._channel = cygrpc.Channel(_common.encode(target), _options(options), credentials) self._call_state = _ChannelCallState(self._channel) self._connectivity_state = _ChannelConnectivityState(self._channel)
def metadata_plugin_call_credentials(metadata_plugin, name): if name is None: try: effective_name = metadata_plugin.__name__ except AttributeError: effective_name = metadata_plugin.__class__.__name__ else: effective_name = name return grpc.CallCredentials( cygrpc.MetadataPluginCallCredentials( _Plugin(metadata_plugin), _common.encode(effective_name)))
def call_credentials_metadata_plugin(plugin, name): """ Args: plugin: A callable accepting a grpc.AuthMetadataContext object and a callback (itself accepting a list of metadata key/value 2-tuples and a None-able exception value). The callback must be eventually called, but need not be called in plugin's invocation. plugin's invocation must be non-blocking. """ return cygrpc.call_credentials_metadata_plugin( cygrpc.CredentialsMetadataPlugin(_WrappedPlugin(plugin), _common.encode(name)))
def unary_stream( self, method: str, request_serializer: Optional[SerializingFunction] = None, response_deserializer: Optional[DeserializingFunction] = None ) -> UnaryStreamMultiCallable: return UnaryStreamMultiCallable(self._channel, _common.encode(method), request_serializer, response_deserializer, self._unary_stream_interceptors, self._loop)
def metadata_plugin_call_credentials(metadata_plugin, name): if name is None: try: effective_name = metadata_plugin.__name__ except AttributeError: effective_name = metadata_plugin.__class__.__name__ else: effective_name = name return grpc.CallCredentials( cygrpc.MetadataPluginCallCredentials(_Plugin(metadata_plugin), _common.encode(effective_name)))
def abort(self, code, details): # treat OK like other invalid arguments: fail the RPC if code == grpc.StatusCode.OK: _LOGGER.error( 'abort() called with StatusCode.OK; returning UNKNOWN') code = grpc.StatusCode.UNKNOWN details = '' with self._state.condition: self._state.code = code self._state.details = _common.encode(details) self._state.aborted = True raise Exception()
def _call_behavior(rpc_event, state, behavior, argument, request_deserializer): context = _Context(rpc_event, state, request_deserializer) try: return behavior(argument, context), True except Exception as e: # pylint: disable=broad-except with state.condition: if e not in state.rpc_errors: details = 'Exception calling application: {}'.format(e) logging.exception(details) _abort(state, rpc_event.operation_call, cygrpc.StatusCode.unknown, _common.encode(details)) return None, False
async def _call_behavior_async(rpc_event, state, behavior, argument, request_deserializer): context = _Context(rpc_event, state, request_deserializer) try: return await behavior(argument, context), True except Exception as e: with state.condition: if e not in state.rpc_errors: logging.exception(e) _abort(state, rpc_event.operation_call, StatusCode.unknown, _common.encode(e)) return None, False
def abort(self, code, details): # treat OK like other invalid arguments: fail the RPC if code == grpc.StatusCode.OK: _LOGGER.error( 'abort() called with StatusCode.OK; returning UNKNOWN') code = grpc.StatusCode.UNKNOWN details = '' with self._state.condition: self._state.code = code self._state.details = _common.encode(details) self._state.abortion = Exception() raise self._state.abortion
def __init__(self, target: str, options: ChannelArgumentType, credentials: Optional[grpc.ChannelCredentials], compression: Optional[grpc.Compression], interceptors: Optional[Sequence[ClientInterceptor]]): """Constructor. Args: target: The target to which to connect. options: Configuration options for the channel. credentials: A cygrpc.ChannelCredentials or None. compression: An optional value indicating the compression method to be used over the lifetime of the channel. interceptors: An optional list of interceptors that would be used for intercepting any RPC executed with that channel. """ self._unary_unary_interceptors = [] self._unary_stream_interceptors = [] self._stream_unary_interceptors = [] if interceptors: attrs_and_interceptor_classes = ((self._unary_unary_interceptors, UnaryUnaryClientInterceptor), (self._unary_stream_interceptors, UnaryStreamClientInterceptor), (self._stream_unary_interceptors, StreamUnaryClientInterceptor)) # pylint: disable=cell-var-from-loop for attr, interceptor_class in attrs_and_interceptor_classes: attr.extend([ interceptor for interceptor in interceptors if isinstance(interceptor, interceptor_class) ]) invalid_interceptors = set(interceptors) - set( self._unary_unary_interceptors) - set( self._unary_stream_interceptors) - set( self._stream_unary_interceptors) if invalid_interceptors: raise ValueError( "Interceptor must be " + "{} or ".format(UnaryUnaryClientInterceptor.__name__) + "{} or ".format(UnaryStreamClientInterceptor.__name__) + "{}. ".format(StreamUnaryClientInterceptor.__name__) + "The following are invalid: {}".format(invalid_interceptors) ) self._loop = asyncio.get_event_loop() self._channel = cygrpc.AioChannel( _common.encode(target), _augment_channel_arguments(options, compression), credentials, self._loop)
def add_insecure_port(self, address: str) -> int: """Opens an insecure port for accepting RPCs. This method may only be called before starting the server. Args: address: The address for which to open a port. If the port is 0, or not specified in the address, then the gRPC runtime will choose a port. Returns: An integer port on which the server will accept RPC requests. """ return self._server.add_insecure_port(_common.encode(address))
def _take_response_from_response_iterator(rpc_event, state, response_iterator): try: return next(response_iterator), True except StopIteration: return None, True except Exception as e: # pylint: disable=broad-except with state.condition: if e not in state.rpc_errors: details = 'Exception iterating responses: {}'.format(e) logging.exception(details) _abort(state, rpc_event.operation_call, cygrpc.StatusCode.unknown, _common.encode(details)) return None, False
def _call_behavior(rpc_event, state, behavior, argument, request_deserializer): context = _Context(rpc_event, state, request_deserializer) try: return behavior(argument, context), True except Exception as exception: # pylint: disable=broad-except with state.condition: if exception is state.abortion: _abort(state, rpc_event.call, cygrpc.StatusCode.unknown, b'RPC Aborted') elif exception not in state.rpc_errors: details = 'Exception calling application: {}'.format(exception) _LOGGER.exception(details) _abort(state, rpc_event.call, cygrpc.StatusCode.unknown, _common.encode(details)) return None, False
def __init__(self, target, options, credentials, compression): """Constructor. Args: target: The target to which to connect. options: Configuration options for the channel. credentials: A cygrpc.ChannelCredentials or None. compression: An optional value indicating the compression method to be used over the lifetime of the channel. """ self._channel = cygrpc.Channel( _common.encode(target), _augment_options(options, compression), credentials) self._call_state = _ChannelCallState(self._channel) self._connectivity_state = _ChannelConnectivityState(self._channel) cygrpc.fork_register_channel(self)
def __init__(self, target, options, credentials, compression): """Constructor. Args: target: The target to which to connect. options: Configuration options for the channel. credentials: A cygrpc.ChannelCredentials or None. compression: An optional value indicating the compression method to be used over the lifetime of the channel. """ self._channel = cygrpc.Channel(_common.encode(target), _augment_options(options, compression), credentials) self._call_state = _ChannelCallState(self._channel) self._connectivity_state = _ChannelConnectivityState(self._channel) cygrpc.fork_register_channel(self)
def __init__(self, target, options, credentials): """Constructor. Args: target: The target to which to connect. options: Configuration options for the channel. credentials: A cygrpc.ChannelCredentials or None. """ self._channel = cygrpc.Channel(_common.encode(target), _options(options), credentials) self._call_state = _ChannelCallState(self._channel) self._connectivity_state = _ChannelConnectivityState(self._channel) # TODO(https://github.com/grpc/grpc/issues/9884) # Temporary work around UNAVAILABLE issues # Remove this once c-core has retry support _subscribe(self._connectivity_state, lambda *args: None, None)
def __call__(self, service_url, method_name, callback): context = _AuthMetadataContext( _common.decode(service_url), _common.decode(method_name)) callback_state = _CallbackState() try: self._metadata_plugin( context, _AuthMetadataPluginCallback(callback_state, callback)) except Exception as exception: # pylint: disable=broad-except logging.exception( 'AuthMetadataPluginCallback "%s" raised exception!', self._metadata_plugin) with callback_state.lock: callback_state.exception = exception if callback_state.called: return callback(None, cygrpc.StatusCode.internal, _common.encode(str(exception)))
def add_secure_port(self, address: Text, server_credentials: grpc.ServerCredentials) -> int: """Opens a secure port for accepting RPCs. This method may only be called before starting the server. Args: address: The address for which to open a port. if the port is 0, or not specified in the address, then the gRPC runtime will choose a port. server_credentials: A ServerCredentials object. Returns: An integer port on which the server will accept RPC requests. """ return self._server.add_secure_port(_common.encode(address), server_credentials)
def __call__(self, metadata, error): with self._state.lock: if self._state.exception is None: if self._state.called: raise RuntimeError( 'AuthMetadataPluginCallback invoked more than once!') else: self._state.called = True else: raise RuntimeError( 'AuthMetadataPluginCallback raised exception "{}"!'.format( self._state.exception)) if error is None: self._callback(metadata, cygrpc.StatusCode.ok, None) else: self._callback(None, cygrpc.StatusCode.internal, _common.encode(str(error)))
def __call__(self, service_url, method_name, callback): context = _AuthMetadataContext(_common.decode(service_url), _common.decode(method_name)) callback_state = _CallbackState() try: self._metadata_plugin( context, _AuthMetadataPluginCallback(callback_state, callback)) except Exception as exception: # pylint: disable=broad-except _LOGGER.exception( 'AuthMetadataPluginCallback "%s" raised exception!', self._metadata_plugin) with callback_state.lock: callback_state.exception = exception if callback_state.called: return callback(None, cygrpc.StatusCode.internal, _common.encode(str(exception)))
def __init__(self, target, options, credentials): """Constructor. Args: target: The target to which to connect. options: Configuration options for the channel. credentials: A cygrpc.ChannelCredentials or None. """ self._channel = cygrpc.Channel( _common.encode(target), _common.channel_args(_options(options)), credentials) self._call_state = _ChannelCallState(self._channel) self._connectivity_state = _ChannelConnectivityState(self._channel) # TODO(https://github.com/grpc/grpc/issues/9884) # Temporary work around UNAVAILABLE issues # Remove this once c-core has retry support _subscribe(self._connectivity_state, lambda *args: None, None)
def __init__(self, target: str, options: ChannelArgumentType, credentials: Optional[grpc.ChannelCredentials], compression: Optional[grpc.Compression], interceptors: Optional[Sequence[ClientInterceptor]]): """Constructor. Args: target: The target to which to connect. options: Configuration options for the channel. credentials: A cygrpc.ChannelCredentials or None. compression: An optional value indicating the compression method to be used over the lifetime of the channel. interceptors: An optional list of interceptors that would be used for intercepting any RPC executed with that channel. """ self._unary_unary_interceptors = [] self._unary_stream_interceptors = [] self._stream_unary_interceptors = [] self._stream_stream_interceptors = [] if interceptors is not None: for interceptor in interceptors: if isinstance(interceptor, UnaryUnaryClientInterceptor): self._unary_unary_interceptors.append(interceptor) elif isinstance(interceptor, UnaryStreamClientInterceptor): self._unary_stream_interceptors.append(interceptor) elif isinstance(interceptor, StreamUnaryClientInterceptor): self._stream_unary_interceptors.append(interceptor) elif isinstance(interceptor, StreamStreamClientInterceptor): self._stream_stream_interceptors.append(interceptor) else: raise ValueError( "Interceptor {} must be ".format(interceptor) + "{} or ".format(UnaryUnaryClientInterceptor.__name__) + "{} or ".format(UnaryStreamClientInterceptor.__name__) + "{} or ".format( StreamUnaryClientInterceptor.__name__) + "{}. ".format(StreamStreamClientInterceptor.__name__)) self._loop = cygrpc.get_working_loop() self._channel = cygrpc.AioChannel( _common.encode(target), _augment_channel_arguments(options, compression), credentials, self._loop)
def __init__( self, target: Text, options: Optional[ChannelArgumentType], credentials: Optional[grpc.ChannelCredentials], compression: Optional[grpc.Compression], interceptors: Optional[Sequence[UnaryUnaryClientInterceptor]]): """Constructor. Args: target: The target to which to connect. options: Configuration options for the channel. credentials: A cygrpc.ChannelCredentials or None. compression: An optional value indicating the compression method to be used over the lifetime of the channel. interceptors: An optional list of interceptors that would be used for intercepting any RPC executed with that channel. """ if compression: raise NotImplementedError("TODO: compression not implemented yet") if interceptors is None: self._unary_unary_interceptors = None else: self._unary_unary_interceptors = list( filter( lambda interceptor: isinstance( interceptor, UnaryUnaryClientInterceptor), interceptors)) invalid_interceptors = set(interceptors) - set( self._unary_unary_interceptors) if invalid_interceptors: raise ValueError( "Interceptor must be "+\ "UnaryUnaryClientInterceptors, the following are invalid: {}"\ .format(invalid_interceptors)) self._loop = asyncio.get_event_loop() self._channel = cygrpc.AioChannel(_common.encode(target), options, credentials, self._loop) self._ongoing_calls = _OngoingCalls()
def unary_unary(self, method, request_serializer=None, response_deserializer=None): """Creates a UnaryUnaryMultiCallable for a unary-unary method. Args: method: The name of the RPC method. request_serializer: Optional behaviour for serializing the request message. Request goes unserialized in case None is passed. response_deserializer: Optional behaviour for deserializing the response message. Response goes undeserialized in case None is passed. Returns: A UnaryUnaryMultiCallable value for the named unary-unary method. """ return UnaryUnaryMultiCallable(self._channel, _common.encode(method), request_serializer, response_deserializer)
def __init__(self, target, options, credentials, compression): """Constructor. Args: target: The target to which to connect. options: Configuration options for the channel. credentials: A cygrpc.ChannelCredentials or None. compression: An optional value indicating the compression method to be used over the lifetime of the channel. """ if options: raise NotImplementedError("TODO: options not implemented yet") if credentials: raise NotImplementedError("TODO: credentials not implemented yet") if compression: raise NotImplementedError("TODO: compression not implemented yet") self._channel = cygrpc.AioChannel(_common.encode(target))
def _invoke_failure(self, error): # TODO(atash) translate different Exception superclasses into different # status codes. self.cygrpc_callback(_common.EMPTY_METADATA, cygrpc.StatusCode.internal, _common.encode(str(error)))
def add_secure_port(self, address, server_credentials): return _add_secure_port(self._state, _common.encode(address), server_credentials)
def add_insecure_port(self, address): return _add_insecure_port(self._state, _common.encode(address))
def abort(self, code, details): with self._state.condition: self._state.code = code self._state.details = _common.encode(details) self._state.abortion = Exception() raise self._state.abortion
def set_details(self, details): with self._state.condition: self._state.details = _common.encode(details)