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
10 changes: 5 additions & 5 deletions bigquery/google/cloud/bigquery/_http.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,11 @@


class Connection(_http.JSONConnection):
"""A connection to Google BigQuery via the JSON REST API."""
"""A connection to Google BigQuery via the JSON REST API.

:type client: :class:`~google.cloud.bigquery.client.Client`
:param client: The client that owns the current connection.
"""

API_BASE_URL = 'https://www.googleapis.com'
"""The base of the API call URL."""
Expand All @@ -28,7 +32,3 @@ class Connection(_http.JSONConnection):

API_URL_TEMPLATE = '{api_base_url}/bigquery/{api_version}{path}'
"""A template for the URL of a particular API call."""

SCOPE = ('https://www.googleapis.com/auth/bigquery',
'https://www.googleapis.com/auth/cloud-platform')
"""The scopes required for authenticating as a BigQuery consumer."""
7 changes: 5 additions & 2 deletions bigquery/google/cloud/bigquery/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,11 +72,14 @@ class Client(ClientWithProject):
``credentials`` for the current object.
"""

SCOPE = ('https://www.googleapis.com/auth/bigquery',
'https://www.googleapis.com/auth/cloud-platform')
"""The scopes required for authenticating as a BigQuery consumer."""

def __init__(self, project=None, credentials=None, http=None):
super(Client, self).__init__(
project=project, credentials=credentials, http=http)
self._connection = Connection(
credentials=self._credentials, http=self._http)
self._connection = Connection(self)

def list_projects(self, max_results=None, page_token=None):
"""List projects for the project associated with this client.
Expand Down
4 changes: 2 additions & 2 deletions bigquery/unit_tests/test__http.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ def _make_one(self, *args, **kw):
return self._get_target_class()(*args, **kw)

def test_build_api_url_no_extra_query_params(self):
conn = self._make_one()
conn = self._make_one(object())
URI = '/'.join([
conn.API_BASE_URL,
'bigquery',
Expand All @@ -40,7 +40,7 @@ def test_build_api_url_w_extra_query_params(self):
from six.moves.urllib.parse import parse_qsl
from six.moves.urllib.parse import urlsplit

conn = self._make_one()
conn = self._make_one(object())
uri = conn.build_api_url('/foo', {'bar': 'baz'})
scheme, netloc, path, qs, _ = urlsplit(uri)
self.assertEqual('%s://%s' % (scheme, netloc), conn.API_BASE_URL)
Expand Down
58 changes: 6 additions & 52 deletions core/google/cloud/_http.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,6 @@
import six
from six.moves.urllib.parse import urlencode

import google.auth.credentials
import google_auth_httplib2
import httplib2

from google.cloud.exceptions import make_exception


Expand All @@ -37,50 +33,14 @@
class Connection(object):
"""A generic connection to Google Cloud Platform.

Subclasses should understand only the basic types in method arguments,
however they should be capable of returning advanced types.

If no value is passed in for ``http``, a :class:`httplib2.Http` object
will be created and authorized with the ``credentials``. If not, the
``credentials`` and ``http`` need not be related.

Subclasses may seek to use the private key from ``credentials`` to sign
data.

A custom (non-``httplib2``) HTTP object must have a ``request`` method
which accepts the following arguments:

* ``uri``
* ``method``
* ``body``
* ``headers``

In addition, ``redirections`` and ``connection_type`` may be used.

Without the use of ``credentials.authorize(http)``, a custom ``http``
object will also need to be able to add a bearer token to API
requests and handle token refresh on 401 errors.

:type credentials: :class:`google.auth.credentials.Credentials` or
:class:`NoneType`
:param credentials: The credentials to use for this connection.

:type http: :class:`httplib2.Http` or class that defines ``request()``.
:param http: An optional HTTP object to make requests.
:type client: :class:`~google.cloud.client.Client`
:param client: The client that owns the current connection.
"""

USER_AGENT = DEFAULT_USER_AGENT

SCOPE = None
"""The scopes required for authenticating with a service.

Needs to be set by subclasses.
"""

def __init__(self, credentials=None, http=None):
self._http = http
self._credentials = google.auth.credentials.with_scopes_if_required(
credentials, self.SCOPE)
def __init__(self, client):
self._client = client

@property
def credentials(self):
Expand All @@ -90,7 +50,7 @@ def credentials(self):
:class:`NoneType`
:returns: The credentials object associated with this connection.
"""
return self._credentials
return self._client._credentials

@property
def http(self):
Expand All @@ -99,13 +59,7 @@ def http(self):
:rtype: :class:`httplib2.Http`
:returns: A Http object used to transport data.
"""
if self._http is None:
if self._credentials:
self._http = google_auth_httplib2.AuthorizedHttp(
self._credentials)
else:
self._http = httplib2.Http()
return self._http
return self._client._http


class JSONConnection(Connection):
Expand Down
44 changes: 42 additions & 2 deletions core/google/cloud/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

import google.auth.credentials
from google.oauth2 import service_account
import google_auth_httplib2
import six

from google.cloud._helpers import _determine_default_project
Expand Down Expand Up @@ -74,6 +75,26 @@ class Client(_ClientFactoryMixin):
Stores ``credentials`` and ``http`` object so that subclasses
can pass them along to a connection class.

If no value is passed in for ``http``, a :class:`httplib2.Http` object
will be created and authorized with the ``credentials``. If not, the
``credentials`` and ``http`` need not be related.

Callers and subclasses may seek to use the private key from
``credentials`` to sign data.

A custom (non-``httplib2``) HTTP object must have a ``request`` method
which accepts the following arguments:

* ``uri``
* ``method``
* ``body``
* ``headers``

In addition, ``redirections`` and ``connection_type`` may be used.

A custom ``http`` object will also need to be able to add a bearer token
to API requests and handle token refresh on 401 errors.

:type credentials: :class:`~google.auth.credentials.Credentials`
:param credentials: (Optional) The OAuth2 Credentials to use for this
client. If not passed (and if no ``http`` object is
Expand All @@ -88,15 +109,34 @@ class Client(_ClientFactoryMixin):
``credentials`` for the current object.
"""

SCOPE = None
"""The scopes required for authenticating with a service.

Needs to be set by subclasses.
"""

def __init__(self, credentials=None, http=None):
if (credentials is not None and
not isinstance(
credentials, google.auth.credentials.Credentials)):
raise ValueError(_GOOGLE_AUTH_CREDENTIALS_HELP)
if credentials is None and http is None:
credentials = get_credentials()
self._credentials = credentials
self._http = http
self._credentials = google.auth.credentials.with_scopes_if_required(
credentials, self.SCOPE)
self._http_internal = http

@property
def _http(self):
"""Getter for object used for HTTP transport.

:rtype: :class:`~httplib2.Http`
:returns: An HTTP object.
"""
if self._http_internal is None:
self._http_internal = google_auth_httplib2.AuthorizedHttp(
self._credentials)
return self._http_internal


class _ClientProjectMixin(object):
Expand Down
Loading