Skip to content

Commit 44e0104

Browse files
committed
test and refactoring
1 parent 300968a commit 44e0104

File tree

6 files changed

+83
-76
lines changed

6 files changed

+83
-76
lines changed

google/cloud/spanner_v1/client.py

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -462,10 +462,4 @@ def default_transaction_options(self, default_transaction_options):
462462
:param default_transaction_options: Client options used to set the default_transaction_options
463463
used for all Read Write Transactions.
464464
"""
465-
if default_transaction_options is not None and not isinstance(
466-
default_transaction_options, TransactionOptions
467-
):
468-
raise TypeError(
469-
"default_transaction_option must be a TransactionOptions instance"
470-
)
471465
self._default_transaction_options = default_transaction_options

google/cloud/spanner_v1/database.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -823,7 +823,12 @@ def batch(
823823
# Set isolation level
824824
if isolation_level is None:
825825
isolation_level = (
826-
self.default_transaction_options.isolation_level
826+
self.default_transaction_options.get(
827+
"isolation_level",
828+
TransactionOptions.IsolationLevel.ISOLATION_LEVEL_UNSPECIFIED,
829+
)
830+
if isinstance(self.default_transaction_options, dict)
831+
else self.default_transaction_options.isolation_level
827832
if isinstance(self.default_transaction_options, TransactionOptions)
828833
else TransactionOptions.IsolationLevel.ISOLATION_LEVEL_UNSPECIFIED
829834
)

google/cloud/spanner_v1/session.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -466,7 +466,12 @@ def run_in_transaction(self, func, *args, **kw):
466466

467467
if isolation_level is None:
468468
isolation_level = (
469-
self._database.default_transaction_options.isolation_level
469+
self._database.default_transaction_options.get(
470+
"isolation_level",
471+
TransactionOptions.IsolationLevel.ISOLATION_LEVEL_UNSPECIFIED,
472+
)
473+
if isinstance(self._database.default_transaction_options, dict)
474+
else self._database.default_transaction_options.isolation_level
470475
if isinstance(
471476
self._database.default_transaction_options, TransactionOptions
472477
)

tests/unit/test_batch.py

Lines changed: 15 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,20 @@
2121
StatusCode,
2222
enrich_with_otel_scope,
2323
)
24-
from google.cloud.spanner_v1 import RequestOptions
24+
from google.cloud.spanner_v1 import (
25+
RequestOptions,
26+
CommitResponse,
27+
TransactionOptions,
28+
Mutation,
29+
BatchWriteResponse,
30+
)
31+
from google.cloud._helpers import UTC, _datetime_to_pb_timestamp
32+
import datetime
33+
from google.api_core.exceptions import Aborted, Unknown
34+
from google.cloud.spanner_v1.batch import MutationGroups, _BatchBase, Batch
35+
from google.cloud.spanner_v1.keyset import KeySet
36+
from google.rpc.status_pb2 import Status
37+
2538

2639
TABLE_NAME = "citizens"
2740
COLUMNS = ["email", "first_name", "last_name", "age"]
@@ -57,8 +70,6 @@ def _make_one(self, *args, **kwargs):
5770

5871
class Test_BatchBase(_BaseTest):
5972
def _getTargetClass(self):
60-
from google.cloud.spanner_v1.batch import _BatchBase
61-
6273
return _BatchBase
6374

6475
def _compare_values(self, result, source):
@@ -83,8 +94,6 @@ def test__check_state_virtual(self):
8394
base._check_state()
8495

8596
def test_insert(self):
86-
from google.cloud.spanner_v1 import Mutation
87-
8897
session = _Session()
8998
base = self._make_one(session)
9099

@@ -100,8 +109,6 @@ def test_insert(self):
100109
self._compare_values(write.values, VALUES)
101110

102111
def test_update(self):
103-
from google.cloud.spanner_v1 import Mutation
104-
105112
session = _Session()
106113
base = self._make_one(session)
107114

@@ -117,8 +124,6 @@ def test_update(self):
117124
self._compare_values(write.values, VALUES)
118125

119126
def test_insert_or_update(self):
120-
from google.cloud.spanner_v1 import Mutation
121-
122127
session = _Session()
123128
base = self._make_one(session)
124129

@@ -134,8 +139,6 @@ def test_insert_or_update(self):
134139
self._compare_values(write.values, VALUES)
135140

136141
def test_replace(self):
137-
from google.cloud.spanner_v1 import Mutation
138-
139142
session = _Session()
140143
base = self._make_one(session)
141144

@@ -151,9 +154,6 @@ def test_replace(self):
151154
self._compare_values(write.values, VALUES)
152155

153156
def test_delete(self):
154-
from google.cloud.spanner_v1 import Mutation
155-
from google.cloud.spanner_v1.keyset import KeySet
156-
157157
keys = [[0], [1], [2]]
158158
keyset = KeySet(keys=keys)
159159
session = _Session()
@@ -176,8 +176,6 @@ def test_delete(self):
176176

177177
class TestBatch(_BaseTest, OpenTelemetryBase):
178178
def _getTargetClass(self):
179-
from google.cloud.spanner_v1.batch import Batch
180-
181179
return Batch
182180

183181
def test_ctor(self):
@@ -186,8 +184,6 @@ def test_ctor(self):
186184
self.assertIs(batch._session, session)
187185

188186
def test_commit_already_committed(self):
189-
from google.cloud.spanner_v1.keyset import KeySet
190-
191187
keys = [[0], [1], [2]]
192188
keyset = KeySet(keys=keys)
193189
database = _Database()
@@ -202,9 +198,6 @@ def test_commit_already_committed(self):
202198
self.assertNoSpans()
203199

204200
def test_commit_grpc_error(self):
205-
from google.api_core.exceptions import Unknown
206-
from google.cloud.spanner_v1.keyset import KeySet
207-
208201
keys = [[0], [1], [2]]
209202
keyset = KeySet(keys=keys)
210203
database = _Database()
@@ -223,12 +216,6 @@ def test_commit_grpc_error(self):
223216
)
224217

225218
def test_commit_ok(self):
226-
import datetime
227-
from google.cloud.spanner_v1 import CommitResponse
228-
from google.cloud.spanner_v1 import TransactionOptions
229-
from google.cloud._helpers import UTC
230-
from google.cloud._helpers import _datetime_to_pb_timestamp
231-
232219
now = datetime.datetime.utcnow().replace(tzinfo=UTC)
233220
now_pb = _datetime_to_pb_timestamp(now)
234221
response = CommitResponse(commit_timestamp=now_pb)
@@ -273,7 +260,6 @@ def test_commit_ok(self):
273260
def test_aborted_exception_on_commit_with_retries(self):
274261
# Test case to verify that an Aborted exception is raised when
275262
# batch.commit() is called and the transaction is aborted internally.
276-
from google.api_core.exceptions import Aborted
277263

278264
database = _Database()
279265
# Setup the spanner API which throws Aborted exception when calling commit API.
@@ -306,13 +292,8 @@ def _test_commit_with_options(
306292
request_options=None,
307293
max_commit_delay_in=None,
308294
exclude_txn_from_change_streams=False,
295+
isolation_level=None,
309296
):
310-
import datetime
311-
from google.cloud.spanner_v1 import CommitResponse
312-
from google.cloud.spanner_v1 import TransactionOptions
313-
from google.cloud._helpers import UTC
314-
from google.cloud._helpers import _datetime_to_pb_timestamp
315-
316297
now = datetime.datetime.utcnow().replace(tzinfo=UTC)
317298
now_pb = _datetime_to_pb_timestamp(now)
318299
response = CommitResponse(commit_timestamp=now_pb)
@@ -399,8 +380,6 @@ def test_commit_w_incorrect_tag_dictionary_error(self):
399380
self._test_commit_with_options(request_options=request_options)
400381

401382
def test_commit_w_max_commit_delay(self):
402-
import datetime
403-
404383
request_options = RequestOptions(
405384
request_tag="tag-1",
406385
)
@@ -418,9 +397,6 @@ def test_commit_w_exclude_txn_from_change_streams(self):
418397
)
419398

420399
def test_context_mgr_already_committed(self):
421-
import datetime
422-
from google.cloud._helpers import UTC
423-
424400
now = datetime.datetime.utcnow().replace(tzinfo=UTC)
425401
database = _Database()
426402
api = database.spanner_api = _FauxSpannerAPI()
@@ -435,12 +411,6 @@ def test_context_mgr_already_committed(self):
435411
self.assertEqual(api._committed, None)
436412

437413
def test_context_mgr_success(self):
438-
import datetime
439-
from google.cloud.spanner_v1 import CommitResponse
440-
from google.cloud.spanner_v1 import TransactionOptions
441-
from google.cloud._helpers import UTC
442-
from google.cloud._helpers import _datetime_to_pb_timestamp
443-
444414
now = datetime.datetime.utcnow().replace(tzinfo=UTC)
445415
now_pb = _datetime_to_pb_timestamp(now)
446416
response = CommitResponse(commit_timestamp=now_pb)
@@ -481,11 +451,6 @@ def test_context_mgr_success(self):
481451
)
482452

483453
def test_context_mgr_failure(self):
484-
import datetime
485-
from google.cloud.spanner_v1 import CommitResponse
486-
from google.cloud._helpers import UTC
487-
from google.cloud._helpers import _datetime_to_pb_timestamp
488-
489454
now = datetime.datetime.utcnow().replace(tzinfo=UTC)
490455
now_pb = _datetime_to_pb_timestamp(now)
491456
response = CommitResponse(commit_timestamp=now_pb)
@@ -509,8 +474,6 @@ class _BailOut(Exception):
509474

510475
class TestMutationGroups(_BaseTest, OpenTelemetryBase):
511476
def _getTargetClass(self):
512-
from google.cloud.spanner_v1.batch import MutationGroups
513-
514477
return MutationGroups
515478

516479
def test_ctor(self):
@@ -519,8 +482,6 @@ def test_ctor(self):
519482
self.assertIs(groups._session, session)
520483

521484
def test_batch_write_already_committed(self):
522-
from google.cloud.spanner_v1.keyset import KeySet
523-
524485
keys = [[0], [1], [2]]
525486
keyset = KeySet(keys=keys)
526487
database = _Database()
@@ -541,9 +502,6 @@ def test_batch_write_already_committed(self):
541502
groups.batch_write()
542503

543504
def test_batch_write_grpc_error(self):
544-
from google.api_core.exceptions import Unknown
545-
from google.cloud.spanner_v1.keyset import KeySet
546-
547505
keys = [[0], [1], [2]]
548506
keyset = KeySet(keys=keys)
549507
database = _Database()
@@ -565,12 +523,6 @@ def test_batch_write_grpc_error(self):
565523
def _test_batch_write_with_request_options(
566524
self, request_options=None, exclude_txn_from_change_streams=False
567525
):
568-
import datetime
569-
from google.cloud.spanner_v1 import BatchWriteResponse
570-
from google.cloud._helpers import UTC
571-
from google.cloud._helpers import _datetime_to_pb_timestamp
572-
from google.rpc.status_pb2 import Status
573-
574526
now = datetime.datetime.utcnow().replace(tzinfo=UTC)
575527
now_pb = _datetime_to_pb_timestamp(now)
576528
status_pb = Status(code=200)
@@ -676,9 +628,6 @@ def commit(
676628
request=None,
677629
metadata=None,
678630
):
679-
from google.api_core.exceptions import Unknown
680-
from google.api_core.exceptions import Aborted
681-
682631
max_commit_delay = None
683632
if type(request).pb(request).HasField("max_commit_delay"):
684633
max_commit_delay = request.max_commit_delay
@@ -703,8 +652,6 @@ def batch_write(
703652
request=None,
704653
metadata=None,
705654
):
706-
from google.api_core.exceptions import Unknown
707-
708655
self._batch_request = (
709656
request.session,
710657
request.mutation_groups,

tests/unit/test_client.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ class TestClient(unittest.TestCase):
5252
"auto_failover_disabled": True,
5353
},
5454
}
55+
DEFAULT_TRANSACTION_OPTIONS = {"isolation_level": "SERIALIZABLE"}
5556

5657
def _get_target_class(self):
5758
from google.cloud import spanner
@@ -72,6 +73,7 @@ def _constructor_test_helper(
7273
expected_query_options=None,
7374
route_to_leader_enabled=True,
7475
directed_read_options=None,
76+
default_transaction_options=None,
7577
):
7678
import google.api_core.client_options
7779
from google.cloud.spanner_v1 import client as MUT
@@ -98,6 +100,7 @@ def _constructor_test_helper(
98100
credentials=creds,
99101
query_options=query_options,
100102
directed_read_options=directed_read_options,
103+
default_transaction_options=default_transaction_options,
101104
**kwargs
102105
)
103106

@@ -128,6 +131,10 @@ def _constructor_test_helper(
128131
self.assertFalse(client.route_to_leader_enabled)
129132
if directed_read_options is not None:
130133
self.assertEqual(client.directed_read_options, directed_read_options)
134+
if default_transaction_options is not None:
135+
self.assertEqual(
136+
client.default_transaction_options, default_transaction_options
137+
)
131138

132139
@mock.patch("google.cloud.spanner_v1.client._get_spanner_emulator_host")
133140
@mock.patch("warnings.warn")
@@ -259,6 +266,17 @@ def test_constructor_route_to_leader_disbled(self):
259266
expected_scopes, creds, route_to_leader_enabled=False
260267
)
261268

269+
def test_constructor_w_default_transaction_options(self):
270+
from google.cloud.spanner_v1 import client as MUT
271+
272+
expected_scopes = (MUT.SPANNER_ADMIN_SCOPE,)
273+
creds = _make_credentials()
274+
self._constructor_test_helper(
275+
expected_scopes,
276+
creds,
277+
default_transaction_options=self.DEFAULT_TRANSACTION_OPTIONS,
278+
)
279+
262280
@mock.patch("google.cloud.spanner_v1.client._get_spanner_emulator_host")
263281
def test_instance_admin_api(self, mock_em):
264282
from google.cloud.spanner_v1.client import SPANNER_ADMIN_SCOPE

tests/unit/test_session.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1915,6 +1915,44 @@ def unit_of_work(txn, *args, **kw):
19151915
* 2,
19161916
)
19171917

1918+
def test_run_in_transaction_w_isolation_level(self):
1919+
from google.cloud.spanner_v1 import (
1920+
Transaction as TransactionPB,
1921+
TransactionOptions,
1922+
)
1923+
from google.cloud.spanner_v1.transaction import Transaction
1924+
1925+
gax_api = self._make_spanner_api()
1926+
gax_api.begin_transaction.return_value = TransactionPB(id=b"FACEDACE")
1927+
database = self._make_database()
1928+
database.spanner_api = gax_api
1929+
session = self._make_one(database)
1930+
session._session_id = self.SESSION_ID
1931+
1932+
def unit_of_work(txn, *args, **kw):
1933+
txn.insert("test", [], [])
1934+
return 42
1935+
1936+
return_value = session.run_in_transaction(
1937+
unit_of_work, "abc", isolation_level="SERIALIZABLE"
1938+
)
1939+
1940+
self.assertIsNone(session._transaction)
1941+
self.assertEqual(return_value, 42)
1942+
1943+
expected_options = TransactionOptions(
1944+
read_write=TransactionOptions.ReadWrite(),
1945+
isolation_level="SERIALIZABLE",
1946+
)
1947+
gax_api.begin_transaction.assert_called_once_with(
1948+
session=self.SESSION_NAME,
1949+
options=expected_options,
1950+
metadata=[
1951+
("google-cloud-resource-prefix", database.name),
1952+
("x-goog-spanner-route-to-leader", "true"),
1953+
],
1954+
)
1955+
19181956
def test_delay_helper_w_no_delay(self):
19191957
from google.cloud.spanner_v1._helpers import _delay_until_retry
19201958

0 commit comments

Comments
 (0)