From 52b1a0af0103a5b91aa5bf9ea1138319bdb90d79 Mon Sep 17 00:00:00 2001 From: Astha Mohta <35952883+asthamohta@users.noreply.github.com> Date: Tue, 28 Mar 2023 23:55:15 +0530 Subject: [PATCH 1/2] feat: pass custom Client object to dbapi (#911) --- google/cloud/spanner_dbapi/connection.py | 33 +++++++++------ tests/unit/spanner_dbapi/test_connection.py | 46 +++++++++++++++++++++ 2 files changed, 66 insertions(+), 13 deletions(-) diff --git a/google/cloud/spanner_dbapi/connection.py b/google/cloud/spanner_dbapi/connection.py index a1d46d3efe..d251e0f62a 100644 --- a/google/cloud/spanner_dbapi/connection.py +++ b/google/cloud/spanner_dbapi/connection.py @@ -497,6 +497,7 @@ def connect( credentials=None, pool=None, user_agent=None, + client=None, ): """Creates a connection to a Google Cloud Spanner database. @@ -529,25 +530,31 @@ def connect( :param user_agent: (Optional) User agent to be used with this connection's requests. + :type client: Concrete subclass of + :class:`~google.cloud.spanner_v1.Client`. + :param client: (Optional) Custom user provided Client Object + :rtype: :class:`google.cloud.spanner_dbapi.connection.Connection` :returns: Connection object associated with the given Google Cloud Spanner resource. """ - - client_info = ClientInfo( - user_agent=user_agent or DEFAULT_USER_AGENT, - python_version=PY_VERSION, - client_library_version=spanner.__version__, - ) - - if isinstance(credentials, str): - client = spanner.Client.from_service_account_json( - credentials, project=project, client_info=client_info + if client is None: + client_info = ClientInfo( + user_agent=user_agent or DEFAULT_USER_AGENT, + python_version=PY_VERSION, + client_library_version=spanner.__version__, ) + if isinstance(credentials, str): + client = spanner.Client.from_service_account_json( + credentials, project=project, client_info=client_info + ) + else: + client = spanner.Client( + project=project, credentials=credentials, client_info=client_info + ) else: - client = spanner.Client( - project=project, credentials=credentials, client_info=client_info - ) + if project is not None and client.project != project: + raise ValueError("project in url does not match client object project") instance = client.instance(instance_id) conn = Connection(instance, instance.database(database_id, pool=pool)) diff --git a/tests/unit/spanner_dbapi/test_connection.py b/tests/unit/spanner_dbapi/test_connection.py index 090def3519..b077c1feba 100644 --- a/tests/unit/spanner_dbapi/test_connection.py +++ b/tests/unit/spanner_dbapi/test_connection.py @@ -18,6 +18,7 @@ import mock import unittest import warnings +import pytest PROJECT = "test-project" INSTANCE = "test-instance" @@ -915,7 +916,52 @@ def test_request_priority(self): sql, params, param_types=param_types, request_options=None ) + @mock.patch("google.cloud.spanner_v1.Client") + def test_custom_client_connection(self, mock_client): + from google.cloud.spanner_dbapi import connect + + client = _Client() + connection = connect("test-instance", "test-database", client=client) + self.assertTrue(connection.instance._client == client) + + @mock.patch("google.cloud.spanner_v1.Client") + def test_invalid_custom_client_connection(self, mock_client): + from google.cloud.spanner_dbapi import connect + + client = _Client() + with pytest.raises(ValueError): + connect( + "test-instance", + "test-database", + project="invalid_project", + client=client, + ) + def exit_ctx_func(self, exc_type, exc_value, traceback): """Context __exit__ method mock.""" pass + + +class _Client(object): + def __init__(self, project="project_id"): + self.project = project + self.project_name = "projects/" + self.project + + def instance(self, instance_id="instance_id"): + return _Instance(name=instance_id, client=self) + + +class _Instance(object): + def __init__(self, name="instance_id", client=None): + self.name = name + self._client = client + + def database(self, database_id="database_id", pool=None): + return _Database(database_id, pool) + + +class _Database(object): + def __init__(self, database_id="database_id", pool=None): + self.name = database_id + self.pool = pool From 1f4a3ca3ab10941bc4ea23a482c5aaf9fa2c6b4f Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Mon, 3 Apr 2023 12:47:13 +0530 Subject: [PATCH 2/2] chore(main): release 3.30.0 (#922) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- .release-please-manifest.json | 2 +- CHANGELOG.md | 7 +++++++ google/cloud/spanner_admin_database_v1/gapic_version.py | 2 +- google/cloud/spanner_admin_instance_v1/gapic_version.py | 2 +- google/cloud/spanner_v1/gapic_version.py | 2 +- .../snippet_metadata_google.spanner.admin.database.v1.json | 2 +- .../snippet_metadata_google.spanner.admin.instance.v1.json | 2 +- .../snippet_metadata_google.spanner.v1.json | 2 +- 8 files changed, 14 insertions(+), 7 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 76a2556c17..41e3bcbc9a 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "3.29.0" + ".": "3.30.0" } diff --git a/CHANGELOG.md b/CHANGELOG.md index 5fac18fe0a..5c2d2cebf4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,13 @@ [1]: https://pypi.org/project/google-cloud-spanner/#history +## [3.30.0](https://github.com/googleapis/python-spanner/compare/v3.29.0...v3.30.0) (2023-03-28) + + +### Features + +* Pass custom Client object to dbapi ([#911](https://github.com/googleapis/python-spanner/issues/911)) ([52b1a0a](https://github.com/googleapis/python-spanner/commit/52b1a0af0103a5b91aa5bf9ea1138319bdb90d79)) + ## [3.29.0](https://github.com/googleapis/python-spanner/compare/v3.28.0...v3.29.0) (2023-03-23) diff --git a/google/cloud/spanner_admin_database_v1/gapic_version.py b/google/cloud/spanner_admin_database_v1/gapic_version.py index 16c2618143..f13e09ad48 100644 --- a/google/cloud/spanner_admin_database_v1/gapic_version.py +++ b/google/cloud/spanner_admin_database_v1/gapic_version.py @@ -13,4 +13,4 @@ # See the License for the specific language governing permissions and # limitations under the License. # -__version__ = "3.29.0" # {x-release-please-version} +__version__ = "3.30.0" # {x-release-please-version} diff --git a/google/cloud/spanner_admin_instance_v1/gapic_version.py b/google/cloud/spanner_admin_instance_v1/gapic_version.py index 16c2618143..f13e09ad48 100644 --- a/google/cloud/spanner_admin_instance_v1/gapic_version.py +++ b/google/cloud/spanner_admin_instance_v1/gapic_version.py @@ -13,4 +13,4 @@ # See the License for the specific language governing permissions and # limitations under the License. # -__version__ = "3.29.0" # {x-release-please-version} +__version__ = "3.30.0" # {x-release-please-version} diff --git a/google/cloud/spanner_v1/gapic_version.py b/google/cloud/spanner_v1/gapic_version.py index 16c2618143..f13e09ad48 100644 --- a/google/cloud/spanner_v1/gapic_version.py +++ b/google/cloud/spanner_v1/gapic_version.py @@ -13,4 +13,4 @@ # See the License for the specific language governing permissions and # limitations under the License. # -__version__ = "3.29.0" # {x-release-please-version} +__version__ = "3.30.0" # {x-release-please-version} diff --git a/samples/generated_samples/snippet_metadata_google.spanner.admin.database.v1.json b/samples/generated_samples/snippet_metadata_google.spanner.admin.database.v1.json index d27129ac69..9af6b015b1 100644 --- a/samples/generated_samples/snippet_metadata_google.spanner.admin.database.v1.json +++ b/samples/generated_samples/snippet_metadata_google.spanner.admin.database.v1.json @@ -8,7 +8,7 @@ ], "language": "PYTHON", "name": "google-cloud-spanner-admin-database", - "version": "3.29.0" + "version": "3.30.0" }, "snippets": [ { diff --git a/samples/generated_samples/snippet_metadata_google.spanner.admin.instance.v1.json b/samples/generated_samples/snippet_metadata_google.spanner.admin.instance.v1.json index 91f4d1cdfc..fd268b75e7 100644 --- a/samples/generated_samples/snippet_metadata_google.spanner.admin.instance.v1.json +++ b/samples/generated_samples/snippet_metadata_google.spanner.admin.instance.v1.json @@ -8,7 +8,7 @@ ], "language": "PYTHON", "name": "google-cloud-spanner-admin-instance", - "version": "3.29.0" + "version": "3.30.0" }, "snippets": [ { diff --git a/samples/generated_samples/snippet_metadata_google.spanner.v1.json b/samples/generated_samples/snippet_metadata_google.spanner.v1.json index aa8600b373..09648fac70 100644 --- a/samples/generated_samples/snippet_metadata_google.spanner.v1.json +++ b/samples/generated_samples/snippet_metadata_google.spanner.v1.json @@ -8,7 +8,7 @@ ], "language": "PYTHON", "name": "google-cloud-spanner", - "version": "3.29.0" + "version": "3.30.0" }, "snippets": [ {