Home | History | Annotate | Download | only in _cygrpc
      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 cimport cpython
     16 
     17 
     18 cdef 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