Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 0 additions & 5 deletions appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,25 +30,21 @@ environment:
- PYTHON: "C:\\Python34"
PYTHON_VERSION: "3.4.4"
PYTHON_ARCH: "32"
# Use mocked-up GRPC for now

- PYTHON: "C:\\Python34-x64"
PYTHON_VERSION: "3.4.4"
PYTHON_ARCH: "64"
# Use mocked-up GRPC for now

# Python 3.5.1 is the latest Python 3.5 with a Windows installer
# Python 3.5.1 is the overall latest
# https://www.python.org/ftp/python/3.5.1/
- PYTHON: "C:\\Python35"
PYTHON_VERSION: "3.5.1"
PYTHON_ARCH: "32"
# Use mocked-up GRPC for now

- PYTHON: "C:\\Python35-x64"
PYTHON_VERSION: "3.5.1"
PYTHON_ARCH: "64"
# Use mocked-up GRPC for now

install:
- ECHO "Filesystem root:"
Expand Down Expand Up @@ -85,7 +81,6 @@ build_script:
- "%CMD_IN_ENV% python setup.py build"

test_script:
- "set PYTHONPATH=%GRPC_PATH%"
- "%CMD_IN_ENV% pip list"
# Run the project tests
- "%CMD_IN_ENV% python setup.py nosetests"
Expand Down
8 changes: 3 additions & 5 deletions docs/bigtable-client-intro.rst
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,9 @@ Long-lived Defaults
-------------------

When creating a :class:`Client <gcloud.bigtable.client.Client>`, the
``user_agent`` and ``timeout_seconds`` arguments have sensible
defaults
(:data:`DEFAULT_USER_AGENT <gcloud.bigtable.client.DEFAULT_USER_AGENT>` and
:data:`DEFAULT_TIMEOUT_SECONDS <gcloud.bigtable.client.DEFAULT_TIMEOUT_SECONDS>`).
However, you may over-ride them and these will be used throughout all API
``user_agent`` argument has sensible a default
(:data:`DEFAULT_USER_AGENT <gcloud.bigtable.client.DEFAULT_USER_AGENT>`).
However, you may over-ride it and the value will be used throughout all API
requests made with the ``client`` you create.

Configuration
Expand Down
45 changes: 32 additions & 13 deletions gcloud/_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,13 @@
except ImportError:
app_identity = None
try:
from grpc.beta import implementations
from google.gax.grpc import exc_to_code as beta_exc_to_code
import grpc
from grpc._channel import _Rendezvous

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.

except ImportError: # pragma: NO COVER
implementations = None
beta_exc_to_code = None
grpc = None
_Rendezvous = Exception
import six
from six.moves.http_client import HTTPConnection
from six.moves import configparser
Expand Down Expand Up @@ -572,10 +576,10 @@ def __call__(self, unused_context, callback):
callback(headers, None)


def make_stub(credentials, user_agent, stub_factory, host, port):
def make_stub(credentials, user_agent, stub_class, host, port):
"""Makes a stub for an RPC service.

Uses / depends on the beta implementation of gRPC.
Uses / depends on gRPC.

:type credentials: :class:`oauth2client.client.OAuth2Credentials`
:param credentials: The OAuth2 Credentials to use for creating
Expand All @@ -584,29 +588,44 @@ def make_stub(credentials, user_agent, stub_factory, host, port):
:type user_agent: str
:param user_agent: (Optional) The user agent to be used with API requests.

:type stub_factory: callable
:param stub_factory: A factory which will create a gRPC stub for
a given service.
:type stub_class: type
:param stub_class: A gRPC stub type for a given service.

:type host: str
:param host: The host for the service.

:type port: int
:param port: The port for the service.

:rtype: :class:`grpc.beta._stub._AutoIntermediary`
:rtype: object, instance of ``stub_class``
:returns: The stub object used to make gRPC requests to a given API.
"""
# Leaving the first argument to ssl_channel_credentials() as None
# loads root certificates from `grpc/_adapter/credentials/roots.pem`.
transport_creds = implementations.ssl_channel_credentials(None, None, None)
transport_creds = grpc.ssl_channel_credentials()
custom_metadata_plugin = MetadataPlugin(credentials, user_agent)
auth_creds = implementations.metadata_call_credentials(
auth_creds = grpc.metadata_call_credentials(
custom_metadata_plugin, name='google_creds')
channel_creds = implementations.composite_channel_credentials(
channel_creds = grpc.composite_channel_credentials(
transport_creds, auth_creds)
channel = implementations.secure_channel(host, port, channel_creds)
return stub_factory(channel)
target = '%s:%d' % (host, port)
channel = grpc.secure_channel(target, channel_creds)
return stub_class(channel)


def exc_to_code(exc):

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.

"""Retrieves the status code from a gRPC exception.

:type exc: :class:`Exception`
:param exc: An exception from gRPC beta or stable.

:rtype: :class:`grpc.StatusCode`
:returns: The status code attached to the exception.
"""
if isinstance(exc, _Rendezvous):
return exc.code()
else:
return beta_exc_to_code(exc)


try:
Expand Down
18 changes: 7 additions & 11 deletions gcloud/_testing.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,23 +58,19 @@ def __init__(self, **kw):
self.__dict__.update(kw)

def _make_grpc_error(self, status_code):
from grpc.framework.interfaces.face.face import AbortionError
from grpc._channel import _Rendezvous
from grpc._channel import _RPCState

class _DummyException(AbortionError):
code = status_code

def __init__(self):
super(_DummyException, self).__init__(
None, None, self.code, None)

return _DummyException()
details = 'Some error details.'
exc_state = _RPCState((), None, None, status_code, details)
return _Rendezvous(exc_state, None, None, None)

def _make_grpc_not_found(self):
from grpc.beta.interfaces import StatusCode
from grpc import StatusCode
return self._make_grpc_error(StatusCode.NOT_FOUND)

def _make_grpc_failed_precondition(self):
from grpc.beta.interfaces import StatusCode
from grpc import StatusCode
return self._make_grpc_error(StatusCode.FAILED_PRECONDITION)


Expand Down
2 changes: 1 addition & 1 deletion gcloud/bigtable/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,6 @@
"""

try:
import grpc.beta.implementations
import grpc
except ImportError as exc: # pragma: NO COVER
raise ImportError(_ERR_MSG, exc)
23 changes: 6 additions & 17 deletions gcloud/bigtable/_testing.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,6 @@ class _FakeStub(object):
def __init__(self, *results):
self.results = results
self.method_calls = []
self._entered = 0
self._exited = []

def __enter__(self):
self._entered += 1
return self

def __exit__(self, exc_type, exc_val, exc_tb):
self._exited.append((exc_type, exc_val, exc_tb))
return True

def __getattr__(self, name):
# We need not worry about attributes set in constructor
Expand All @@ -41,17 +31,16 @@ def __getattr__(self, name):
class _MethodMock(object):
"""Mock for API method attached to a gRPC stub.

In the beta implementation, these are of type.
:class:`grpc.framework.crust.implementations._UnaryUnaryMultiCallable`
These are of type :class:`grpc._channel._UnaryUnaryMultiCallable`.

This comment was marked as spam.

This comment was marked as spam.

"""

def __init__(self, name, factory):
def __init__(self, name, stub):
self._name = name
self._factory = factory
self._stub = stub

def __call__(self, *args, **kwargs):
"""Sync method meant to mock a gRPC stub request."""
self._factory.method_calls.append((self._name, args, kwargs))
curr_result, self._factory.results = (self._factory.results[0],
self._factory.results[1:])
self._stub.method_calls.append((self._name, args, kwargs))
curr_result, self._stub.results = (self._stub.results[0],
self._stub.results[1:])
return curr_result
Loading