diff options
-rw-r--r-- | src/python/grpcio/grpc/_cython/_cygrpc/call.pyx | 8 | ||||
-rw-r--r-- | src/python/grpcio/grpc/_cython/_cygrpc/channel.pyx | 16 | ||||
-rw-r--r-- | src/python/grpcio/grpc/_cython/_cygrpc/completion_queue.pyx | 8 | ||||
-rw-r--r-- | src/python/grpcio/grpc/_cython/_cygrpc/credentials.pyx | 40 | ||||
-rw-r--r-- | src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxd | 73 | ||||
-rw-r--r-- | src/python/grpcio/grpc/_cython/_cygrpc/records.pyx | 32 | ||||
-rw-r--r-- | src/python/grpcio/grpc/_cython/_cygrpc/server.pyx | 7 | ||||
-rw-r--r-- | src/python/grpcio/grpc/_cython/cygrpc.pyx | 12 | ||||
-rw-r--r-- | src/python/grpcio/requirements.txt | 1 | ||||
-rw-r--r-- | src/python/grpcio/setup.py | 42 | ||||
-rw-r--r-- | src/python/grpcio_test/.gitignore | 2 | ||||
-rw-r--r-- | src/python/grpcio_test/grpc_test/_cython/cygrpc_test.py | 22 | ||||
-rw-r--r-- | src/python/grpcio_test/grpc_test/test_common.py | 12 | ||||
-rw-r--r-- | src/python/grpcio_test/setup.cfg | 1 | ||||
-rw-r--r-- | src/python/grpcio_test/setup.py | 2 | ||||
-rw-r--r-- | tools/dockerfile/grpc_python_base/Dockerfile | 2 |
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 |