def collection(self, name) -> 'CollectionReference': from mockfirestore.collection import CollectionReference document = get_by_path(self._data, self._path) new_path = self._path + [name] if name not in document: set_by_path(self._data, new_path, {}) return CollectionReference(self._data, new_path, parent=self)
def list_documents( self, page_size: Optional[int] = None) -> Sequence[DocumentReference]: docs = [] for key in get_by_path(self._data, self._path): docs.append(self.document(key)) return docs
def document(self, name: Optional[str] = None) -> DocumentReference: collection = get_by_path(self._data, self._path) if name is None: name = generate_random_string() new_path = self._path + [name] if name not in collection: set_by_path(self._data, new_path, {}) return DocumentReference(self._data, new_path, parent=self)
def stream(self, transaction=None) -> Iterable[DocumentSnapshot]: for key in sorted(get_by_path(self._data, self._path)): doc_snapshot = self.document(key).get() if self._select: data = { field: doc_snapshot.get(field) for field in self._select } yield DocumentSnapshot(doc_snapshot.reference, data) else: yield doc_snapshot
def _update_data(new_values: dict, default: Any): for key, value in new_values.items(): path = key.split('.') try: item = get_by_path(document, path) except (TypeError, KeyError): item = default set_by_path(data, path, item + value)
def document(self, name=None): collection = get_by_path(self._data, self._path) if name is None: name = generate_random_string() new_path = self._path + [name] if name not in collection: set_by_path(self._data, new_path, {}) return MyMockFirestore.MyDocumentReference(self._data, new_path, parent=self)
def add(self, document_data: Dict, document_id: str = None) \ -> Tuple[Timestamp, DocumentReference]: document_id = generate_random_string() collection = get_by_path(self._data, self._path) new_path = self._path + [document_id] if document_id in collection: raise AlreadyExists('Document already exists: {}'.format(new_path)) doc_ref = DocumentReference(self._data, new_path, parent=self) doc_ref.set(document_data) timestamp = Timestamp.from_now() return timestamp, doc_ref
def _apply_transformations(document: Dict[str, Any], data: Dict[str, Any]) -> Dict[str, Any]: """Handles special fields like INCREMENT.""" increments: Dict[str, int] = {} for key, value in get_document_iterator(data): if not value.__class__.__module__.startswith('google.cloud.firestore'): # Unfortunately, we can't use `isinstance` here because that would require # us to declare google-cloud-firestore as a dependency for this library. # However, it's somewhat strange that the mocked version of the library # requires the library itself, so we'll just leverage this heuristic as a # means of identifying it. # # Furthermore, we don't hardcode the full module name, since the original # library seems to use a thin shim to perform versioning. e.g. at the time # of writing, the full module name is `google.cloud.firestore_v1.transforms`, # and it can evolve to `firestore_v2` in the future. continue transformer = value.__class__.__name__ if transformer == 'Increment': increments[key] = value.value # All other transformations can be applied as needed. # See #29 for tracking. for key, value in increments.items(): path = key.split('.') try: item = get_by_path(document, path) except (TypeError, KeyError): item = 0 set_by_path(data, path, item + value) document.update(data)
def update(self, data: Dict[str, Any]): document = get_by_path(self._data, self._path) if document == {}: raise NotFound('No document to update: {}'.format(self._path)) _apply_transformations(document, deepcopy(data))
def get(self) -> DocumentSnapshot: return DocumentSnapshot(self, get_by_path(self._data, self._path))
def stream(self, transaction=None) -> Iterable[DocumentSnapshot]: for key in sorted(get_by_path(self._data, self._path)): doc_snapshot = self.document(key).get() yield doc_snapshot
def update(self, data: Dict[str, Any]): document = get_by_path(self._data, self._path) if document == {}: raise NotFound('No document to update: {}'.format(self._path)) document.update(deepcopy(data))
def update(self, data: Dict[str, Any]): get_by_path(self._data, self._path).update(data)