Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/google/cloud/firestore_v1/client.py: 50%
64 statements
« prev ^ index » next coverage.py v7.3.2, created at 2023-12-09 06:27 +0000
« prev ^ index » next coverage.py v7.3.2, created at 2023-12-09 06:27 +0000
1# Copyright 2017 Google LLC All rights reserved.
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
15"""Client for interacting with the Google Cloud Firestore API.
17This is the base from which all interactions with the API occur.
19In the hierarchy of API concepts
21* a :class:`~google.cloud.firestore_v1.client.Client` owns a
22 :class:`~google.cloud.firestore_v1.collection.CollectionReference`
23* a :class:`~google.cloud.firestore_v1.client.Client` owns a
24 :class:`~google.cloud.firestore_v1.document.DocumentReference`
25"""
27from google.api_core import gapic_v1
28from google.api_core import retry as retries
30from google.cloud.firestore_v1.base_client import (
31 BaseClient,
32 _CLIENT_INFO,
33 _parse_batch_get,
34 _path_helper,
35)
37from google.cloud.firestore_v1.query import CollectionGroup
38from google.cloud.firestore_v1.batch import WriteBatch
39from google.cloud.firestore_v1.collection import CollectionReference
40from google.cloud.firestore_v1.document import DocumentReference
41from google.cloud.firestore_v1.field_path import FieldPath
42from google.cloud.firestore_v1.transaction import Transaction
43from google.cloud.firestore_v1.services.firestore import client as firestore_client
44from google.cloud.firestore_v1.services.firestore.transports import (
45 grpc as firestore_grpc_transport,
46)
47from typing import Any, Generator, Iterable, List, Optional, Union, TYPE_CHECKING
49# Types needed only for Type Hints
50from google.cloud.firestore_v1.base_document import DocumentSnapshot
52if TYPE_CHECKING:
53 from google.cloud.firestore_v1.bulk_writer import BulkWriter # pragma: NO COVER
56class Client(BaseClient):
57 """Client for interacting with Google Cloud Firestore API.
59 .. note::
61 Since the Cloud Firestore API requires the gRPC transport, no
62 ``_http`` argument is accepted by this class.
64 Args:
65 project (Optional[str]): The project which the client acts on behalf
66 of. If not passed, falls back to the default inferred
67 from the environment.
68 credentials (Optional[~google.auth.credentials.Credentials]): The
69 OAuth2 Credentials to use for this client. If not passed, falls
70 back to the default inferred from the environment.
71 database (Optional[str]): The database name that the client targets.
72 If not passed, falls back to :attr:`DEFAULT_DATABASE`.
73 client_info (Optional[google.api_core.gapic_v1.client_info.ClientInfo]):
74 The client info used to send a user-agent string along with API
75 requests. If ``None``, then default info will be used. Generally,
76 you only need to set this if you're developing your own library
77 or partner tool.
78 client_options (Union[dict, google.api_core.client_options.ClientOptions]):
79 Client options used to set user options on the client. API Endpoint
80 should be set through client_options.
81 """
83 def __init__(
84 self,
85 project=None,
86 credentials=None,
87 database=None,
88 client_info=_CLIENT_INFO,
89 client_options=None,
90 ) -> None:
91 super(Client, self).__init__(
92 project=project,
93 credentials=credentials,
94 database=database,
95 client_info=client_info,
96 client_options=client_options,
97 )
99 @property
100 def _firestore_api(self):
101 """Lazy-loading getter GAPIC Firestore API.
102 Returns:
103 :class:`~google.cloud.gapic.firestore.v1`.firestore_client.FirestoreClient:
104 The GAPIC client with the credentials of the current client.
105 """
106 return self._firestore_api_helper(
107 firestore_grpc_transport.FirestoreGrpcTransport,
108 firestore_client.FirestoreClient,
109 firestore_client,
110 )
112 @property
113 def _target(self):
114 """Return the target (where the API is).
115 Eg. "firestore.googleapis.com"
117 Returns:
118 str: The location of the API.
119 """
120 return self._target_helper(firestore_client.FirestoreClient)
122 def collection(self, *collection_path: str) -> CollectionReference:
123 """Get a reference to a collection.
125 For a top-level collection:
127 .. code-block:: python
129 >>> client.collection('top')
131 For a sub-collection:
133 .. code-block:: python
135 >>> client.collection('mydocs/doc/subcol')
136 >>> # is the same as
137 >>> client.collection('mydocs', 'doc', 'subcol')
139 Sub-collections can be nested deeper in a similar fashion.
141 Args:
142 collection_path: Can either be
144 * A single ``/``-delimited path to a collection
145 * A tuple of collection path segments
147 Returns:
148 :class:`~google.cloud.firestore_v1.collection.CollectionReference`:
149 A reference to a collection in the Firestore database.
150 """
151 return CollectionReference(*_path_helper(collection_path), client=self)
153 def collection_group(self, collection_id: str) -> CollectionGroup:
154 """
155 Creates and returns a new Query that includes all documents in the
156 database that are contained in a collection or subcollection with the
157 given collection_id.
159 .. code-block:: python
161 >>> query = client.collection_group('mygroup')
163 Args:
164 collection_id (str) Identifies the collections to query over.
166 Every collection or subcollection with this ID as the last segment of its
167 path will be included. Cannot contain a slash.
169 Returns:
170 :class:`~google.cloud.firestore_v1.query.CollectionGroup`:
171 The created Query.
172 """
173 return CollectionGroup(self._get_collection_reference(collection_id))
175 def document(self, *document_path: str) -> DocumentReference:
176 """Get a reference to a document in a collection.
178 For a top-level document:
180 .. code-block:: python
182 >>> client.document('collek/shun')
183 >>> # is the same as
184 >>> client.document('collek', 'shun')
186 For a document in a sub-collection:
188 .. code-block:: python
190 >>> client.document('mydocs/doc/subcol/child')
191 >>> # is the same as
192 >>> client.document('mydocs', 'doc', 'subcol', 'child')
194 Documents in sub-collections can be nested deeper in a similar fashion.
196 Args:
197 document_path): Can either be
199 * A single ``/``-delimited path to a document
200 * A tuple of document path segments
202 Returns:
203 :class:`~google.cloud.firestore_v1.document.DocumentReference`:
204 A reference to a document in a collection.
205 """
206 return DocumentReference(
207 *self._document_path_helper(*document_path), client=self
208 )
210 def get_all(
211 self,
212 references: list,
213 field_paths: Iterable[str] = None,
214 transaction: Transaction = None,
215 retry: retries.Retry = gapic_v1.method.DEFAULT,
216 timeout: float = None,
217 ) -> Generator[DocumentSnapshot, Any, None]:
218 """Retrieve a batch of documents.
220 .. note::
222 Documents returned by this method are not guaranteed to be
223 returned in the same order that they are given in ``references``.
225 .. note::
227 If multiple ``references`` refer to the same document, the server
228 will only return one result.
230 See :meth:`~google.cloud.firestore_v1.client.Client.field_path` for
231 more information on **field paths**.
233 If a ``transaction`` is used and it already has write operations
234 added, this method cannot be used (i.e. read-after-write is not
235 allowed).
237 Args:
238 references (List[.DocumentReference, ...]): Iterable of document
239 references to be retrieved.
240 field_paths (Optional[Iterable[str, ...]]): An iterable of field
241 paths (``.``-delimited list of field names) to use as a
242 projection of document fields in the returned results. If
243 no value is provided, all fields will be returned.
244 transaction (Optional[:class:`~google.cloud.firestore_v1.transaction.Transaction`]):
245 An existing transaction that these ``references`` will be
246 retrieved in.
247 retry (google.api_core.retry.Retry): Designation of what errors, if any,
248 should be retried. Defaults to a system-specified policy.
249 timeout (float): The timeout for this request. Defaults to a
250 system-specified value.
252 Yields:
253 .DocumentSnapshot: The next document snapshot that fulfills the
254 query, or :data:`None` if the document does not exist.
255 """
256 request, reference_map, kwargs = self._prep_get_all(
257 references, field_paths, transaction, retry, timeout
258 )
260 response_iterator = self._firestore_api.batch_get_documents(
261 request=request,
262 metadata=self._rpc_metadata,
263 **kwargs,
264 )
266 for get_doc_response in response_iterator:
267 yield _parse_batch_get(get_doc_response, reference_map, self)
269 def collections(
270 self,
271 retry: retries.Retry = gapic_v1.method.DEFAULT,
272 timeout: float = None,
273 ) -> Generator[Any, Any, None]:
274 """List top-level collections of the client's database.
276 Args:
277 retry (google.api_core.retry.Retry): Designation of what errors, if any,
278 should be retried. Defaults to a system-specified policy.
279 timeout (float): The timeout for this request. Defaults to a
280 system-specified value.
282 Returns:
283 Sequence[:class:`~google.cloud.firestore_v1.collection.CollectionReference`]:
284 iterator of subcollections of the current document.
285 """
286 request, kwargs = self._prep_collections(retry, timeout)
288 iterator = self._firestore_api.list_collection_ids(
289 request=request,
290 metadata=self._rpc_metadata,
291 **kwargs,
292 )
294 for collection_id in iterator:
295 yield self.collection(collection_id)
297 def recursive_delete(
298 self,
299 reference: Union[CollectionReference, DocumentReference],
300 *,
301 bulk_writer: Optional["BulkWriter"] = None,
302 chunk_size: Optional[int] = 5000,
303 ) -> int:
304 """Deletes documents and their subcollections, regardless of collection
305 name.
307 Passing a CollectionReference leads to each document in the collection
308 getting deleted, as well as all of their descendents.
310 Passing a DocumentReference deletes that one document and all of its
311 descendents.
313 Args:
314 reference (Union[
315 :class:`@google.cloud.firestore_v1.collection.CollectionReference`,
316 :class:`@google.cloud.firestore_v1.document.DocumentReference`,
317 ])
318 The reference to be deleted.
320 bulk_writer (Optional[:class:`@google.cloud.firestore_v1.bulk_writer.BulkWriter`])
321 The BulkWriter used to delete all matching documents. Supply this
322 if you want to override the default throttling behavior.
324 """
325 if bulk_writer is None:
326 bulk_writer = self.bulk_writer()
328 return self._recursive_delete(
329 reference,
330 bulk_writer,
331 chunk_size=chunk_size,
332 )
334 def _recursive_delete(
335 self,
336 reference: Union[CollectionReference, DocumentReference],
337 bulk_writer: "BulkWriter",
338 *,
339 chunk_size: Optional[int] = 5000,
340 depth: Optional[int] = 0,
341 ) -> int:
342 """Recursion helper for `recursive_delete."""
344 num_deleted: int = 0
346 if isinstance(reference, CollectionReference):
347 chunk: List[DocumentSnapshot]
348 for chunk in (
349 reference.recursive()
350 .select([FieldPath.document_id()])
351 ._chunkify(chunk_size)
352 ):
353 doc_snap: DocumentSnapshot
354 for doc_snap in chunk:
355 num_deleted += 1
356 bulk_writer.delete(doc_snap.reference)
358 elif isinstance(reference, DocumentReference):
359 col_ref: CollectionReference
360 for col_ref in reference.collections():
361 num_deleted += self._recursive_delete(
362 col_ref,
363 bulk_writer,
364 chunk_size=chunk_size,
365 depth=depth + 1,
366 )
367 num_deleted += 1
368 bulk_writer.delete(reference)
370 else:
371 raise TypeError(
372 f"Unexpected type for reference: {reference.__class__.__name__}"
373 )
375 if depth == 0:
376 bulk_writer.close()
378 return num_deleted
380 def batch(self) -> WriteBatch:
381 """Get a batch instance from this client.
383 Returns:
384 :class:`~google.cloud.firestore_v1.batch.WriteBatch`:
385 A "write" batch to be used for accumulating document changes and
386 sending the changes all at once.
387 """
388 return WriteBatch(self)
390 def transaction(self, **kwargs) -> Transaction:
391 """Get a transaction that uses this client.
393 See :class:`~google.cloud.firestore_v1.transaction.Transaction` for
394 more information on transactions and the constructor arguments.
396 Args:
397 kwargs (Dict[str, Any]): The keyword arguments (other than
398 ``client``) to pass along to the
399 :class:`~google.cloud.firestore_v1.transaction.Transaction`
400 constructor.
402 Returns:
403 :class:`~google.cloud.firestore_v1.transaction.Transaction`:
404 A transaction attached to this client.
405 """
406 return Transaction(self, **kwargs)