1# Copyright 2015 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 15cimport cpython 16 17 18cdef class Call: 19 20 def __cinit__(self): 21 # Create an *empty* call 22 fork_handlers_and_grpc_init() 23 self.c_call = NULL 24 self.references = [] 25 26 def _start_batch(self, operations, tag, retain_self): 27 if not self.is_valid: 28 raise ValueError("invalid call object cannot be used from Python") 29 cdef _BatchOperationTag batch_operation_tag = _BatchOperationTag( 30 tag, operations, self if retain_self else None) 31 batch_operation_tag.prepare() 32 cpython.Py_INCREF(batch_operation_tag) 33 cdef grpc_call_error error 34 with nogil: 35 error = grpc_call_start_batch( 36 self.c_call, batch_operation_tag.c_ops, batch_operation_tag.c_nops, 37 <cpython.PyObject *>batch_operation_tag, NULL) 38 return error 39 40 def start_client_batch(self, operations, tag): 41 # We don't reference this call in the operations tag because 42 # it should be cancelled when it goes out of scope 43 return self._start_batch(operations, tag, False) 44 45 def start_server_batch(self, operations, tag): 46 return self._start_batch(operations, tag, True) 47 48 def cancel( 49 self, grpc_status_code error_code=GRPC_STATUS__DO_NOT_USE, 50 details=None): 51 details = str_to_bytes(details) 52 if not self.is_valid: 53 raise ValueError("invalid call object cannot be used from Python") 54 if (details is None) != (error_code == GRPC_STATUS__DO_NOT_USE): 55 raise ValueError("if error_code is specified, so must details " 56 "(and vice-versa)") 57 cdef grpc_call_error result 58 cdef char *c_details = NULL 59 if error_code != GRPC_STATUS__DO_NOT_USE: 60 self.references.append(details) 61 c_details = details 62 with nogil: 63 result = grpc_call_cancel_with_status( 64 self.c_call, error_code, c_details, NULL) 65 return result 66 else: 67 with nogil: 68 result = grpc_call_cancel(self.c_call, NULL) 69 return result 70 71 def set_credentials(self, CallCredentials call_credentials not None): 72 cdef grpc_call_credentials *c_call_credentials = call_credentials.c() 73 cdef grpc_call_error call_error = grpc_call_set_credentials( 74 self.c_call, c_call_credentials) 75 grpc_call_credentials_release(c_call_credentials) 76 return call_error 77 78 def peer(self): 79 cdef char *peer = NULL 80 with nogil: 81 peer = grpc_call_get_peer(self.c_call) 82 result = <bytes>peer 83 with nogil: 84 gpr_free(peer) 85 return result 86 87 def __dealloc__(self): 88 if self.c_call != NULL: 89 grpc_call_unref(self.c_call) 90 grpc_shutdown() 91 92 # The object *should* always be valid from Python. Used for debugging. 93 @property 94 def is_valid(self): 95 return self.c_call != NULL 96 97 def _custom_op_on_c_call(self, int op): 98 return _custom_op_on_c_call(op, self.c_call) 99