aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/python
diff options
context:
space:
mode:
authorGravatar Alistair Veitch <aveitch@google.com>2016-02-11 09:23:20 -0800
committerGravatar Alistair Veitch <aveitch@google.com>2016-02-11 09:23:20 -0800
commit749250f6a00a97b0deb4c92afc25f3f1eab04c14 (patch)
tree93c15de447ed683f5778e7c2283a802688d3ca0d /src/python
parent532519ac210d59551520c70cb3aa5eb7cc1f1b37 (diff)
parentf79366a3c99592eccd9c719c86dca2f976804d3d (diff)
merge to HEAD
Diffstat (limited to 'src/python')
-rw-r--r--src/python/grpcio/.gitignore2
-rw-r--r--src/python/grpcio/commands.py42
-rw-r--r--src/python/grpcio/grpc/_adapter/_low.py5
-rw-r--r--src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi9
-rw-r--r--src/python/grpcio/grpc/_cython/_cygrpc/security.pxd.pxi32
-rw-r--r--src/python/grpcio/grpc/_cython/_cygrpc/security.pyx.pxi44
-rw-r--r--src/python/grpcio/grpc/_cython/cygrpc.pxd1
-rw-r--r--src/python/grpcio/grpc/_cython/cygrpc.pyx3
-rw-r--r--src/python/grpcio/grpc_core_dependencies.py86
-rw-r--r--src/python/grpcio/grpc_version.py32
-rw-r--r--src/python/grpcio/tests/unit/beta/_implementations_test.py54
11 files changed, 243 insertions, 67 deletions
diff --git a/src/python/grpcio/.gitignore b/src/python/grpcio/.gitignore
index 1d804e1ffc..6e5e65096c 100644
--- a/src/python/grpcio/.gitignore
+++ b/src/python/grpcio/.gitignore
@@ -14,4 +14,4 @@ nosetests.xml
doc/
_grpcio_metadata.py
htmlcov/
-grpc/_adapter/credentials
+grpc/_cython/_credentials
diff --git a/src/python/grpcio/commands.py b/src/python/grpcio/commands.py
index 31bd00e94e..774e7ad6a1 100644
--- a/src/python/grpcio/commands.py
+++ b/src/python/grpcio/commands.py
@@ -54,7 +54,10 @@ PYTHON_STEM = os.path.dirname(os.path.abspath(__file__))
BINARIES_REPOSITORY = os.environ.get(
'GRPC_PYTHON_BINARIES_REPOSITORY',
- 'https://storage.googleapis.com/grpc-precompiled-binaries/python/')
+ 'https://storage.googleapis.com/grpc-precompiled-binaries/python')
+
+USE_GRPC_CUSTOM_BDIST = bool(int(os.environ.get(
+ 'GRPC_PYTHON_USE_CUSTOM_BDIST', '1')))
CONF_PY_ADDENDUM = """
extensions.append('sphinx.ext.napoleon')
@@ -135,7 +138,7 @@ class Install(install.install, EggNameMixin):
def initialize_options(self):
install.install.initialize_options(self)
- self.use_grpc_custom_bdist = bool(int(os.environ.get('GRPC_PYTHON_USE_CUSTOM_BDIST', '1')))
+ self.use_grpc_custom_bdist = USE_GRPC_CUSTOM_BDIST
def finalize_options(self):
install.install.finalize_options(self)
@@ -143,22 +146,25 @@ class Install(install.install, EggNameMixin):
def run(self):
if self.use_grpc_custom_bdist:
try:
- egg_path = _get_grpc_custom_bdist_egg(self.egg_name(True),
- self.egg_name(False))
- except CommandError as error:
- sys.stderr.write(
- '\nWARNING: Failed to acquire grpcio prebuilt binary:\n'
- '{}.\n\n'.format(error.message))
- raise
- try:
- self._run_bdist_retrieval_install(egg_path)
- except Exception as error:
- # if anything else happens (and given how there's no way to really know
- # what's happening in setuptools here, I mean *anything*), warn the user
- # and fall back to building from source.
- sys.stderr.write(
- '{}\nWARNING: Failed to install grpcio prebuilt binary.\n\n'
- .format(traceback.format_exc()))
+ try:
+ egg_path = _get_grpc_custom_bdist_egg(self.egg_name(True),
+ self.egg_name(False))
+ except CommandError as error:
+ sys.stderr.write(
+ '\nWARNING: Failed to acquire grpcio prebuilt binary:\n'
+ '{}.\n\n'.format(error.message))
+ raise
+ try:
+ self._run_bdist_retrieval_install(egg_path)
+ except Exception as error:
+ # if anything else happens (and given how there's no way to really know
+ # what's happening in setuptools here, I mean *anything*), warn the user
+ # and fall back to building from source.
+ sys.stderr.write(
+ '{}\nWARNING: Failed to install grpcio prebuilt binary.\n\n'
+ .format(traceback.format_exc()))
+ raise
+ except Exception:
install.install.run(self)
else:
install.install.run(self)
diff --git a/src/python/grpcio/grpc/_adapter/_low.py b/src/python/grpcio/grpc/_adapter/_low.py
index a850c57741..62fd52ab40 100644
--- a/src/python/grpcio/grpc/_adapter/_low.py
+++ b/src/python/grpcio/grpc/_adapter/_low.py
@@ -27,7 +27,6 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-import pkg_resources
import threading
from grpc import _grpcio_metadata
@@ -35,7 +34,6 @@ from grpc._cython import cygrpc
from grpc._adapter import _implementations
from grpc._adapter import _types
-_ROOT_CERTIFICATES_RESOURCE_PATH = 'credentials/roots.pem'
_USER_AGENT = 'Python-gRPC-{}'.format(_grpcio_metadata.__version__)
ChannelCredentials = cygrpc.ChannelCredentials
@@ -56,9 +54,6 @@ def channel_credentials_ssl(
pair = None
if private_key is not None or certificate_chain is not None:
pair = cygrpc.SslPemKeyCertPair(private_key, certificate_chain)
- if root_certificates is None:
- root_certificates = pkg_resources.resource_string(
- __name__, _ROOT_CERTIFICATES_RESOURCE_PATH)
return cygrpc.channel_credentials_ssl(root_certificates, pair)
diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi
index 9c85e0ee1b..bbeed9ad40 100644
--- a/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi
+++ b/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi
@@ -100,6 +100,11 @@ cdef extern from "grpc/_cython/loader.h":
GRPC_STATUS_DATA_LOSS
GRPC_STATUS__DO_NOT_USE
+ ctypedef enum grpc_ssl_roots_override_result:
+ GRPC_SSL_ROOTS_OVERRIDE_OK
+ GRPC_SSL_ROOTS_OVERRIDE_FAILED_PERMANENTLY
+ GRPC_SSL_ROOTS_OVERRIDE_FAILED
+
struct grpc_byte_buffer_reader:
# We don't care about the internals
pass
@@ -338,6 +343,10 @@ cdef extern from "grpc/_cython/loader.h":
# We don't care about the internals (and in fact don't know them)
pass
+ ctypedef void (*grpc_ssl_roots_override_callback)(char **pem_root_certs)
+
+ void grpc_set_ssl_roots_override_callback(grpc_ssl_roots_override_callback cb)
+
grpc_channel_credentials *grpc_google_default_credentials_create()
grpc_channel_credentials *grpc_ssl_credentials_create(
const char *pem_root_certs, grpc_ssl_pem_key_cert_pair *pem_key_cert_pair,
diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/security.pxd.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/security.pxd.pxi
new file mode 100644
index 0000000000..3a952ca309
--- /dev/null
+++ b/src/python/grpcio/grpc/_cython/_cygrpc/security.pxd.pxi
@@ -0,0 +1,32 @@
+# Copyright 2016, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+cdef grpc_ssl_roots_override_result ssl_roots_override_callback(
+ char **pem_root_certs) with gil
diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/security.pyx.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/security.pyx.pxi
new file mode 100644
index 0000000000..23cee7bd6e
--- /dev/null
+++ b/src/python/grpcio/grpc/_cython/_cygrpc/security.pyx.pxi
@@ -0,0 +1,44 @@
+# Copyright 2016, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (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 libc.string cimport memcpy
+
+import pkg_resources
+
+
+cdef grpc_ssl_roots_override_result ssl_roots_override_callback(
+ char **pem_root_certs) with gil:
+ temporary_pem_root_certs = pkg_resources.resource_string(
+ 'grpc._cython', '_credentials/roots.pem')
+ pem_root_certs[0] = <char *>gpr_malloc(len(temporary_pem_root_certs) + 1)
+ memcpy(
+ pem_root_certs[0], <char *>temporary_pem_root_certs,
+ len(temporary_pem_root_certs))
+ pem_root_certs[0][len(temporary_pem_root_certs)] = '\0'
+ return GRPC_SSL_ROOTS_OVERRIDE_OK
diff --git a/src/python/grpcio/grpc/_cython/cygrpc.pxd b/src/python/grpcio/grpc/_cython/cygrpc.pxd
index f22346c4f3..61b0fa788f 100644
--- a/src/python/grpcio/grpc/_cython/cygrpc.pxd
+++ b/src/python/grpcio/grpc/_cython/cygrpc.pxd
@@ -34,4 +34,5 @@ include "grpc/_cython/_cygrpc/channel.pxd.pxi"
include "grpc/_cython/_cygrpc/credentials.pxd.pxi"
include "grpc/_cython/_cygrpc/completion_queue.pxd.pxi"
include "grpc/_cython/_cygrpc/records.pxd.pxi"
+include "grpc/_cython/_cygrpc/security.pxd.pxi"
include "grpc/_cython/_cygrpc/server.pxd.pxi"
diff --git a/src/python/grpcio/grpc/_cython/cygrpc.pyx b/src/python/grpcio/grpc/_cython/cygrpc.pyx
index b1836bf5be..30cc7a132b 100644
--- a/src/python/grpcio/grpc/_cython/cygrpc.pyx
+++ b/src/python/grpcio/grpc/_cython/cygrpc.pyx
@@ -40,6 +40,7 @@ include "grpc/_cython/_cygrpc/channel.pyx.pxi"
include "grpc/_cython/_cygrpc/credentials.pyx.pxi"
include "grpc/_cython/_cygrpc/completion_queue.pyx.pxi"
include "grpc/_cython/_cygrpc/records.pyx.pxi"
+include "grpc/_cython/_cygrpc/security.pyx.pxi"
include "grpc/_cython/_cygrpc/server.pyx.pxi"
#
@@ -58,6 +59,8 @@ cdef class _ModuleState:
raise ImportError('failed to load core gRPC library')
grpc_init()
self.is_loaded = True
+ grpc_set_ssl_roots_override_callback(
+ <grpc_ssl_roots_override_callback>ssl_roots_override_callback)
def __dealloc__(self):
if self.is_loaded:
diff --git a/src/python/grpcio/grpc_core_dependencies.py b/src/python/grpcio/grpc_core_dependencies.py
index 8d289eab03..632a7c4c08 100644
--- a/src/python/grpcio/grpc_core_dependencies.py
+++ b/src/python/grpcio/grpc_core_dependencies.py
@@ -30,6 +30,49 @@
# AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio/grpc_core_dependencies.py.template`!!!
CORE_SOURCE_FILES = [
+ 'src/core/profiling/basic_timers.c',
+ 'src/core/profiling/stap_timers.c',
+ 'src/core/support/alloc.c',
+ 'src/core/support/avl.c',
+ 'src/core/support/cmdline.c',
+ 'src/core/support/cpu_iphone.c',
+ 'src/core/support/cpu_linux.c',
+ 'src/core/support/cpu_posix.c',
+ 'src/core/support/cpu_windows.c',
+ 'src/core/support/env_linux.c',
+ 'src/core/support/env_posix.c',
+ 'src/core/support/env_win32.c',
+ 'src/core/support/file.c',
+ 'src/core/support/file_posix.c',
+ 'src/core/support/file_win32.c',
+ 'src/core/support/histogram.c',
+ 'src/core/support/host_port.c',
+ 'src/core/support/log.c',
+ 'src/core/support/log_android.c',
+ 'src/core/support/log_linux.c',
+ 'src/core/support/log_posix.c',
+ 'src/core/support/log_win32.c',
+ 'src/core/support/murmur_hash.c',
+ 'src/core/support/slice.c',
+ 'src/core/support/slice_buffer.c',
+ 'src/core/support/stack_lockfree.c',
+ 'src/core/support/string.c',
+ 'src/core/support/string_posix.c',
+ 'src/core/support/string_win32.c',
+ 'src/core/support/subprocess_posix.c',
+ 'src/core/support/subprocess_windows.c',
+ 'src/core/support/sync.c',
+ 'src/core/support/sync_posix.c',
+ 'src/core/support/sync_win32.c',
+ 'src/core/support/thd.c',
+ 'src/core/support/thd_posix.c',
+ 'src/core/support/thd_win32.c',
+ 'src/core/support/time.c',
+ 'src/core/support/time_posix.c',
+ 'src/core/support/time_precise.c',
+ 'src/core/support/time_win32.c',
+ 'src/core/support/tls_pthread.c',
+ 'src/core/support/wrap_memcpy.c',
'src/core/httpcli/httpcli_security_connector.c',
'src/core/security/base64.c',
'src/core/security/client_auth_filter.c',
@@ -178,49 +221,6 @@ CORE_SOURCE_FILES = [
'src/core/transport/static_metadata.c',
'src/core/transport/transport.c',
'src/core/transport/transport_op_string.c',
- 'src/core/profiling/basic_timers.c',
- 'src/core/profiling/stap_timers.c',
- 'src/core/support/alloc.c',
- 'src/core/support/avl.c',
- 'src/core/support/cmdline.c',
- 'src/core/support/cpu_iphone.c',
- 'src/core/support/cpu_linux.c',
- 'src/core/support/cpu_posix.c',
- 'src/core/support/cpu_windows.c',
- 'src/core/support/env_linux.c',
- 'src/core/support/env_posix.c',
- 'src/core/support/env_win32.c',
- 'src/core/support/file.c',
- 'src/core/support/file_posix.c',
- 'src/core/support/file_win32.c',
- 'src/core/support/histogram.c',
- 'src/core/support/host_port.c',
- 'src/core/support/log.c',
- 'src/core/support/log_android.c',
- 'src/core/support/log_linux.c',
- 'src/core/support/log_posix.c',
- 'src/core/support/log_win32.c',
- 'src/core/support/murmur_hash.c',
- 'src/core/support/slice.c',
- 'src/core/support/slice_buffer.c',
- 'src/core/support/stack_lockfree.c',
- 'src/core/support/string.c',
- 'src/core/support/string_posix.c',
- 'src/core/support/string_win32.c',
- 'src/core/support/subprocess_posix.c',
- 'src/core/support/subprocess_windows.c',
- 'src/core/support/sync.c',
- 'src/core/support/sync_posix.c',
- 'src/core/support/sync_win32.c',
- 'src/core/support/thd.c',
- 'src/core/support/thd_posix.c',
- 'src/core/support/thd_win32.c',
- 'src/core/support/time.c',
- 'src/core/support/time_posix.c',
- 'src/core/support/time_precise.c',
- 'src/core/support/time_win32.c',
- 'src/core/support/tls_pthread.c',
- 'src/core/support/wrap_memcpy.c',
'src/core/census/context.c',
'src/core/census/initialize.c',
'src/core/census/log.c',
diff --git a/src/python/grpcio/grpc_version.py b/src/python/grpcio/grpc_version.py
new file mode 100644
index 0000000000..75b88cfd61
--- /dev/null
+++ b/src/python/grpcio/grpc_version.py
@@ -0,0 +1,32 @@
+# Copyright 2015-2016, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio/grpc_version.py.template`!!!
+
+VERSION='0.14.0.dev0'
diff --git a/src/python/grpcio/tests/unit/beta/_implementations_test.py b/src/python/grpcio/tests/unit/beta/_implementations_test.py
new file mode 100644
index 0000000000..6b32305af7
--- /dev/null
+++ b/src/python/grpcio/tests/unit/beta/_implementations_test.py
@@ -0,0 +1,54 @@
+# Copyright 2016, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""Tests the implementations module of the gRPC Python Beta API."""
+
+import unittest
+
+from grpc.beta import implementations
+from tests.unit import resources
+
+
+class ChannelCredentialsTest(unittest.TestCase):
+
+ def test_runtime_provided_root_certificates(self):
+ channel_credentials = implementations.ssl_channel_credentials(
+ None, None, None)
+ self.assertIsInstance(
+ channel_credentials, implementations.ChannelCredentials)
+
+ def test_application_provided_root_certificates(self):
+ channel_credentials = implementations.ssl_channel_credentials(
+ resources.test_root_certificates(), None, None)
+ self.assertIsInstance(
+ channel_credentials, implementations.ChannelCredentials)
+
+
+if __name__ == '__main__':
+ unittest.main(verbosity=2)