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- self ._experimental_host = self ._instance ._client ._experimental_host
234+ self ._experimental_host = (
235+ self ._instance .experimental_host if self ._instance else None
236+ )
224237 is_experimental_host = self ._experimental_host is not None
225238
226239 self ._sessions_manager = DatabaseSessionsManager (
@@ -231,8 +244,12 @@ def __init__(
231244 def _resource_info (self ):
232245 """Resource information for metrics labels."""
233246 return {
234- "project" : self ._instance ._client .project ,
235- "instance" : self ._instance .instance_id ,
247+ "project" : (
248+ self ._instance ._client .project
249+ if self ._instance and self ._instance ._client
250+ else None
251+ ),
252+ "instance" : self ._instance .instance_id if self ._instance else None ,
236253 "database" : self .database_id ,
237254 }
238255
@@ -1351,7 +1368,8 @@ async def list_tables(self, schema="_default"):
13511368 async for row in results :
13521369 yield self .table (row [0 ])
13531370
1354- def get_iam_policy (self , policy_version = None ):
1371+ @CrossSync .convert
1372+ async def get_iam_policy (self , policy_version = None ):
13551373 """Gets the access control policy for a database resource.
13561374
13571375 :type policy_version: int
@@ -1374,13 +1392,14 @@ def get_iam_policy(self, policy_version=None):
13741392 requested_policy_version = policy_version
13751393 ),
13761394 )
1377- response = api .get_iam_policy (
1395+ response = await api .get_iam_policy (
13781396 request = request ,
13791397 metadata = self .metadata_with_request_id (self ._next_nth_request , 1 , metadata ),
13801398 )
13811399 return response
13821400
1383- def set_iam_policy (self , policy ):
1401+ @CrossSync .convert
1402+ async def set_iam_policy (self , policy ):
13841403 """Sets the access control policy on a database resource.
13851404 Replaces any existing policy.
13861405
@@ -1399,7 +1418,7 @@ def set_iam_policy(self, policy):
13991418 resource = self .name ,
14001419 policy = policy ,
14011420 )
1402- response = api .set_iam_policy (
1421+ response = await api .set_iam_policy (
14031422 request = request ,
14041423 metadata = self .metadata_with_request_id (self ._next_nth_request , 1 , metadata ),
14051424 )
@@ -1430,6 +1449,11 @@ def sessions_manager(self) -> DatabaseSessionsManager:
14301449 """
14311450 return self ._sessions_manager
14321451
1452+ @CrossSync .convert
1453+ async def close (self ):
1454+ """Clean up underlying session manager and background tasks."""
1455+ await self ._sessions_manager .close ()
1456+
14331457
14341458class BatchCheckout (object ):
14351459 """Context manager for using a batch from a database.
0 commit comments