aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--src/python/grpcio/grpc/_cython/_cygrpc/call.pyx8
-rw-r--r--src/python/grpcio/grpc/_cython/_cygrpc/channel.pyx16
-rw-r--r--src/python/grpcio/grpc/_cython/_cygrpc/completion_queue.pyx8
-rw-r--r--src/python/grpcio/grpc/_cython/_cygrpc/credentials.pyx40
-rw-r--r--src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxd73
-rw-r--r--src/python/grpcio/grpc/_cython/_cygrpc/records.pyx32
-rw-r--r--src/python/grpcio/grpc/_cython/_cygrpc/server.pyx7
-rw-r--r--src/python/grpcio/grpc/_cython/cygrpc.pyx12
-rw-r--r--src/python/grpcio/requirements.txt1
-rw-r--r--src/python/grpcio/setup.py42
-rw-r--r--src/python/grpcio_test/.gitignore2
-rw-r--r--src/python/grpcio_test/grpc_test/_cython/cygrpc_test.py22
-rw-r--r--src/python/grpcio_test/grpc_test/test_common.py12
-rw-r--r--src/python/grpcio_test/setup.cfg1
-rw-r--r--src/python/grpcio_test/setup.py2
-rw-r--r--tools/dockerfile/grpc_python_base/Dockerfile2
16 files changed, 188 insertions, 92 deletions
diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/call.pyx b/src/python/grpcio/grpc/_cython/_cygrpc/call.pyx
index 4349786b3a..ed037b660a 100644
--- a/src/python/grpcio/grpc/_cython/_cygrpc/call.pyx
+++ b/src/python/grpcio/grpc/_cython/_cygrpc/call.pyx
@@ -29,6 +29,7 @@
cimport cpython
+from grpc._cython._cygrpc cimport grpc
from grpc._cython._cygrpc cimport records
@@ -49,7 +50,7 @@ cdef class Call:
cpython.Py_INCREF(operation_tag)
return grpc.grpc_call_start_batch(
self.c_call, cy_operations.c_ops, cy_operations.c_nops,
- <cpython.PyObject *>operation_tag)
+ <cpython.PyObject *>operation_tag, NULL)
def cancel(self,
grpc.grpc_status_code error_code=grpc.GRPC_STATUS__DO_NOT_USE,
@@ -67,9 +68,10 @@ cdef class Call:
raise TypeError("expected details to be str or bytes")
if error_code != grpc.GRPC_STATUS__DO_NOT_USE:
self.references.append(details)
- return grpc.grpc_call_cancel_with_status(self.c_call, error_code, details)
+ return grpc.grpc_call_cancel_with_status(self.c_call, error_code, details,
+ NULL)
else:
- return grpc.grpc_call_cancel(self.c_call)
+ return grpc.grpc_call_cancel(self.c_call, NULL)
def __dealloc__(self):
if self.c_call != NULL:
diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/channel.pyx b/src/python/grpcio/grpc/_cython/_cygrpc/channel.pyx
index b20313818d..b52ddb6bcd 100644
--- a/src/python/grpcio/grpc/_cython/_cygrpc/channel.pyx
+++ b/src/python/grpcio/grpc/_cython/_cygrpc/channel.pyx
@@ -30,6 +30,7 @@
from grpc._cython._cygrpc cimport call
from grpc._cython._cygrpc cimport completion_queue
from grpc._cython._cygrpc cimport credentials
+from grpc._cython._cygrpc cimport grpc
from grpc._cython._cygrpc cimport records
@@ -49,15 +50,17 @@ cdef class Channel:
else:
raise TypeError("expected target to be str or bytes")
if client_credentials is None:
- self.c_channel = grpc.grpc_channel_create(target, c_arguments)
+ self.c_channel = grpc.grpc_insecure_channel_create(target, c_arguments,
+ NULL)
else:
self.c_channel = grpc.grpc_secure_channel_create(
- client_credentials.c_credentials, target, c_arguments)
+ client_credentials.c_credentials, target, c_arguments, NULL)
self.references.append(client_credentials)
self.references.append(target)
self.references.append(arguments)
- def create_call(self, completion_queue.CompletionQueue queue not None,
+ def create_call(self, call.Call parent, int flags,
+ completion_queue.CompletionQueue queue not None,
method, host, records.Timespec deadline not None):
if queue.is_shutting_down:
raise ValueError("queue must not be shutting down or shutdown")
@@ -75,8 +78,13 @@ cdef class Channel:
raise TypeError("expected host to be str or bytes")
cdef call.Call operation_call = call.Call()
operation_call.references = [self, method, host, queue]
+ cdef grpc.grpc_call *parent_call = NULL
+ if parent is not None:
+ parent_call = parent.c_call
operation_call.c_call = grpc.grpc_channel_create_call(
- self.c_channel, queue.c_completion_queue, method, host, deadline.c_time)
+ self.c_channel, parent_call, flags,
+ queue.c_completion_queue, method, host, deadline.c_time,
+ NULL)
return operation_call
def __dealloc__(self):
diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/completion_queue.pyx b/src/python/grpcio/grpc/_cython/_cygrpc/completion_queue.pyx
index 886d85360a..a7a265eab7 100644
--- a/src/python/grpcio/grpc/_cython/_cygrpc/completion_queue.pyx
+++ b/src/python/grpcio/grpc/_cython/_cygrpc/completion_queue.pyx
@@ -30,6 +30,7 @@
cimport cpython
from grpc._cython._cygrpc cimport call
+from grpc._cython._cygrpc cimport grpc
from grpc._cython._cygrpc cimport records
import threading
@@ -39,7 +40,7 @@ import time
cdef class CompletionQueue:
def __cinit__(self):
- self.c_completion_queue = grpc.grpc_completion_queue_create()
+ self.c_completion_queue = grpc.grpc_completion_queue_create(NULL)
self.is_shutting_down = False
self.is_shutdown = False
self.poll_condition = threading.Condition()
@@ -48,7 +49,8 @@ cdef class CompletionQueue:
def poll(self, records.Timespec deadline=None):
# We name this 'poll' to avoid problems with CPython's expectations for
# 'special' methods (like next and __next__).
- cdef grpc.gpr_timespec c_deadline = grpc.gpr_inf_future
+ cdef grpc.gpr_timespec c_deadline = grpc.gpr_inf_future(
+ grpc.GPR_CLOCK_REALTIME)
cdef records.OperationTag tag = None
cdef object user_tag = None
cdef call.Call operation_call = None
@@ -66,7 +68,7 @@ cdef class CompletionQueue:
self.is_polling = True
with nogil:
event = grpc.grpc_completion_queue_next(
- self.c_completion_queue, c_deadline)
+ self.c_completion_queue, c_deadline, NULL)
with self.poll_condition:
self.is_polling = False
self.poll_condition.notify()
diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/credentials.pyx b/src/python/grpcio/grpc/_cython/_cygrpc/credentials.pyx
index dc40a7a611..608207f0a2 100644
--- a/src/python/grpcio/grpc/_cython/_cygrpc/credentials.pyx
+++ b/src/python/grpcio/grpc/_cython/_cygrpc/credentials.pyx
@@ -27,6 +27,7 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+from grpc._cython._cygrpc cimport grpc
from grpc._cython._cygrpc cimport records
@@ -81,13 +82,11 @@ def client_credentials_ssl(pem_root_certificates,
credentials.references.append(pem_root_certificates)
if ssl_pem_key_cert_pair is not None:
credentials.c_credentials = grpc.grpc_ssl_credentials_create(
- c_pem_root_certificates, &ssl_pem_key_cert_pair.c_pair
- )
+ c_pem_root_certificates, &ssl_pem_key_cert_pair.c_pair, NULL)
credentials.references.append(ssl_pem_key_cert_pair)
else:
credentials.c_credentials = grpc.grpc_ssl_credentials_create(
- c_pem_root_certificates, NULL
- )
+ c_pem_root_certificates, NULL, NULL)
def client_credentials_composite_credentials(
ClientCredentials credentials_1 not None,
@@ -96,18 +95,20 @@ def client_credentials_composite_credentials(
raise ValueError("passed credentials must both be valid")
cdef ClientCredentials credentials = ClientCredentials()
credentials.c_credentials = grpc.grpc_composite_credentials_create(
- credentials_1.c_credentials, credentials_2.c_credentials)
+ credentials_1.c_credentials, credentials_2.c_credentials, NULL)
credentials.references.append(credentials_1)
credentials.references.append(credentials_2)
return credentials
-def client_credentials_compute_engine():
+def client_credentials_google_compute_engine():
cdef ClientCredentials credentials = ClientCredentials()
- credentials.c_credentials = grpc.grpc_compute_engine_credentials_create()
+ credentials.c_credentials = (
+ grpc.grpc_google_compute_engine_credentials_create(NULL))
return credentials
#TODO rename to something like client_credentials_service_account_jwt_access.
-def client_credentials_jwt(json_key, records.Timespec token_lifetime not None):
+def client_credentials_service_account_jwt_access(
+ json_key, records.Timespec token_lifetime not None):
if isinstance(json_key, bytes):
pass
elif isinstance(json_key, basestring):
@@ -115,12 +116,13 @@ def client_credentials_jwt(json_key, records.Timespec token_lifetime not None):
else:
raise TypeError("expected json_key to be str or bytes")
cdef ClientCredentials credentials = ClientCredentials()
- credentials.c_credentials = grpc.grpc_service_account_jwt_access_credentials_create(
- json_key, token_lifetime.c_time)
+ credentials.c_credentials = (
+ grpc.grpc_service_account_jwt_access_credentials_create(
+ json_key, token_lifetime.c_time, NULL))
credentials.references.append(json_key)
return credentials
-def client_credentials_refresh_token(json_refresh_token):
+def client_credentials_google_refresh_token(json_refresh_token):
if isinstance(json_refresh_token, bytes):
pass
elif isinstance(json_refresh_token, basestring):
@@ -128,12 +130,12 @@ def client_credentials_refresh_token(json_refresh_token):
else:
raise TypeError("expected json_refresh_token to be str or bytes")
cdef ClientCredentials credentials = ClientCredentials()
- credentials.c_credentials = grpc.grpc_refresh_token_credentials_create(
- json_refresh_token)
+ credentials.c_credentials = grpc.grpc_google_refresh_token_credentials_create(
+ json_refresh_token, NULL)
credentials.references.append(json_refresh_token)
return credentials
-def client_credentials_iam(authorization_token, authority_selector):
+def client_credentials_google_iam(authorization_token, authority_selector):
if isinstance(authorization_token, bytes):
pass
elif isinstance(authorization_token, basestring):
@@ -147,13 +149,14 @@ def client_credentials_iam(authorization_token, authority_selector):
else:
raise TypeError("expected authority_selector to be str or bytes")
cdef ClientCredentials credentials = ClientCredentials()
- credentials.c_credentials = grpc.grpc_iam_credentials_create(
- authorization_token, authority_selector)
+ credentials.c_credentials = grpc.grpc_google_iam_credentials_create(
+ authorization_token, authority_selector, NULL)
credentials.references.append(authorization_token)
credentials.references.append(authority_selector)
return credentials
-def server_credentials_ssl(pem_root_certs, pem_key_cert_pairs):
+def server_credentials_ssl(pem_root_certs, pem_key_cert_pairs,
+ bint force_client_auth):
if pem_root_certs is None:
pass
elif isinstance(pem_root_certs, bytes):
@@ -181,7 +184,6 @@ def server_credentials_ssl(pem_root_certs, pem_key_cert_pairs):
(<records.SslPemKeyCertPair>pem_key_cert_pairs[i]).c_pair)
credentials.c_credentials = grpc.grpc_ssl_server_credentials_create(
pem_root_certs, credentials.c_ssl_pem_key_cert_pairs,
- credentials.c_ssl_pem_key_cert_pairs_count
- )
+ credentials.c_ssl_pem_key_cert_pairs_count, force_client_auth, NULL)
return credentials
diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxd b/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxd
index 8b46972490..62d40e7a58 100644
--- a/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxd
+++ b/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxd
@@ -64,15 +64,25 @@ cdef extern from "grpc/support/port_platform.h":
cdef extern from "grpc/support/time.h":
+ ctypedef enum gpr_clock_type:
+ GPR_CLOCK_MONOTONIC
+ GPR_CLOCK_REALTIME
+ GPR_CLOCK_PRECISE
+ GPR_TIMESPAN
+
ctypedef struct gpr_timespec:
libc.time.time_t seconds "tv_sec"
int nanoseconds "tv_nsec"
+ gpr_clock_type clock_type
+
+ gpr_timespec gpr_time_0(gpr_clock_type type)
+ gpr_timespec gpr_inf_future(gpr_clock_type type)
+ gpr_timespec gpr_inf_past(gpr_clock_type type)
- cdef gpr_timespec gpr_time_0
- cdef gpr_timespec gpr_inf_future
- cdef gpr_timespec gpr_inf_past
+ gpr_timespec gpr_now(gpr_clock_type clock)
- gpr_timespec gpr_now()
+ gpr_timespec gpr_convert_clock_type(gpr_timespec t,
+ gpr_clock_type target_clock)
cdef extern from "grpc/status.h":
@@ -255,38 +265,44 @@ cdef extern from "grpc/grpc.h":
void grpc_init()
void grpc_shutdown()
- grpc_completion_queue *grpc_completion_queue_create()
+ grpc_completion_queue *grpc_completion_queue_create(void *reserved)
grpc_event grpc_completion_queue_next(grpc_completion_queue *cq,
- gpr_timespec deadline) nogil
+ gpr_timespec deadline,
+ void *reserved) nogil
void grpc_completion_queue_shutdown(grpc_completion_queue *cq)
void grpc_completion_queue_destroy(grpc_completion_queue *cq)
grpc_call_error grpc_call_start_batch(grpc_call *call, const grpc_op *ops,
- size_t nops, void *tag)
- grpc_call_error grpc_call_cancel(grpc_call *call)
+ size_t nops, void *tag, void *reserved)
+ grpc_call_error grpc_call_cancel(grpc_call *call, void *reserved)
grpc_call_error grpc_call_cancel_with_status(grpc_call *call,
grpc_status_code status,
- const char *description)
+ const char *description,
+ void *reserved)
void grpc_call_destroy(grpc_call *call)
- grpc_channel *grpc_channel_create(const char *target,
- const grpc_channel_args *args)
+ grpc_channel *grpc_insecure_channel_create(const char *target,
+ const grpc_channel_args *args,
+ void *reserved)
grpc_call *grpc_channel_create_call(grpc_channel *channel,
+ grpc_call *parent_call,
+ gpr_uint32 propagation_mask,
grpc_completion_queue *completion_queue,
const char *method, const char *host,
- gpr_timespec deadline)
+ gpr_timespec deadline, void *reserved)
void grpc_channel_destroy(grpc_channel *channel)
- grpc_server *grpc_server_create(const grpc_channel_args *args)
+ grpc_server *grpc_server_create(const grpc_channel_args *args, void *reserved)
grpc_call_error grpc_server_request_call(
grpc_server *server, grpc_call **call, grpc_call_details *details,
grpc_metadata_array *request_metadata, grpc_completion_queue
*cq_bound_to_call, grpc_completion_queue *cq_for_notification, void
*tag_new)
void grpc_server_register_completion_queue(grpc_server *server,
- grpc_completion_queue *cq)
- int grpc_server_add_http2_port(grpc_server *server, const char *addr)
+ grpc_completion_queue *cq,
+ void *reserved)
+ int grpc_server_add_insecure_http2_port(grpc_server *server, const char *addr)
void grpc_server_start(grpc_server *server)
void grpc_server_shutdown_and_notify(
grpc_server *server, grpc_completion_queue *cq, void *tag)
@@ -306,22 +322,27 @@ cdef extern from "grpc/grpc_security.h":
grpc_credentials *grpc_google_default_credentials_create()
grpc_credentials *grpc_ssl_credentials_create(
- const char *pem_root_certs, grpc_ssl_pem_key_cert_pair *pem_key_cert_pair)
+ const char *pem_root_certs, grpc_ssl_pem_key_cert_pair *pem_key_cert_pair,
+ void *reserved)
grpc_credentials *grpc_composite_credentials_create(grpc_credentials *creds1,
- grpc_credentials *creds2)
- grpc_credentials *grpc_compute_engine_credentials_create()
- grpc_credentials *grpc_service_account_jwt_access_credentials_create(const char *json_key,
- gpr_timespec token_lifetime)
- grpc_credentials *grpc_refresh_token_credentials_create(
- const char *json_refresh_token)
- grpc_credentials *grpc_iam_credentials_create(const char *authorization_token,
- const char *authority_selector)
+ grpc_credentials *creds2,
+ void *reserved)
+ grpc_credentials *grpc_google_compute_engine_credentials_create(
+ void *reserved)
+ grpc_credentials *grpc_service_account_jwt_access_credentials_create(
+ const char *json_key,
+ gpr_timespec token_lifetime, void *reserved)
+ grpc_credentials *grpc_google_refresh_token_credentials_create(
+ const char *json_refresh_token, void *reserved)
+ grpc_credentials *grpc_google_iam_credentials_create(
+ const char *authorization_token, const char *authority_selector,
+ void *reserved)
void grpc_credentials_release(grpc_credentials *creds)
grpc_channel *grpc_secure_channel_create(
grpc_credentials *creds, const char *target,
- const grpc_channel_args *args)
+ const grpc_channel_args *args, void *reserved)
ctypedef struct grpc_server_credentials:
# We don't care about the internals (and in fact don't know them)
@@ -330,7 +351,7 @@ cdef extern from "grpc/grpc_security.h":
grpc_server_credentials *grpc_ssl_server_credentials_create(
const char *pem_root_certs,
grpc_ssl_pem_key_cert_pair *pem_key_cert_pairs,
- size_t num_key_cert_pairs)
+ size_t num_key_cert_pairs, int force_client_auth, void *reserved)
void grpc_server_credentials_release(grpc_server_credentials *creds)
int grpc_server_add_secure_http2_port(grpc_server *server, const char *addr,
diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/records.pyx b/src/python/grpcio/grpc/_cython/_cygrpc/records.pyx
index 4814769fd2..8edee09c2d 100644
--- a/src/python/grpcio/grpc/_cython/_cygrpc/records.pyx
+++ b/src/python/grpcio/grpc/_cython/_cygrpc/records.pyx
@@ -87,28 +87,38 @@ cdef class Timespec:
def __cinit__(self, time):
if time is None:
- self.c_time = grpc.gpr_now()
+ self.c_time = grpc.gpr_now(grpc.GPR_CLOCK_REALTIME)
elif isinstance(time, float):
if time == float("+inf"):
- self.c_time = grpc.gpr_inf_future
+ self.c_time = grpc.gpr_inf_future(grpc.GPR_CLOCK_REALTIME)
elif time == float("-inf"):
- self.c_time = grpc.gpr_inf_past
+ self.c_time = grpc.gpr_inf_past(grpc.GPR_CLOCK_REALTIME)
else:
self.c_time.seconds = time
self.c_time.nanoseconds = (time - float(self.c_time.seconds)) * 1e9
+ self.c_time.clock_type = grpc.GPR_CLOCK_REALTIME
else:
raise TypeError("expected time to be float")
@property
def seconds(self):
- return self.c_time.seconds
+ # TODO(atash) ensure that everywhere a Timespec is created that it's
+ # converted to GPR_CLOCK_REALTIME then and not every time someone wants to
+ # read values off in Python.
+ cdef grpc.gpr_timespec real_time = (
+ grpc.gpr_convert_clock_type(self.c_time, grpc.GPR_CLOCK_REALTIME))
+ return real_time.seconds
@property
def nanoseconds(self):
- return self.c_time.nanoseconds
+ cdef grpc.gpr_timespec real_time = (
+ grpc.gpr_convert_clock_type(self.c_time, grpc.GPR_CLOCK_REALTIME))
+ return real_time.nanoseconds
def __float__(self):
- return <double>self.c_time.seconds + <double>self.c_time.nanoseconds / 1e9
+ cdef grpc.gpr_timespec real_time = (
+ grpc.gpr_convert_clock_type(self.c_time, grpc.GPR_CLOCK_REALTIME))
+ return <double>real_time.seconds + <double>real_time.nanoseconds / 1e9
infinite_future = Timespec(float("+inf"))
infinite_past = Timespec(float("-inf"))
@@ -339,13 +349,16 @@ cdef class _MetadataIterator:
self.i = 0
self.metadata = metadata
+ def __iter__(self):
+ return self
+
def __next__(self):
if self.i < len(self.metadata):
result = self.metadata[self.i]
self.i = self.i + 1
return result
else:
- raise StopIteration()
+ raise StopIteration
cdef class Metadata:
@@ -536,13 +549,16 @@ cdef class _OperationsIterator:
self.i = 0
self.operations = operations
+ def __iter__(self):
+ return self
+
def __next__(self):
if self.i < len(self.operations):
result = self.operations[self.i]
self.i = self.i + 1
return result
else:
- raise StopIteration()
+ raise StopIteration
cdef class Operations:
diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/server.pyx b/src/python/grpcio/grpc/_cython/_cygrpc/server.pyx
index dcf9d38337..6d20d2910c 100644
--- a/src/python/grpcio/grpc/_cython/_cygrpc/server.pyx
+++ b/src/python/grpcio/grpc/_cython/_cygrpc/server.pyx
@@ -32,6 +32,7 @@ cimport cpython
from grpc._cython._cygrpc cimport call
from grpc._cython._cygrpc cimport completion_queue
from grpc._cython._cygrpc cimport credentials
+from grpc._cython._cygrpc cimport grpc
from grpc._cython._cygrpc cimport records
import time
@@ -46,7 +47,7 @@ cdef class Server:
if arguments is not None:
c_arguments = &arguments.c_args
self.references.append(arguments)
- self.c_server = grpc.grpc_server_create(c_arguments)
+ self.c_server = grpc.grpc_server_create(c_arguments, NULL)
self.is_started = False
self.is_shutting_down = False
self.is_shutdown = False
@@ -78,7 +79,7 @@ cdef class Server:
if self.is_started:
raise ValueError("cannot register completion queues after start")
grpc.grpc_server_register_completion_queue(
- self.c_server, queue.c_completion_queue)
+ self.c_server, queue.c_completion_queue, NULL)
self.registered_completion_queues.append(queue)
def start(self):
@@ -103,7 +104,7 @@ cdef class Server:
return grpc.grpc_server_add_secure_http2_port(
self.c_server, address, server_credentials.c_credentials)
else:
- return grpc.grpc_server_add_http2_port(self.c_server, address)
+ return grpc.grpc_server_add_insecure_http2_port(self.c_server, address)
def shutdown(self, completion_queue.CompletionQueue queue not None, tag):
cdef records.OperationTag operation_tag
diff --git a/src/python/grpcio/grpc/_cython/cygrpc.pyx b/src/python/grpcio/grpc/_cython/cygrpc.pyx
index f4d9661580..1ef2997db5 100644
--- a/src/python/grpcio/grpc/_cython/cygrpc.pyx
+++ b/src/python/grpcio/grpc/_cython/cygrpc.pyx
@@ -78,11 +78,13 @@ client_credentials_google_default = (
client_credentials_ssl = credentials.client_credentials_ssl
client_credentials_composite_credentials = (
credentials.client_credentials_composite_credentials)
-client_credentials_compute_engine = (
- credentials.client_credentials_compute_engine)
-client_credentials_jwt = credentials.client_credentials_jwt
-client_credentials_refresh_token = credentials.client_credentials_refresh_token
-client_credentials_iam = credentials.client_credentials_iam
+client_credentials_google_compute_engine = (
+ credentials.client_credentials_google_compute_engine)
+client_credentials_jwt_access = (
+ credentials.client_credentials_service_account_jwt_access)
+client_credentials_refresh_token = (
+ credentials.client_credentials_google_refresh_token)
+client_credentials_google_iam = credentials.client_credentials_google_iam
server_credentials_ssl = credentials.server_credentials_ssl
CompletionQueue = completion_queue.CompletionQueue
diff --git a/src/python/grpcio/requirements.txt b/src/python/grpcio/requirements.txt
index 77356e0a74..ee8568120b 100644
--- a/src/python/grpcio/requirements.txt
+++ b/src/python/grpcio/requirements.txt
@@ -1,2 +1,3 @@
enum34>=1.0.4
futures>=2.2.0
+cython>=0.23
diff --git a/src/python/grpcio/setup.py b/src/python/grpcio/setup.py
index 8b87c09d5c..97fa4fe6b3 100644
--- a/src/python/grpcio/setup.py
+++ b/src/python/grpcio/setup.py
@@ -34,6 +34,7 @@ import os.path
import sys
from distutils import core as _core
+from distutils import extension as _extension
import setuptools
# Ensure we're in the proper directory whether or not we're being used by pip.
@@ -59,6 +60,18 @@ _C_EXTENSION_SOURCES = (
'grpc/_adapter/_c/types/server.c',
)
+_CYTHON_EXTENSION_PACKAGE_NAMES = ()
+
+_CYTHON_EXTENSION_MODULE_NAMES = (
+ 'grpc._cython.cygrpc',
+ 'grpc._cython._cygrpc.call',
+ 'grpc._cython._cygrpc.channel',
+ 'grpc._cython._cygrpc.completion_queue',
+ 'grpc._cython._cygrpc.credentials',
+ 'grpc._cython._cygrpc.records',
+ 'grpc._cython._cygrpc.server',
+)
+
_EXTENSION_INCLUDE_DIRECTORIES = (
'.',
)
@@ -78,9 +91,30 @@ _C_EXTENSION_MODULE = _core.Extension(
)
_EXTENSION_MODULES = [_C_EXTENSION_MODULE]
-_PACKAGES = (
- setuptools.find_packages('.', exclude=['*._cython', '*._cython.*'])
-)
+
+def cython_extensions(package_names, module_names, include_dirs, libraries,
+ build_with_cython=False):
+ file_extension = 'pyx' if build_with_cython else 'c'
+ module_files = [name.replace('.', '/') + '.' + file_extension
+ for name in module_names]
+ extensions = [
+ _extension.Extension(
+ name=module_name, sources=[module_file],
+ include_dirs=include_dirs, libraries=libraries
+ ) for (module_name, module_file) in zip(module_names, module_files)
+ ]
+ if build_with_cython:
+ import Cython.Build
+ return Cython.Build.cythonize(extensions)
+ else:
+ return extensions
+
+_CYTHON_EXTENSION_MODULES = cython_extensions(
+ list(_CYTHON_EXTENSION_PACKAGE_NAMES), list(_CYTHON_EXTENSION_MODULE_NAMES),
+ list(_EXTENSION_INCLUDE_DIRECTORIES), list(_EXTENSION_LIBRARIES),
+ bool(_BUILD_WITH_CYTHON))
+
+_PACKAGES = setuptools.find_packages('.')
_PACKAGE_DIRECTORIES = {
'': '.',
@@ -104,7 +138,7 @@ _COMMAND_CLASS = {
setuptools.setup(
name='grpcio',
version='0.11.0b1',
- ext_modules=_EXTENSION_MODULES,
+ ext_modules=_EXTENSION_MODULES + _CYTHON_EXTENSION_MODULES,
packages=list(_PACKAGES),
package_dir=_PACKAGE_DIRECTORIES,
install_requires=_INSTALL_REQUIRES,
diff --git a/src/python/grpcio_test/.gitignore b/src/python/grpcio_test/.gitignore
index e3540baa7c..4bb4d42dfe 100644
--- a/src/python/grpcio_test/.gitignore
+++ b/src/python/grpcio_test/.gitignore
@@ -7,5 +7,5 @@ dist/
*.eggs/
.coverage
.coverage.*
-.cache
+.cache/
nosetests.xml
diff --git a/src/python/grpcio_test/grpc_test/_cython/cygrpc_test.py b/src/python/grpcio_test/grpc_test/_cython/cygrpc_test.py
index 637506b42e..1307a30ca0 100644
--- a/src/python/grpcio_test/grpc_test/_cython/cygrpc_test.py
+++ b/src/python/grpcio_test/grpc_test/_cython/cygrpc_test.py
@@ -32,6 +32,7 @@ import unittest
from grpc._cython import cygrpc
from grpc_test._cython import test_utilities
+from grpc_test import test_common
class TypeSmokeTest(unittest.TestCase):
@@ -139,7 +140,7 @@ class InsecureServerInsecureClient(unittest.TestCase):
CLIENT_METADATA_BIN_VALUE = b'\0'*1000
SERVER_INITIAL_METADATA_KEY = b'init_me_me_me'
SERVER_INITIAL_METADATA_VALUE = b'whodawha?'
- SERVER_TRAILING_METADATA_KEY = b'California_is_in_a_drought'
+ SERVER_TRAILING_METADATA_KEY = b'california_is_in_a_drought'
SERVER_TRAILING_METADATA_VALUE = b'zomg it is'
SERVER_STATUS_CODE = cygrpc.StatusCode.ok
SERVER_STATUS_DETAILS = b'our work is never over'
@@ -158,8 +159,8 @@ class InsecureServerInsecureClient(unittest.TestCase):
self.assertEqual(cygrpc.CallError.ok, request_call_result)
client_call_tag = object()
- client_call = self.client_channel.create_call(self.client_completion_queue,
- METHOD, HOST, cygrpc_deadline)
+ client_call = self.client_channel.create_call(
+ None, 0, self.client_completion_queue, METHOD, HOST, cygrpc_deadline)
client_initial_metadata = cygrpc.Metadata([
cygrpc.Metadatum(CLIENT_METADATA_ASCII_KEY,
CLIENT_METADATA_ASCII_VALUE),
@@ -182,8 +183,9 @@ class InsecureServerInsecureClient(unittest.TestCase):
self.assertIsInstance(request_event.operation_call, cygrpc.Call)
self.assertIs(server_request_tag, request_event.tag)
self.assertEqual(0, len(request_event.batch_operations))
- self.assertEqual(dict(client_initial_metadata),
- dict(request_event.request_metadata))
+ self.assertTrue(
+ test_common.metadata_transmitted(client_initial_metadata,
+ request_event.request_metadata))
self.assertEqual(METHOD, request_event.request_call_details.method)
self.assertEqual(HOST, request_event.request_call_details.host)
self.assertLess(
@@ -218,13 +220,15 @@ class InsecureServerInsecureClient(unittest.TestCase):
self.assertNotIn(client_result.type, found_client_op_types)
found_client_op_types.add(client_result.type)
if client_result.type == cygrpc.OperationType.receive_initial_metadata:
- self.assertEqual(dict(server_initial_metadata),
- dict(client_result.received_metadata))
+ self.assertTrue(
+ test_common.metadata_transmitted(server_initial_metadata,
+ client_result.received_metadata))
elif client_result.type == cygrpc.OperationType.receive_message:
self.assertEqual(RESPONSE, client_result.received_message.bytes())
elif client_result.type == cygrpc.OperationType.receive_status_on_client:
- self.assertEqual(dict(server_trailing_metadata),
- dict(client_result.received_metadata))
+ self.assertTrue(
+ test_common.metadata_transmitted(server_trailing_metadata,
+ client_result.received_metadata))
self.assertEqual(SERVER_STATUS_DETAILS,
client_result.received_status_details)
self.assertEqual(SERVER_STATUS_CODE, client_result.received_status_code)
diff --git a/src/python/grpcio_test/grpc_test/test_common.py b/src/python/grpcio_test/grpc_test/test_common.py
index 44284be88b..29431bfb9d 100644
--- a/src/python/grpcio_test/grpc_test/test_common.py
+++ b/src/python/grpcio_test/grpc_test/test_common.py
@@ -46,19 +46,23 @@ def metadata_transmitted(original_metadata, transmitted_metadata):
the same key.
Args:
- original_metadata: A metadata value used in a test of gRPC.
+ original_metadata: A metadata value used in a test of gRPC. An iterable over
+ iterables of length 2.
transmitted_metadata: A metadata value corresponding to original_metadata
- after having been transmitted via gRPC.
+ after having been transmitted via gRPC. An iterable over iterables of
+ length 2.
Returns:
A boolean indicating whether transmitted_metadata accurately reflects
original_metadata after having been transmitted via gRPC.
"""
original = collections.defaultdict(list)
- for key, value in original_metadata:
+ for key_value_pair in original_metadata:
+ key, value = tuple(key_value_pair)
original[key].append(value)
transmitted = collections.defaultdict(list)
- for key, value in transmitted_metadata:
+ for key_value_pair in transmitted_metadata:
+ key, value = tuple(key_value_pair)
transmitted[key].append(value)
for key, values in original.iteritems():
diff --git a/src/python/grpcio_test/setup.cfg b/src/python/grpcio_test/setup.cfg
index b32d3f5972..3be93cb918 100644
--- a/src/python/grpcio_test/setup.cfg
+++ b/src/python/grpcio_test/setup.cfg
@@ -1,3 +1,2 @@
[pytest]
-norecursedirs = _cython
python_files = *_test.py
diff --git a/src/python/grpcio_test/setup.py b/src/python/grpcio_test/setup.py
index fe36bc9232..0f43b4a638 100644
--- a/src/python/grpcio_test/setup.py
+++ b/src/python/grpcio_test/setup.py
@@ -40,7 +40,7 @@ os.chdir(os.path.dirname(os.path.abspath(__file__)))
# Break import-style to ensure we can actually find our commands module.
import commands
-_PACKAGES = setuptools.find_packages('.', exclude=['*._cython', '*._cython.*'])
+_PACKAGES = setuptools.find_packages('.')
_PACKAGE_DIRECTORIES = {
'': '.',
diff --git a/tools/dockerfile/grpc_python_base/Dockerfile b/tools/dockerfile/grpc_python_base/Dockerfile
index 90a57bf341..6ef7a111df 100644
--- a/tools/dockerfile/grpc_python_base/Dockerfile
+++ b/tools/dockerfile/grpc_python_base/Dockerfile
@@ -43,7 +43,7 @@ RUN apt-get update && apt-get install -y \
python-virtualenv
# Install Python packages from PyPI
-RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.0.0a2
+RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.0.0a2 cython==0.23
# Get the GRPC source from GitHub
RUN git clone --recursive https://github.com/grpc/grpc.git /var/local/git/grpc