4343from google .cloud .spanner_admin_database_v1 import CreateDatabaseRequest
4444from google .cloud .spanner_admin_database_v1 import Database as DatabasePB
4545from google .cloud .spanner_admin_database_v1 .types import DatabaseDialect
46- from google .cloud .spanner_v1 .transaction import DefaultTransactionOptions
47- from google .cloud .spanner_v1 .types .spanner import ExecuteSqlRequest
48- from google .cloud .spanner_v1 .types .spanner import RequestOptions
49- from google .cloud .spanner_v1 .types .transaction import TransactionOptions
50- from google .cloud .spanner_v1 .types .transaction import TransactionSelector
51- from google .cloud .spanner_v1 .types .type import Type
52- from google .cloud .spanner_v1 .types .type import TypeCode
5346from google .cloud .spanner_v1 ._async .batch import Batch , MutationGroups
5447from google .cloud .spanner_v1 ._async .database_sessions_manager import (
5548 DatabaseSessionsManager ,
7265from google .cloud .spanner_v1 .services .spanner .async_client import (
7366 SpannerAsyncClient as SpannerClient ,
7467)
75- from google .cloud .spanner_v1 .transaction import BatchTransactionId
68+ from google .cloud .spanner_v1 .transaction import (
69+ BatchTransactionId ,
70+ DefaultTransactionOptions ,
71+ )
72+ from google .cloud .spanner_v1 .types .spanner import ExecuteSqlRequest , RequestOptions
73+ from google .cloud .spanner_v1 .types .transaction import (
74+ TransactionOptions ,
75+ TransactionSelector ,
76+ )
77+ from google .cloud .spanner_v1 .types .type import Type , TypeCode
7678
7779if CrossSync .is_async :
7880 from google .cloud .spanner_v1 .services .spanner .transports .grpc_asyncio import (
@@ -198,13 +200,22 @@ def __init__(
198200 self ._encryption_config = encryption_config
199201 self ._database_dialect = database_dialect
200202 self ._database_role = database_role
201- self ._route_to_leader_enabled = self ._instance ._client .route_to_leader_enabled
203+ if self ._instance and self ._instance ._client :
204+ self ._route_to_leader_enabled = (
205+ self ._instance ._client .route_to_leader_enabled
206+ )
207+ else :
208+ self ._route_to_leader_enabled = False
202209 self ._enable_drop_protection = enable_drop_protection
203210 self ._reconciling = False
204- self ._directed_read_options = self ._instance ._client .directed_read_options
205- self .default_transaction_options : DefaultTransactionOptions = (
206- self ._instance ._client .default_transaction_options
207- )
211+ if self ._instance and self ._instance ._client :
212+ self ._directed_read_options = self ._instance ._client .directed_read_options
213+ self .default_transaction_options : DefaultTransactionOptions = (
214+ self ._instance ._client .default_transaction_options
215+ )
216+ else :
217+ self ._directed_read_options = None
218+ self .default_transaction_options = None
208219 self ._proto_descriptors = proto_descriptors
209220 self ._channel_id = 0 # It'll be created when _spanner_api is created.
210221
@@ -220,7 +231,9 @@ def __init__(
220231 except RuntimeError :
221232 # No running loop, bind should have been sync or will be failed later
222233 pass
223- is_experimental_host = self ._instance .experimental_host is not None
234+ is_experimental_host = (
235+ self ._instance .experimental_host is not None if self ._instance else False
236+ )
224237
225238 self ._sessions_manager = DatabaseSessionsManager (
226239 self , pool , is_experimental_host
@@ -230,8 +243,12 @@ def __init__(
230243 def _resource_info (self ):
231244 """Resource information for metrics labels."""
232245 return {
233- "project" : self ._instance ._client .project ,
234- "instance" : self ._instance .instance_id ,
246+ "project" : (
247+ self ._instance ._client .project
248+ if self ._instance and self ._instance ._client
249+ else None
250+ ),
251+ "instance" : self ._instance .instance_id if self ._instance else None ,
235252 "database" : self .database_id ,
236253 }
237254
@@ -1365,7 +1382,8 @@ async def list_tables(self, schema="_default"):
13651382 async for row in results :
13661383 yield self .table (row [0 ])
13671384
1368- def get_iam_policy (self , policy_version = None ):
1385+ @CrossSync .convert
1386+ async def get_iam_policy (self , policy_version = None ):
13691387 """Gets the access control policy for a database resource.
13701388
13711389 :type policy_version: int
@@ -1388,13 +1406,14 @@ def get_iam_policy(self, policy_version=None):
13881406 requested_policy_version = policy_version
13891407 ),
13901408 )
1391- response = api .get_iam_policy (
1409+ response = await api .get_iam_policy (
13921410 request = request ,
13931411 metadata = self .metadata_with_request_id (self ._next_nth_request , 1 , metadata ),
13941412 )
13951413 return response
13961414
1397- def set_iam_policy (self , policy ):
1415+ @CrossSync .convert
1416+ async def set_iam_policy (self , policy ):
13981417 """Sets the access control policy on a database resource.
13991418 Replaces any existing policy.
14001419
@@ -1413,7 +1432,7 @@ def set_iam_policy(self, policy):
14131432 resource = self .name ,
14141433 policy = policy ,
14151434 )
1416- response = api .set_iam_policy (
1435+ response = await api .set_iam_policy (
14171436 request = request ,
14181437 metadata = self .metadata_with_request_id (self ._next_nth_request , 1 , metadata ),
14191438 )
@@ -1444,6 +1463,11 @@ def sessions_manager(self) -> DatabaseSessionsManager:
14441463 """
14451464 return self ._sessions_manager
14461465
1466+ @CrossSync .convert
1467+ async def close (self ):
1468+ """Clean up underlying session manager and background tasks."""
1469+ await self ._sessions_manager .close ()
1470+
14471471
14481472class BatchCheckout (object ):
14491473 """Context manager for using a batch from a database.
0 commit comments