1# -*- coding: utf-8 -*-
2# Copyright 2025 Google LLC
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15#
16import json
17import logging as std_logging
18import pickle
19import warnings
20from typing import Callable, Dict, Optional, Sequence, Tuple, Union
21
22from google.api_core import grpc_helpers
23from google.api_core import gapic_v1
24import google.auth # type: ignore
25from google.auth import credentials as ga_credentials # type: ignore
26from google.auth.transport.grpc import SslCredentials # type: ignore
27from google.protobuf.json_format import MessageToJson
28import google.protobuf.message
29
30import grpc # type: ignore
31import proto # type: ignore
32
33from google.cloud.firestore_v1.types import document
34from google.cloud.firestore_v1.types import document as gf_document
35from google.cloud.firestore_v1.types import firestore
36from google.cloud.location import locations_pb2 # type: ignore
37from google.longrunning import operations_pb2 # type: ignore
38from google.protobuf import empty_pb2 # type: ignore
39from .base import FirestoreTransport, DEFAULT_CLIENT_INFO
40
41try:
42 from google.api_core import client_logging # type: ignore
43
44 CLIENT_LOGGING_SUPPORTED = True # pragma: NO COVER
45except ImportError: # pragma: NO COVER
46 CLIENT_LOGGING_SUPPORTED = False
47
48_LOGGER = std_logging.getLogger(__name__)
49
50
51class _LoggingClientInterceptor(grpc.UnaryUnaryClientInterceptor): # pragma: NO COVER
52 def intercept_unary_unary(self, continuation, client_call_details, request):
53 logging_enabled = CLIENT_LOGGING_SUPPORTED and _LOGGER.isEnabledFor(
54 std_logging.DEBUG
55 )
56 if logging_enabled: # pragma: NO COVER
57 request_metadata = client_call_details.metadata
58 if isinstance(request, proto.Message):
59 request_payload = type(request).to_json(request)
60 elif isinstance(request, google.protobuf.message.Message):
61 request_payload = MessageToJson(request)
62 else:
63 request_payload = f"{type(request).__name__}: {pickle.dumps(request)}"
64
65 request_metadata = {
66 key: value.decode("utf-8") if isinstance(value, bytes) else value
67 for key, value in request_metadata
68 }
69 grpc_request = {
70 "payload": request_payload,
71 "requestMethod": "grpc",
72 "metadata": dict(request_metadata),
73 }
74 _LOGGER.debug(
75 f"Sending request for {client_call_details.method}",
76 extra={
77 "serviceName": "google.firestore.v1.Firestore",
78 "rpcName": str(client_call_details.method),
79 "request": grpc_request,
80 "metadata": grpc_request["metadata"],
81 },
82 )
83 response = continuation(client_call_details, request)
84 if logging_enabled: # pragma: NO COVER
85 response_metadata = response.trailing_metadata()
86 # Convert gRPC metadata `<class 'grpc.aio._metadata.Metadata'>` to list of tuples
87 metadata = (
88 dict([(k, str(v)) for k, v in response_metadata])
89 if response_metadata
90 else None
91 )
92 result = response.result()
93 if isinstance(result, proto.Message):
94 response_payload = type(result).to_json(result)
95 elif isinstance(result, google.protobuf.message.Message):
96 response_payload = MessageToJson(result)
97 else:
98 response_payload = f"{type(result).__name__}: {pickle.dumps(result)}"
99 grpc_response = {
100 "payload": response_payload,
101 "metadata": metadata,
102 "status": "OK",
103 }
104 _LOGGER.debug(
105 f"Received response for {client_call_details.method}.",
106 extra={
107 "serviceName": "google.firestore.v1.Firestore",
108 "rpcName": client_call_details.method,
109 "response": grpc_response,
110 "metadata": grpc_response["metadata"],
111 },
112 )
113 return response
114
115
116class FirestoreGrpcTransport(FirestoreTransport):
117 """gRPC backend transport for Firestore.
118
119 The Cloud Firestore service.
120
121 Cloud Firestore is a fast, fully managed, serverless,
122 cloud-native NoSQL document database that simplifies storing,
123 syncing, and querying data for your mobile, web, and IoT apps at
124 global scale. Its client libraries provide live synchronization
125 and offline support, while its security features and
126 integrations with Firebase and Google Cloud Platform accelerate
127 building truly serverless apps.
128
129 This class defines the same methods as the primary client, so the
130 primary client can load the underlying transport implementation
131 and call it.
132
133 It sends protocol buffers over the wire using gRPC (which is built on
134 top of HTTP/2); the ``grpcio`` package must be installed.
135 """
136
137 _stubs: Dict[str, Callable]
138
139 def __init__(
140 self,
141 *,
142 host: str = "firestore.googleapis.com",
143 credentials: Optional[ga_credentials.Credentials] = None,
144 credentials_file: Optional[str] = None,
145 scopes: Optional[Sequence[str]] = None,
146 channel: Optional[Union[grpc.Channel, Callable[..., grpc.Channel]]] = None,
147 api_mtls_endpoint: Optional[str] = None,
148 client_cert_source: Optional[Callable[[], Tuple[bytes, bytes]]] = None,
149 ssl_channel_credentials: Optional[grpc.ChannelCredentials] = None,
150 client_cert_source_for_mtls: Optional[Callable[[], Tuple[bytes, bytes]]] = None,
151 quota_project_id: Optional[str] = None,
152 client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO,
153 always_use_jwt_access: Optional[bool] = False,
154 api_audience: Optional[str] = None,
155 ) -> None:
156 """Instantiate the transport.
157
158 Args:
159 host (Optional[str]):
160 The hostname to connect to (default: 'firestore.googleapis.com').
161 credentials (Optional[google.auth.credentials.Credentials]): The
162 authorization credentials to attach to requests. These
163 credentials identify the application to the service; if none
164 are specified, the client will attempt to ascertain the
165 credentials from the environment.
166 This argument is ignored if a ``channel`` instance is provided.
167 credentials_file (Optional[str]): Deprecated. A file with credentials that can
168 be loaded with :func:`google.auth.load_credentials_from_file`.
169 This argument is ignored if a ``channel`` instance is provided.
170 This argument will be removed in the next major version of this library.
171 scopes (Optional(Sequence[str])): A list of scopes. This argument is
172 ignored if a ``channel`` instance is provided.
173 channel (Optional[Union[grpc.Channel, Callable[..., grpc.Channel]]]):
174 A ``Channel`` instance through which to make calls, or a Callable
175 that constructs and returns one. If set to None, ``self.create_channel``
176 is used to create the channel. If a Callable is given, it will be called
177 with the same arguments as used in ``self.create_channel``.
178 api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint.
179 If provided, it overrides the ``host`` argument and tries to create
180 a mutual TLS channel with client SSL credentials from
181 ``client_cert_source`` or application default SSL credentials.
182 client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]):
183 Deprecated. A callback to provide client SSL certificate bytes and
184 private key bytes, both in PEM format. It is ignored if
185 ``api_mtls_endpoint`` is None.
186 ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials
187 for the grpc channel. It is ignored if a ``channel`` instance is provided.
188 client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]):
189 A callback to provide client certificate bytes and private key bytes,
190 both in PEM format. It is used to configure a mutual TLS channel. It is
191 ignored if a ``channel`` instance or ``ssl_channel_credentials`` is provided.
192 quota_project_id (Optional[str]): An optional project to use for billing
193 and quota.
194 client_info (google.api_core.gapic_v1.client_info.ClientInfo):
195 The client info used to send a user-agent string along with
196 API requests. If ``None``, then default info will be used.
197 Generally, you only need to set this if you're developing
198 your own client library.
199 always_use_jwt_access (Optional[bool]): Whether self signed JWT should
200 be used for service account credentials.
201
202 Raises:
203 google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport
204 creation failed for any reason.
205 google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials``
206 and ``credentials_file`` are passed.
207 """
208 self._grpc_channel = None
209 self._ssl_channel_credentials = ssl_channel_credentials
210 self._stubs: Dict[str, Callable] = {}
211
212 if api_mtls_endpoint:
213 warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning)
214 if client_cert_source:
215 warnings.warn("client_cert_source is deprecated", DeprecationWarning)
216
217 if isinstance(channel, grpc.Channel):
218 # Ignore credentials if a channel was passed.
219 credentials = None
220 self._ignore_credentials = True
221 # If a channel was explicitly provided, set it.
222 self._grpc_channel = channel
223 self._ssl_channel_credentials = None
224
225 else:
226 if api_mtls_endpoint:
227 host = api_mtls_endpoint
228
229 # Create SSL credentials with client_cert_source or application
230 # default SSL credentials.
231 if client_cert_source:
232 cert, key = client_cert_source()
233 self._ssl_channel_credentials = grpc.ssl_channel_credentials(
234 certificate_chain=cert, private_key=key
235 )
236 else:
237 self._ssl_channel_credentials = SslCredentials().ssl_credentials
238
239 else:
240 if client_cert_source_for_mtls and not ssl_channel_credentials:
241 cert, key = client_cert_source_for_mtls()
242 self._ssl_channel_credentials = grpc.ssl_channel_credentials(
243 certificate_chain=cert, private_key=key
244 )
245
246 # The base transport sets the host, credentials and scopes
247 super().__init__(
248 host=host,
249 credentials=credentials,
250 credentials_file=credentials_file,
251 scopes=scopes,
252 quota_project_id=quota_project_id,
253 client_info=client_info,
254 always_use_jwt_access=always_use_jwt_access,
255 api_audience=api_audience,
256 )
257
258 if not self._grpc_channel:
259 # initialize with the provided callable or the default channel
260 channel_init = channel or type(self).create_channel
261 self._grpc_channel = channel_init(
262 self._host,
263 # use the credentials which are saved
264 credentials=self._credentials,
265 # Set ``credentials_file`` to ``None`` here as
266 # the credentials that we saved earlier should be used.
267 credentials_file=None,
268 scopes=self._scopes,
269 ssl_credentials=self._ssl_channel_credentials,
270 quota_project_id=quota_project_id,
271 options=[
272 ("grpc.max_send_message_length", -1),
273 ("grpc.max_receive_message_length", -1),
274 ],
275 )
276
277 self._interceptor = _LoggingClientInterceptor()
278 self._logged_channel = grpc.intercept_channel(
279 self._grpc_channel, self._interceptor
280 )
281
282 # Wrap messages. This must be done after self._logged_channel exists
283 self._prep_wrapped_messages(client_info)
284
285 @classmethod
286 def create_channel(
287 cls,
288 host: str = "firestore.googleapis.com",
289 credentials: Optional[ga_credentials.Credentials] = None,
290 credentials_file: Optional[str] = None,
291 scopes: Optional[Sequence[str]] = None,
292 quota_project_id: Optional[str] = None,
293 **kwargs,
294 ) -> grpc.Channel:
295 """Create and return a gRPC channel object.
296 Args:
297 host (Optional[str]): The host for the channel to use.
298 credentials (Optional[~.Credentials]): The
299 authorization credentials to attach to requests. These
300 credentials identify this application to the service. If
301 none are specified, the client will attempt to ascertain
302 the credentials from the environment.
303 credentials_file (Optional[str]): Deprecated. A file with credentials that can
304 be loaded with :func:`google.auth.load_credentials_from_file`.
305 This argument is mutually exclusive with credentials. This argument will be
306 removed in the next major version of this library.
307 scopes (Optional[Sequence[str]]): A optional list of scopes needed for this
308 service. These are only used when credentials are not specified and
309 are passed to :func:`google.auth.default`.
310 quota_project_id (Optional[str]): An optional project to use for billing
311 and quota.
312 kwargs (Optional[dict]): Keyword arguments, which are passed to the
313 channel creation.
314 Returns:
315 grpc.Channel: A gRPC channel object.
316
317 Raises:
318 google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials``
319 and ``credentials_file`` are passed.
320 """
321
322 return grpc_helpers.create_channel(
323 host,
324 credentials=credentials,
325 credentials_file=credentials_file,
326 quota_project_id=quota_project_id,
327 default_scopes=cls.AUTH_SCOPES,
328 scopes=scopes,
329 default_host=cls.DEFAULT_HOST,
330 **kwargs,
331 )
332
333 @property
334 def grpc_channel(self) -> grpc.Channel:
335 """Return the channel designed to connect to this service."""
336 return self._grpc_channel
337
338 @property
339 def get_document(
340 self,
341 ) -> Callable[[firestore.GetDocumentRequest], document.Document]:
342 r"""Return a callable for the get document method over gRPC.
343
344 Gets a single document.
345
346 Returns:
347 Callable[[~.GetDocumentRequest],
348 ~.Document]:
349 A function that, when called, will call the underlying RPC
350 on the server.
351 """
352 # Generate a "stub function" on-the-fly which will actually make
353 # the request.
354 # gRPC handles serialization and deserialization, so we just need
355 # to pass in the functions for each.
356 if "get_document" not in self._stubs:
357 self._stubs["get_document"] = self._logged_channel.unary_unary(
358 "/google.firestore.v1.Firestore/GetDocument",
359 request_serializer=firestore.GetDocumentRequest.serialize,
360 response_deserializer=document.Document.deserialize,
361 )
362 return self._stubs["get_document"]
363
364 @property
365 def list_documents(
366 self,
367 ) -> Callable[[firestore.ListDocumentsRequest], firestore.ListDocumentsResponse]:
368 r"""Return a callable for the list documents method over gRPC.
369
370 Lists documents.
371
372 Returns:
373 Callable[[~.ListDocumentsRequest],
374 ~.ListDocumentsResponse]:
375 A function that, when called, will call the underlying RPC
376 on the server.
377 """
378 # Generate a "stub function" on-the-fly which will actually make
379 # the request.
380 # gRPC handles serialization and deserialization, so we just need
381 # to pass in the functions for each.
382 if "list_documents" not in self._stubs:
383 self._stubs["list_documents"] = self._logged_channel.unary_unary(
384 "/google.firestore.v1.Firestore/ListDocuments",
385 request_serializer=firestore.ListDocumentsRequest.serialize,
386 response_deserializer=firestore.ListDocumentsResponse.deserialize,
387 )
388 return self._stubs["list_documents"]
389
390 @property
391 def update_document(
392 self,
393 ) -> Callable[[firestore.UpdateDocumentRequest], gf_document.Document]:
394 r"""Return a callable for the update document method over gRPC.
395
396 Updates or inserts a document.
397
398 Returns:
399 Callable[[~.UpdateDocumentRequest],
400 ~.Document]:
401 A function that, when called, will call the underlying RPC
402 on the server.
403 """
404 # Generate a "stub function" on-the-fly which will actually make
405 # the request.
406 # gRPC handles serialization and deserialization, so we just need
407 # to pass in the functions for each.
408 if "update_document" not in self._stubs:
409 self._stubs["update_document"] = self._logged_channel.unary_unary(
410 "/google.firestore.v1.Firestore/UpdateDocument",
411 request_serializer=firestore.UpdateDocumentRequest.serialize,
412 response_deserializer=gf_document.Document.deserialize,
413 )
414 return self._stubs["update_document"]
415
416 @property
417 def delete_document(
418 self,
419 ) -> Callable[[firestore.DeleteDocumentRequest], empty_pb2.Empty]:
420 r"""Return a callable for the delete document method over gRPC.
421
422 Deletes a document.
423
424 Returns:
425 Callable[[~.DeleteDocumentRequest],
426 ~.Empty]:
427 A function that, when called, will call the underlying RPC
428 on the server.
429 """
430 # Generate a "stub function" on-the-fly which will actually make
431 # the request.
432 # gRPC handles serialization and deserialization, so we just need
433 # to pass in the functions for each.
434 if "delete_document" not in self._stubs:
435 self._stubs["delete_document"] = self._logged_channel.unary_unary(
436 "/google.firestore.v1.Firestore/DeleteDocument",
437 request_serializer=firestore.DeleteDocumentRequest.serialize,
438 response_deserializer=empty_pb2.Empty.FromString,
439 )
440 return self._stubs["delete_document"]
441
442 @property
443 def batch_get_documents(
444 self,
445 ) -> Callable[
446 [firestore.BatchGetDocumentsRequest], firestore.BatchGetDocumentsResponse
447 ]:
448 r"""Return a callable for the batch get documents method over gRPC.
449
450 Gets multiple documents.
451
452 Documents returned by this method are not guaranteed to
453 be returned in the same order that they were requested.
454
455 Returns:
456 Callable[[~.BatchGetDocumentsRequest],
457 ~.BatchGetDocumentsResponse]:
458 A function that, when called, will call the underlying RPC
459 on the server.
460 """
461 # Generate a "stub function" on-the-fly which will actually make
462 # the request.
463 # gRPC handles serialization and deserialization, so we just need
464 # to pass in the functions for each.
465 if "batch_get_documents" not in self._stubs:
466 self._stubs["batch_get_documents"] = self._logged_channel.unary_stream(
467 "/google.firestore.v1.Firestore/BatchGetDocuments",
468 request_serializer=firestore.BatchGetDocumentsRequest.serialize,
469 response_deserializer=firestore.BatchGetDocumentsResponse.deserialize,
470 )
471 return self._stubs["batch_get_documents"]
472
473 @property
474 def begin_transaction(
475 self,
476 ) -> Callable[
477 [firestore.BeginTransactionRequest], firestore.BeginTransactionResponse
478 ]:
479 r"""Return a callable for the begin transaction method over gRPC.
480
481 Starts a new transaction.
482
483 Returns:
484 Callable[[~.BeginTransactionRequest],
485 ~.BeginTransactionResponse]:
486 A function that, when called, will call the underlying RPC
487 on the server.
488 """
489 # Generate a "stub function" on-the-fly which will actually make
490 # the request.
491 # gRPC handles serialization and deserialization, so we just need
492 # to pass in the functions for each.
493 if "begin_transaction" not in self._stubs:
494 self._stubs["begin_transaction"] = self._logged_channel.unary_unary(
495 "/google.firestore.v1.Firestore/BeginTransaction",
496 request_serializer=firestore.BeginTransactionRequest.serialize,
497 response_deserializer=firestore.BeginTransactionResponse.deserialize,
498 )
499 return self._stubs["begin_transaction"]
500
501 @property
502 def commit(self) -> Callable[[firestore.CommitRequest], firestore.CommitResponse]:
503 r"""Return a callable for the commit method over gRPC.
504
505 Commits a transaction, while optionally updating
506 documents.
507
508 Returns:
509 Callable[[~.CommitRequest],
510 ~.CommitResponse]:
511 A function that, when called, will call the underlying RPC
512 on the server.
513 """
514 # Generate a "stub function" on-the-fly which will actually make
515 # the request.
516 # gRPC handles serialization and deserialization, so we just need
517 # to pass in the functions for each.
518 if "commit" not in self._stubs:
519 self._stubs["commit"] = self._logged_channel.unary_unary(
520 "/google.firestore.v1.Firestore/Commit",
521 request_serializer=firestore.CommitRequest.serialize,
522 response_deserializer=firestore.CommitResponse.deserialize,
523 )
524 return self._stubs["commit"]
525
526 @property
527 def rollback(self) -> Callable[[firestore.RollbackRequest], empty_pb2.Empty]:
528 r"""Return a callable for the rollback method over gRPC.
529
530 Rolls back a transaction.
531
532 Returns:
533 Callable[[~.RollbackRequest],
534 ~.Empty]:
535 A function that, when called, will call the underlying RPC
536 on the server.
537 """
538 # Generate a "stub function" on-the-fly which will actually make
539 # the request.
540 # gRPC handles serialization and deserialization, so we just need
541 # to pass in the functions for each.
542 if "rollback" not in self._stubs:
543 self._stubs["rollback"] = self._logged_channel.unary_unary(
544 "/google.firestore.v1.Firestore/Rollback",
545 request_serializer=firestore.RollbackRequest.serialize,
546 response_deserializer=empty_pb2.Empty.FromString,
547 )
548 return self._stubs["rollback"]
549
550 @property
551 def run_query(
552 self,
553 ) -> Callable[[firestore.RunQueryRequest], firestore.RunQueryResponse]:
554 r"""Return a callable for the run query method over gRPC.
555
556 Runs a query.
557
558 Returns:
559 Callable[[~.RunQueryRequest],
560 ~.RunQueryResponse]:
561 A function that, when called, will call the underlying RPC
562 on the server.
563 """
564 # Generate a "stub function" on-the-fly which will actually make
565 # the request.
566 # gRPC handles serialization and deserialization, so we just need
567 # to pass in the functions for each.
568 if "run_query" not in self._stubs:
569 self._stubs["run_query"] = self._logged_channel.unary_stream(
570 "/google.firestore.v1.Firestore/RunQuery",
571 request_serializer=firestore.RunQueryRequest.serialize,
572 response_deserializer=firestore.RunQueryResponse.deserialize,
573 )
574 return self._stubs["run_query"]
575
576 @property
577 def execute_pipeline(
578 self,
579 ) -> Callable[
580 [firestore.ExecutePipelineRequest], firestore.ExecutePipelineResponse
581 ]:
582 r"""Return a callable for the execute pipeline method over gRPC.
583
584 Executes a pipeline query.
585
586 Returns:
587 Callable[[~.ExecutePipelineRequest],
588 ~.ExecutePipelineResponse]:
589 A function that, when called, will call the underlying RPC
590 on the server.
591 """
592 # Generate a "stub function" on-the-fly which will actually make
593 # the request.
594 # gRPC handles serialization and deserialization, so we just need
595 # to pass in the functions for each.
596 if "execute_pipeline" not in self._stubs:
597 self._stubs["execute_pipeline"] = self._logged_channel.unary_stream(
598 "/google.firestore.v1.Firestore/ExecutePipeline",
599 request_serializer=firestore.ExecutePipelineRequest.serialize,
600 response_deserializer=firestore.ExecutePipelineResponse.deserialize,
601 )
602 return self._stubs["execute_pipeline"]
603
604 @property
605 def run_aggregation_query(
606 self,
607 ) -> Callable[
608 [firestore.RunAggregationQueryRequest], firestore.RunAggregationQueryResponse
609 ]:
610 r"""Return a callable for the run aggregation query method over gRPC.
611
612 Runs an aggregation query.
613
614 Rather than producing [Document][google.firestore.v1.Document]
615 results like
616 [Firestore.RunQuery][google.firestore.v1.Firestore.RunQuery],
617 this API allows running an aggregation to produce a series of
618 [AggregationResult][google.firestore.v1.AggregationResult]
619 server-side.
620
621 High-Level Example:
622
623 ::
624
625 -- Return the number of documents in table given a filter.
626 SELECT COUNT(*) FROM ( SELECT * FROM k where a = true );
627
628 Returns:
629 Callable[[~.RunAggregationQueryRequest],
630 ~.RunAggregationQueryResponse]:
631 A function that, when called, will call the underlying RPC
632 on the server.
633 """
634 # Generate a "stub function" on-the-fly which will actually make
635 # the request.
636 # gRPC handles serialization and deserialization, so we just need
637 # to pass in the functions for each.
638 if "run_aggregation_query" not in self._stubs:
639 self._stubs["run_aggregation_query"] = self._logged_channel.unary_stream(
640 "/google.firestore.v1.Firestore/RunAggregationQuery",
641 request_serializer=firestore.RunAggregationQueryRequest.serialize,
642 response_deserializer=firestore.RunAggregationQueryResponse.deserialize,
643 )
644 return self._stubs["run_aggregation_query"]
645
646 @property
647 def partition_query(
648 self,
649 ) -> Callable[[firestore.PartitionQueryRequest], firestore.PartitionQueryResponse]:
650 r"""Return a callable for the partition query method over gRPC.
651
652 Partitions a query by returning partition cursors
653 that can be used to run the query in parallel. The
654 returned partition cursors are split points that can be
655 used by RunQuery as starting/end points for the query
656 results.
657
658 Returns:
659 Callable[[~.PartitionQueryRequest],
660 ~.PartitionQueryResponse]:
661 A function that, when called, will call the underlying RPC
662 on the server.
663 """
664 # Generate a "stub function" on-the-fly which will actually make
665 # the request.
666 # gRPC handles serialization and deserialization, so we just need
667 # to pass in the functions for each.
668 if "partition_query" not in self._stubs:
669 self._stubs["partition_query"] = self._logged_channel.unary_unary(
670 "/google.firestore.v1.Firestore/PartitionQuery",
671 request_serializer=firestore.PartitionQueryRequest.serialize,
672 response_deserializer=firestore.PartitionQueryResponse.deserialize,
673 )
674 return self._stubs["partition_query"]
675
676 @property
677 def write(self) -> Callable[[firestore.WriteRequest], firestore.WriteResponse]:
678 r"""Return a callable for the write method over gRPC.
679
680 Streams batches of document updates and deletes, in
681 order. This method is only available via gRPC or
682 WebChannel (not REST).
683
684 Returns:
685 Callable[[~.WriteRequest],
686 ~.WriteResponse]:
687 A function that, when called, will call the underlying RPC
688 on the server.
689 """
690 # Generate a "stub function" on-the-fly which will actually make
691 # the request.
692 # gRPC handles serialization and deserialization, so we just need
693 # to pass in the functions for each.
694 if "write" not in self._stubs:
695 self._stubs["write"] = self._logged_channel.stream_stream(
696 "/google.firestore.v1.Firestore/Write",
697 request_serializer=firestore.WriteRequest.serialize,
698 response_deserializer=firestore.WriteResponse.deserialize,
699 )
700 return self._stubs["write"]
701
702 @property
703 def listen(self) -> Callable[[firestore.ListenRequest], firestore.ListenResponse]:
704 r"""Return a callable for the listen method over gRPC.
705
706 Listens to changes. This method is only available via
707 gRPC or WebChannel (not REST).
708
709 Returns:
710 Callable[[~.ListenRequest],
711 ~.ListenResponse]:
712 A function that, when called, will call the underlying RPC
713 on the server.
714 """
715 # Generate a "stub function" on-the-fly which will actually make
716 # the request.
717 # gRPC handles serialization and deserialization, so we just need
718 # to pass in the functions for each.
719 if "listen" not in self._stubs:
720 self._stubs["listen"] = self._logged_channel.stream_stream(
721 "/google.firestore.v1.Firestore/Listen",
722 request_serializer=firestore.ListenRequest.serialize,
723 response_deserializer=firestore.ListenResponse.deserialize,
724 )
725 return self._stubs["listen"]
726
727 @property
728 def list_collection_ids(
729 self,
730 ) -> Callable[
731 [firestore.ListCollectionIdsRequest], firestore.ListCollectionIdsResponse
732 ]:
733 r"""Return a callable for the list collection ids method over gRPC.
734
735 Lists all the collection IDs underneath a document.
736
737 Returns:
738 Callable[[~.ListCollectionIdsRequest],
739 ~.ListCollectionIdsResponse]:
740 A function that, when called, will call the underlying RPC
741 on the server.
742 """
743 # Generate a "stub function" on-the-fly which will actually make
744 # the request.
745 # gRPC handles serialization and deserialization, so we just need
746 # to pass in the functions for each.
747 if "list_collection_ids" not in self._stubs:
748 self._stubs["list_collection_ids"] = self._logged_channel.unary_unary(
749 "/google.firestore.v1.Firestore/ListCollectionIds",
750 request_serializer=firestore.ListCollectionIdsRequest.serialize,
751 response_deserializer=firestore.ListCollectionIdsResponse.deserialize,
752 )
753 return self._stubs["list_collection_ids"]
754
755 @property
756 def batch_write(
757 self,
758 ) -> Callable[[firestore.BatchWriteRequest], firestore.BatchWriteResponse]:
759 r"""Return a callable for the batch write method over gRPC.
760
761 Applies a batch of write operations.
762
763 The BatchWrite method does not apply the write operations
764 atomically and can apply them out of order. Method does not
765 allow more than one write per document. Each write succeeds or
766 fails independently. See the
767 [BatchWriteResponse][google.firestore.v1.BatchWriteResponse] for
768 the success status of each write.
769
770 If you require an atomically applied set of writes, use
771 [Commit][google.firestore.v1.Firestore.Commit] instead.
772
773 Returns:
774 Callable[[~.BatchWriteRequest],
775 ~.BatchWriteResponse]:
776 A function that, when called, will call the underlying RPC
777 on the server.
778 """
779 # Generate a "stub function" on-the-fly which will actually make
780 # the request.
781 # gRPC handles serialization and deserialization, so we just need
782 # to pass in the functions for each.
783 if "batch_write" not in self._stubs:
784 self._stubs["batch_write"] = self._logged_channel.unary_unary(
785 "/google.firestore.v1.Firestore/BatchWrite",
786 request_serializer=firestore.BatchWriteRequest.serialize,
787 response_deserializer=firestore.BatchWriteResponse.deserialize,
788 )
789 return self._stubs["batch_write"]
790
791 @property
792 def create_document(
793 self,
794 ) -> Callable[[firestore.CreateDocumentRequest], document.Document]:
795 r"""Return a callable for the create document method over gRPC.
796
797 Creates a new document.
798
799 Returns:
800 Callable[[~.CreateDocumentRequest],
801 ~.Document]:
802 A function that, when called, will call the underlying RPC
803 on the server.
804 """
805 # Generate a "stub function" on-the-fly which will actually make
806 # the request.
807 # gRPC handles serialization and deserialization, so we just need
808 # to pass in the functions for each.
809 if "create_document" not in self._stubs:
810 self._stubs["create_document"] = self._logged_channel.unary_unary(
811 "/google.firestore.v1.Firestore/CreateDocument",
812 request_serializer=firestore.CreateDocumentRequest.serialize,
813 response_deserializer=document.Document.deserialize,
814 )
815 return self._stubs["create_document"]
816
817 def close(self):
818 self._logged_channel.close()
819
820 @property
821 def delete_operation(
822 self,
823 ) -> Callable[[operations_pb2.DeleteOperationRequest], None]:
824 r"""Return a callable for the delete_operation method over gRPC."""
825 # Generate a "stub function" on-the-fly which will actually make
826 # the request.
827 # gRPC handles serialization and deserialization, so we just need
828 # to pass in the functions for each.
829 if "delete_operation" not in self._stubs:
830 self._stubs["delete_operation"] = self._logged_channel.unary_unary(
831 "/google.longrunning.Operations/DeleteOperation",
832 request_serializer=operations_pb2.DeleteOperationRequest.SerializeToString,
833 response_deserializer=None,
834 )
835 return self._stubs["delete_operation"]
836
837 @property
838 def cancel_operation(
839 self,
840 ) -> Callable[[operations_pb2.CancelOperationRequest], None]:
841 r"""Return a callable for the cancel_operation method over gRPC."""
842 # Generate a "stub function" on-the-fly which will actually make
843 # the request.
844 # gRPC handles serialization and deserialization, so we just need
845 # to pass in the functions for each.
846 if "cancel_operation" not in self._stubs:
847 self._stubs["cancel_operation"] = self._logged_channel.unary_unary(
848 "/google.longrunning.Operations/CancelOperation",
849 request_serializer=operations_pb2.CancelOperationRequest.SerializeToString,
850 response_deserializer=None,
851 )
852 return self._stubs["cancel_operation"]
853
854 @property
855 def get_operation(
856 self,
857 ) -> Callable[[operations_pb2.GetOperationRequest], operations_pb2.Operation]:
858 r"""Return a callable for the get_operation method over gRPC."""
859 # Generate a "stub function" on-the-fly which will actually make
860 # the request.
861 # gRPC handles serialization and deserialization, so we just need
862 # to pass in the functions for each.
863 if "get_operation" not in self._stubs:
864 self._stubs["get_operation"] = self._logged_channel.unary_unary(
865 "/google.longrunning.Operations/GetOperation",
866 request_serializer=operations_pb2.GetOperationRequest.SerializeToString,
867 response_deserializer=operations_pb2.Operation.FromString,
868 )
869 return self._stubs["get_operation"]
870
871 @property
872 def list_operations(
873 self,
874 ) -> Callable[
875 [operations_pb2.ListOperationsRequest], operations_pb2.ListOperationsResponse
876 ]:
877 r"""Return a callable for the list_operations method over gRPC."""
878 # Generate a "stub function" on-the-fly which will actually make
879 # the request.
880 # gRPC handles serialization and deserialization, so we just need
881 # to pass in the functions for each.
882 if "list_operations" not in self._stubs:
883 self._stubs["list_operations"] = self._logged_channel.unary_unary(
884 "/google.longrunning.Operations/ListOperations",
885 request_serializer=operations_pb2.ListOperationsRequest.SerializeToString,
886 response_deserializer=operations_pb2.ListOperationsResponse.FromString,
887 )
888 return self._stubs["list_operations"]
889
890 @property
891 def kind(self) -> str:
892 return "grpc"
893
894
895__all__ = ("FirestoreGrpcTransport",)