Repository: googleapis/python-api-core
Pull request #36 (2020-06-03 23:14:55)

feat(client_options): add new options 'quota_project' and 'credentialsAdd 'credentials_file' and 'quota_project' client options
Prerequisite for https://github.com/googleapis/gapic-generator-python/issues/432 and https://github.com/googleapis/gapic-generator-python/issues/433

busunkim96: Please hold off merging. Checking if we want quota project to be named `quota_project_id` or `quota_project`. 
software-dov: Who's involved in the `quota_project_id` vs `quota_project` decision?
busunkim96: > Who's involved in the `quota_project_id` vs `quota_project` decision?

@broady @shinfan Does `quota_project_id` vs `quota_project` matter?

The Python auth lib uses `quota_project_id`, so I'd prefer to be consistent.



shinfan: quota_project_id sounds good tome
software-dov: I'll wait until the beginning of tomorrow for a response from @broady or @shinfan . If I don't hear from either, I'll change to `quota_project_id` for assumed consistency.

Patch:
diff --git a/google/api_core/client_options.py b/google/api_core/client_options.py
index b6d9384..d272f40 100644
--- a/google/api_core/client_options.py
+++ b/google/api_core/client_options.py
@@ -53,15 +53,20 @@ class ClientOptions(object):
     """Client Options used to set options on clients.
 
     Args:
-        api_endpoint (str): The desired API endpoint, e.g., compute.googleapis.com
-        client_cert_source (Callable[[], (bytes, bytes)]): An optional callback
+        api_endpoint (Optional[str]): The desired API endpoint, e.g.,
+            compute.googleapis.com
+        client_cert_source (Optional[Callable[[], (bytes, bytes)]]): A callback
             which returns client certificate bytes and private key bytes both in
             PEM format. ``client_cert_source`` and ``client_encrypted_cert_source``
             are mutually exclusive.
-        client_encrypted_cert_source (Callable[[], (str, str, bytes)]): An optional
-            callback which returns client certificate file path, encrypted private
-            key file path, and the passphrase bytes.``client_cert_source`` and
-            ``client_encrypted_cert_source`` are mutually exclusive.
+        client_encrypted_cert_source (Optional[Callable[[], (str, str, bytes)]]):
+            A callback which returns client certificate file path, encrypted
+            private key file path, and the passphrase bytes.``client_cert_source``
+            and ``client_encrypted_cert_source`` are mutually exclusive.
+        quota_project_id (Optional[str]): A project name that a client's
+            quota belongs to.
+        credentials_file (Optional[str]): A path to a file storing credentials.
+        scopes (Optional[Sequence[str]]): OAuth access token override scopes.
 
     Raises:
         ValueError: If both ``client_cert_source`` and ``client_encrypted_cert_source``
@@ -73,6 +78,9 @@ class ClientOptions(object):
         api_endpoint=None,
         client_cert_source=None,
         client_encrypted_cert_source=None,
+        quota_project_id=None,
+        credentials_file=None,
+        scopes=None,
     ):
         if client_cert_source and client_encrypted_cert_source:
             raise ValueError(
@@ -81,6 +89,9 @@ class ClientOptions(object):
         self.api_endpoint = api_endpoint
         self.client_cert_source = client_cert_source
         self.client_encrypted_cert_source = client_encrypted_cert_source
+        self.quota_project_id = quota_project_id
+        self.credentials_file = credentials_file
+        self.scopes = scopes
 
     def __repr__(self):
         return "ClientOptions: " + repr(self.__dict__)
@@ -90,7 +101,8 @@ def from_dict(options):
     """Construct a client options object from a dictionary.
 
     Args:
-        options (dict): A dictionary with client options.
+        options (Dict[str, Any]): A dictionary with client options.
+            See the docstring for ClientOptions for details on valid arguments.
     """
 
     client_options = ClientOptions()


Test patch:
diff --git a/tests/unit/test_client_options.py b/tests/unit/test_client_options.py
index 67c4f6b..1581c56 100644
--- a/tests/unit/test_client_options.py
+++ b/tests/unit/test_client_options.py
@@ -28,11 +28,24 @@ def get_client_encrypted_cert():
 def test_constructor():
 
     options = client_options.ClientOptions(
-        api_endpoint="foo.googleapis.com", client_cert_source=get_client_cert
+        api_endpoint="foo.googleapis.com",
+        client_cert_source=get_client_cert,
+        quota_project_id="quote-proj",
+        credentials_file="path/to/credentials.json",
+        scopes=[
+            "https://www.googleapis.com/auth/cloud-platform",
+            "https://www.googleapis.com/auth/cloud-platform.read-only",
+        ]
     )
 
     assert options.api_endpoint == "foo.googleapis.com"
     assert options.client_cert_source() == (b"cert", b"key")
+    assert options.quota_project_id == "quote-proj"
+    assert options.credentials_file == "path/to/credentials.json"
+    assert options.scopes == [
+        "https://www.googleapis.com/auth/cloud-platform",
+        "https://www.googleapis.com/auth/cloud-platform.read-only",
+    ]
 
 
 def test_constructor_with_encrypted_cert_source():
@@ -61,12 +74,26 @@ def test_constructor_with_both_cert_sources():
 
 def test_from_dict():
     options = client_options.from_dict(
-        {"api_endpoint": "foo.googleapis.com", "client_cert_source": get_client_cert}
+        {
+            "api_endpoint": "foo.googleapis.com",
+            "client_cert_source": get_client_cert,
+            "quota_project_id": "quote-proj",
+            "credentials_file": "path/to/credentials.json",
+            "scopes": [
+                "https://www.googleapis.com/auth/cloud-platform",
+                "https://www.googleapis.com/auth/cloud-platform.read-only",
+            ]
+        }
     )
 
     assert options.api_endpoint == "foo.googleapis.com"
-    # assert options.client_cert_source == get_client_cert
     assert options.client_cert_source() == (b"cert", b"key")
+    assert options.quota_project_id == "quote-proj"
+    assert options.credentials_file == "path/to/credentials.json"
+    assert options.scopes == [
+        "https://www.googleapis.com/auth/cloud-platform",
+        "https://www.googleapis.com/auth/cloud-platform.read-only",
+    ]
 
 
 def test_from_dict_bad_argument():