From 2af458679533b844ae165774f2ab0f5e95fa2c29 Mon Sep 17 00:00:00 2001 From: Bu Sun Kim Date: Mon, 22 Jul 2019 11:28:23 -0700 Subject: [PATCH 1/3] Add client_options to api core documentation. --- api_core/docs/client_options.rst | 6 ++++++ api_core/docs/index.rst | 1 + api_core/google/api_core/client_options.py | 21 +++++++++++++++++++++ 3 files changed, 28 insertions(+) create mode 100644 api_core/docs/client_options.rst diff --git a/api_core/docs/client_options.rst b/api_core/docs/client_options.rst new file mode 100644 index 000000000000..da7c9a339bbd --- /dev/null +++ b/api_core/docs/client_options.rst @@ -0,0 +1,6 @@ +Client Options +========================== + +.. automodule:: google.api_core.client_options + :members: + :show-inheritance: diff --git a/api_core/docs/index.rst b/api_core/docs/index.rst index 9dec6e8e1de4..67572a0bbf96 100644 --- a/api_core/docs/index.rst +++ b/api_core/docs/index.rst @@ -9,6 +9,7 @@ Core .. toctree:: auth client_info + client_options exceptions futures helpers diff --git a/api_core/google/api_core/client_options.py b/api_core/google/api_core/client_options.py index 580aba9f50c3..1144d2f62a37 100644 --- a/api_core/google/api_core/client_options.py +++ b/api_core/google/api_core/client_options.py @@ -16,6 +16,27 @@ Client options provide a consistent interface for user options to be defined across clients. + +You can pass a client options object to a client. + +.. code-block:: python + + from google.api_core.client_options import ClientOptions + from google.cloud.vision_v1 import ImageAnnotatorClient + + options = ClientOptions(api_endpoint="foo.googleapis.com") + + client = ImageAnnotatorClient(client_options=options) + +You can also pass a dictionary. + +.. code-block:: python + + from google.cloud.vision_v1 import ImageAnnotatorClient + + client = ImageAnnotatorClient(client_options={"api_endpoint": "foo.googleapis.com"}) + + """ From b3a6acd90790d0e759aeea216f746fc233ed646d Mon Sep 17 00:00:00 2001 From: Bu Sun Kim Date: Mon, 22 Jul 2019 15:19:43 -0700 Subject: [PATCH 2/3] Add client options to storage client. --- storage/google/cloud/storage/_http.py | 4 +--- storage/google/cloud/storage/blob.py | 10 ++++++---- storage/google/cloud/storage/bucket.py | 8 +++++--- storage/google/cloud/storage/client.py | 18 +++++++++++++++++- 4 files changed, 29 insertions(+), 11 deletions(-) diff --git a/storage/google/cloud/storage/_http.py b/storage/google/cloud/storage/_http.py index 3dac5dece2ff..425a8296b98d 100644 --- a/storage/google/cloud/storage/_http.py +++ b/storage/google/cloud/storage/_http.py @@ -30,14 +30,12 @@ class Connection(_http.JSONConnection): """ def __init__(self, client, client_info=None): + Connection.API_BASE_URL = client.api_endpoint super(Connection, self).__init__(client, client_info) self._client_info.gapic_version = __version__ self._client_info.client_library_version = __version__ - API_BASE_URL = _http.API_BASE_URL - """The base of the API call URL.""" - API_VERSION = "v1" """The version of the API, used in building the API call's URL.""" diff --git a/storage/google/cloud/storage/blob.py b/storage/google/cloud/storage/blob.py index 9c89c52b9e24..594d11430221 100644 --- a/storage/google/cloud/storage/blob.py +++ b/storage/google/cloud/storage/blob.py @@ -60,7 +60,6 @@ from google.cloud.storage.acl import ObjectACL -_API_ACCESS_ENDPOINT = "https://storage.googleapis.com" _DEFAULT_CONTENT_TYPE = u"application/octet-stream" _DOWNLOAD_URL_TEMPLATE = ( u"https://www.googleapis.com/download/storage/v1{path}?alt=media" @@ -296,7 +295,7 @@ def public_url(self): :returns: The public URL for this blob. """ return "{storage_base_url}/{bucket_name}/{quoted_name}".format( - storage_base_url=_API_ACCESS_ENDPOINT, + storage_base_url=self.bucket.client.api_endpoint, bucket_name=self.bucket.name, quoted_name=_quote(self.name, safe=b"/~"), ) @@ -304,7 +303,7 @@ def public_url(self): def generate_signed_url( self, expiration=None, - api_access_endpoint=_API_ACCESS_ENDPOINT, + api_access_endpoint=None, method="GET", content_md5=None, content_type=None, @@ -342,7 +341,8 @@ def generate_signed_url( :param expiration: Point in time when the signed URL should expire. :type api_access_endpoint: str - :param api_access_endpoint: Optional URI base. + :param api_access_endpoint: Optional URI base. If not passed, falls back + to the api_endpoint of the client. :type method: str :param method: The HTTP verb that will be used when requesting the URL. @@ -423,6 +423,8 @@ def generate_signed_url( if credentials is None: client = self._require_client(client) + if api_access_endpoint is None: + api_access_endpoint = client.api_endpoint credentials = client._credentials if version == "v2": diff --git a/storage/google/cloud/storage/bucket.py b/storage/google/cloud/storage/bucket.py index 3c3afbe97af7..1e14d9f8646c 100644 --- a/storage/google/cloud/storage/bucket.py +++ b/storage/google/cloud/storage/bucket.py @@ -47,7 +47,6 @@ "valid before the bucket is created. Instead, pass the location " "to `Bucket.create`." ) -_API_ACCESS_ENDPOINT = "https://storage.googleapis.com" def _blobs_page_start(iterator, page, response): @@ -2065,7 +2064,7 @@ def lock_retention_policy(self, client=None): def generate_signed_url( self, expiration=None, - api_access_endpoint=_API_ACCESS_ENDPOINT, + api_access_endpoint=None, method="GET", headers=None, query_parameters=None, @@ -2098,7 +2097,8 @@ def generate_signed_url( :param expiration: Point in time when the signed URL should expire. :type api_access_endpoint: str - :param api_access_endpoint: Optional URI base. + :param api_access_endpoint: Optional URI base. If not passed, falls back + to the api_endpoint of the client. :type method: str :param method: The HTTP verb that will be used when requesting the URL. @@ -2151,6 +2151,8 @@ def generate_signed_url( if credentials is None: client = self._require_client(client) + if api_access_endpoint is None: + api_access_endpoint = client.api_endpoint credentials = client._credentials if version == "v2": diff --git a/storage/google/cloud/storage/client.py b/storage/google/cloud/storage/client.py index a3aa5d628fa9..f4149e92ef35 100644 --- a/storage/google/cloud/storage/client.py +++ b/storage/google/cloud/storage/client.py @@ -18,6 +18,7 @@ from google.auth.credentials import AnonymousCredentials +import google.api_core.client_options from google.api_core import page_iterator from google.cloud._helpers import _LocalStack from google.cloud.client import ClientWithProject @@ -60,8 +61,14 @@ class Client(ClientWithProject): requests. If ``None``, then default info will be used. Generally, you only need to set this if you're developing your own library or partner tool. + :type client_options: Union(Dict, :class:`~google.api_core.client_options.ClientOptions`) + :param client_options: + Client options used to set user options on the client. API Endpoint + should be set through client_options. """ + API_ENDPOINT = "https://storage.googleapis.com" + SCOPE = ( "https://www.googleapis.com/auth/devstorage.full_control", "https://www.googleapis.com/auth/devstorage.read_only", @@ -69,7 +76,8 @@ class Client(ClientWithProject): ) """The scopes required for authenticating as a Cloud Storage consumer.""" - def __init__(self, project=_marker, credentials=None, _http=None, client_info=None): + def __init__(self, project=_marker, credentials=None, _http=None, client_info=None, + client_options=None): self._base_connection = None if project is None: no_project = True @@ -78,6 +86,14 @@ def __init__(self, project=_marker, credentials=None, _http=None, client_info=No no_project = False if project is _marker: project = None + + self.api_endpoint = self.API_ENDPOINT + if client_options: + if type(client_options) == dict: + client_options = google.api_core.client_options.from_dict(client_options) + if client_options.api_endpoint: + self.api_endpoint = client_options.api_endpoint + super(Client, self).__init__( project=project, credentials=credentials, _http=_http ) From 468a70fcdd011b3c60b103079f48a26961942e1f Mon Sep 17 00:00:00 2001 From: Bu Sun Kim Date: Tue, 30 Jul 2019 12:58:03 -0700 Subject: [PATCH 3/3] Revert storage changes. --- storage/google/cloud/storage/_http.py | 4 +++- storage/google/cloud/storage/blob.py | 10 ++++------ storage/google/cloud/storage/bucket.py | 8 +++----- storage/google/cloud/storage/client.py | 18 +----------------- 4 files changed, 11 insertions(+), 29 deletions(-) diff --git a/storage/google/cloud/storage/_http.py b/storage/google/cloud/storage/_http.py index 425a8296b98d..3dac5dece2ff 100644 --- a/storage/google/cloud/storage/_http.py +++ b/storage/google/cloud/storage/_http.py @@ -30,12 +30,14 @@ class Connection(_http.JSONConnection): """ def __init__(self, client, client_info=None): - Connection.API_BASE_URL = client.api_endpoint super(Connection, self).__init__(client, client_info) self._client_info.gapic_version = __version__ self._client_info.client_library_version = __version__ + API_BASE_URL = _http.API_BASE_URL + """The base of the API call URL.""" + API_VERSION = "v1" """The version of the API, used in building the API call's URL.""" diff --git a/storage/google/cloud/storage/blob.py b/storage/google/cloud/storage/blob.py index 594d11430221..9c89c52b9e24 100644 --- a/storage/google/cloud/storage/blob.py +++ b/storage/google/cloud/storage/blob.py @@ -60,6 +60,7 @@ from google.cloud.storage.acl import ObjectACL +_API_ACCESS_ENDPOINT = "https://storage.googleapis.com" _DEFAULT_CONTENT_TYPE = u"application/octet-stream" _DOWNLOAD_URL_TEMPLATE = ( u"https://www.googleapis.com/download/storage/v1{path}?alt=media" @@ -295,7 +296,7 @@ def public_url(self): :returns: The public URL for this blob. """ return "{storage_base_url}/{bucket_name}/{quoted_name}".format( - storage_base_url=self.bucket.client.api_endpoint, + storage_base_url=_API_ACCESS_ENDPOINT, bucket_name=self.bucket.name, quoted_name=_quote(self.name, safe=b"/~"), ) @@ -303,7 +304,7 @@ def public_url(self): def generate_signed_url( self, expiration=None, - api_access_endpoint=None, + api_access_endpoint=_API_ACCESS_ENDPOINT, method="GET", content_md5=None, content_type=None, @@ -341,8 +342,7 @@ def generate_signed_url( :param expiration: Point in time when the signed URL should expire. :type api_access_endpoint: str - :param api_access_endpoint: Optional URI base. If not passed, falls back - to the api_endpoint of the client. + :param api_access_endpoint: Optional URI base. :type method: str :param method: The HTTP verb that will be used when requesting the URL. @@ -423,8 +423,6 @@ def generate_signed_url( if credentials is None: client = self._require_client(client) - if api_access_endpoint is None: - api_access_endpoint = client.api_endpoint credentials = client._credentials if version == "v2": diff --git a/storage/google/cloud/storage/bucket.py b/storage/google/cloud/storage/bucket.py index 1e14d9f8646c..3c3afbe97af7 100644 --- a/storage/google/cloud/storage/bucket.py +++ b/storage/google/cloud/storage/bucket.py @@ -47,6 +47,7 @@ "valid before the bucket is created. Instead, pass the location " "to `Bucket.create`." ) +_API_ACCESS_ENDPOINT = "https://storage.googleapis.com" def _blobs_page_start(iterator, page, response): @@ -2064,7 +2065,7 @@ def lock_retention_policy(self, client=None): def generate_signed_url( self, expiration=None, - api_access_endpoint=None, + api_access_endpoint=_API_ACCESS_ENDPOINT, method="GET", headers=None, query_parameters=None, @@ -2097,8 +2098,7 @@ def generate_signed_url( :param expiration: Point in time when the signed URL should expire. :type api_access_endpoint: str - :param api_access_endpoint: Optional URI base. If not passed, falls back - to the api_endpoint of the client. + :param api_access_endpoint: Optional URI base. :type method: str :param method: The HTTP verb that will be used when requesting the URL. @@ -2151,8 +2151,6 @@ def generate_signed_url( if credentials is None: client = self._require_client(client) - if api_access_endpoint is None: - api_access_endpoint = client.api_endpoint credentials = client._credentials if version == "v2": diff --git a/storage/google/cloud/storage/client.py b/storage/google/cloud/storage/client.py index f4149e92ef35..a3aa5d628fa9 100644 --- a/storage/google/cloud/storage/client.py +++ b/storage/google/cloud/storage/client.py @@ -18,7 +18,6 @@ from google.auth.credentials import AnonymousCredentials -import google.api_core.client_options from google.api_core import page_iterator from google.cloud._helpers import _LocalStack from google.cloud.client import ClientWithProject @@ -61,14 +60,8 @@ class Client(ClientWithProject): requests. If ``None``, then default info will be used. Generally, you only need to set this if you're developing your own library or partner tool. - :type client_options: Union(Dict, :class:`~google.api_core.client_options.ClientOptions`) - :param client_options: - Client options used to set user options on the client. API Endpoint - should be set through client_options. """ - API_ENDPOINT = "https://storage.googleapis.com" - SCOPE = ( "https://www.googleapis.com/auth/devstorage.full_control", "https://www.googleapis.com/auth/devstorage.read_only", @@ -76,8 +69,7 @@ class Client(ClientWithProject): ) """The scopes required for authenticating as a Cloud Storage consumer.""" - def __init__(self, project=_marker, credentials=None, _http=None, client_info=None, - client_options=None): + def __init__(self, project=_marker, credentials=None, _http=None, client_info=None): self._base_connection = None if project is None: no_project = True @@ -86,14 +78,6 @@ def __init__(self, project=_marker, credentials=None, _http=None, client_info=No no_project = False if project is _marker: project = None - - self.api_endpoint = self.API_ENDPOINT - if client_options: - if type(client_options) == dict: - client_options = google.api_core.client_options.from_dict(client_options) - if client_options.api_endpoint: - self.api_endpoint = client_options.api_endpoint - super(Client, self).__init__( project=project, credentials=credentials, _http=_http )