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