def test_add_auto_assigned(self): from google.cloud.firestore_v1beta1.proto import document_pb2 from google.cloud.firestore_v1beta1 import _helpers from google.cloud.firestore_v1beta1.document import DocumentReference # Create a minimal fake GAPIC add attach it to a real client. firestore_api = mock.Mock(spec=["create_document"]) create_doc_response = document_pb2.Document() firestore_api.create_document.return_value = create_doc_response client = _make_client() client._firestore_api_internal = firestore_api # Actually make a collection. collection = self._make_one("grand-parent", "parent", "child", client=client) # Add a dummy response for the fake GAPIC. parent_path = collection.parent._document_path auto_assigned_id = "cheezburger" name = "{}/{}/{}".format(parent_path, collection.id, auto_assigned_id) create_doc_response = document_pb2.Document(name=name) create_doc_response.update_time.FromDatetime( datetime.datetime.utcnow()) firestore_api.create_document.return_value = create_doc_response # Actually call add() on our collection. document_data = {"been": "here"} update_time, document_ref = collection.add(document_data) # Verify the response and the mocks. self.assertIs(update_time, create_doc_response.update_time) self.assertIsInstance(document_ref, DocumentReference) self.assertIs(document_ref._client, client) expected_path = collection._path + (auto_assigned_id, ) self.assertEqual(document_ref._path, expected_path) expected_document_pb = document_pb2.Document( fields=_helpers.encode_dict(document_data)) firestore_api.create_document.assert_called_once_with( parent_path, collection_id=collection.id, document_id=None, document=expected_document_pb, mask=None, metadata=client._rpc_metadata, )
def test_update_document(self, mock_create_stub): # Mock gRPC layer grpc_stub = mock.Mock() mock_create_stub.return_value = grpc_stub client = firestore_client.FirestoreClient() # Mock request document = {} update_mask = {} # Mock response name = 'name3373707' expected_response = {'name': name} expected_response = document_pb2.Document(**expected_response) grpc_stub.UpdateDocument.return_value = expected_response response = client.update_document(document, update_mask) self.assertEqual(expected_response, response) grpc_stub.UpdateDocument.assert_called_once() args, kwargs = grpc_stub.UpdateDocument.call_args self.assertEqual(len(args), 2) self.assertEqual(len(kwargs), 1) self.assertIn('metadata', kwargs) actual_request = args[0] expected_request = firestore_pb2.UpdateDocumentRequest( document=document, update_mask=update_mask) self.assertEqual(expected_request, actual_request)
def test_create_document(self): # Setup Expected Response name = 'name3373707' expected_response = {'name': name} expected_response = document_pb2.Document(**expected_response) # Mock the API response channel = ChannelStub(responses=[expected_response]) client = firestore_client.FirestoreClient(channel=channel) # Setup Request parent = client.any_path_path('[PROJECT]', '[DATABASE]', '[DOCUMENT]', '[ANY_PATH]') collection_id = 'collectionId-821242276' document_id = 'documentId506676927' document = {} response = client.create_document(parent, collection_id, document_id, document) assert expected_response == response assert len(channel.requests) == 1 expected_request = firestore_pb2.CreateDocumentRequest( parent=parent, collection_id=collection_id, document_id=document_id, document=document) actual_request = channel.requests[0][1] assert expected_request == actual_request
def test_create_document(self): # Setup Expected Response name = "name3373707" expected_response = {"name": name} expected_response = document_pb2.Document(**expected_response) # Mock the API response channel = ChannelStub(responses=[expected_response]) patch = mock.patch("google.api_core.grpc_helpers.create_channel") with patch as create_channel: create_channel.return_value = channel client = firestore_client.FirestoreClient() # Setup Request parent = client.any_path_path("[PROJECT]", "[DATABASE]", "[DOCUMENT]", "[ANY_PATH]") collection_id = "collectionId-821242276" document_id = "documentId506676927" document = {} response = client.create_document(parent, collection_id, document_id, document) assert expected_response == response assert len(channel.requests) == 1 expected_request = firestore_pb2.CreateDocumentRequest( parent=parent, collection_id=collection_id, document_id=document_id, document=document, ) actual_request = channel.requests[0][1] assert expected_request == actual_request
def test_update(self): from google.cloud.firestore_v1beta1.proto import common_pb2 from google.cloud.firestore_v1beta1.proto import document_pb2 from google.cloud.firestore_v1beta1.proto import write_pb2 client = _make_client() batch = self._make_one(client) self.assertEqual(batch._write_pbs, []) reference = client.document('cats', 'cradle') field_path = 'head.foot' value = u'knees toes shoulders' field_updates = {field_path: value} ret_val = batch.update(reference, field_updates) self.assertIsNone(ret_val) map_pb = document_pb2.MapValue(fields={ 'foot': _value_pb(string_value=value), }) new_write_pb = write_pb2.Write( update=document_pb2.Document( name=reference._document_path, fields={'head': _value_pb(map_value=map_pb)}, ), update_mask=common_pb2.DocumentMask(field_paths=[field_path]), current_document=common_pb2.Precondition(exists=True), ) self.assertEqual(batch._write_pbs, [new_write_pb])
def test_create_document(self): # Setup Expected Response name = "name3373707" expected_response = {"name": name} expected_response = document_pb2.Document(**expected_response) # Mock the API response channel = ChannelStub(responses=[expected_response]) patch = mock.patch("google.api_core.grpc_helpers.create_channel") with patch as create_channel: create_channel.return_value = channel client = firestore_client.FirestoreClient() # Setup Request parent = "parent-995424086" collection_id = "collectionId-821242276" document = {} response = client.create_document(parent, collection_id, "documentid", document) assert expected_response == response assert len(channel.requests) == 1 expected_request = firestore_pb2.CreateDocumentRequest( parent=parent, collection_id=collection_id, document_id="documentid", document=document, ) actual_request = channel.requests[0][1] assert expected_request == actual_request
def _make_query_response(**kwargs): # kwargs supported are ``skipped_results``, ``name`` and ``data`` from google.cloud.firestore_v1beta1.proto import document_pb2 from google.cloud.firestore_v1beta1.proto import firestore_pb2 from google.cloud._helpers import _datetime_to_pb_timestamp from google.cloud.firestore_v1beta1 import _helpers now = datetime.datetime.utcnow() read_time = _datetime_to_pb_timestamp(now) kwargs['read_time'] = read_time name = kwargs.pop('name', None) data = kwargs.pop('data', None) if name is not None and data is not None: document_pb = document_pb2.Document( name=name, fields=_helpers.encode_dict(data), ) delta = datetime.timedelta(seconds=100) update_time = _datetime_to_pb_timestamp(now - delta) create_time = _datetime_to_pb_timestamp(now - 2 * delta) document_pb.update_time.CopyFrom(update_time) document_pb.create_time.CopyFrom(create_time) kwargs['document'] = document_pb return firestore_pb2.RunQueryResponse(**kwargs)
def pbs_for_set_no_merge(document_path, document_data): """Make ``Write`` protobufs for ``set()`` methods. Args: document_path (str): A fully-qualified document path. document_data (dict): Property names and values to use for replacing a document. Returns: List[google.cloud.firestore_v1beta1.types.Write]: One or two ``Write`` protobuf instances for ``set()``. """ transform_paths, actual_data, field_paths = process_server_timestamp( document_data, split_on_dots=False) write_pbs = [ write_pb2.Write(update=document_pb2.Document( name=document_path, fields=encode_dict(actual_data), )), ] if transform_paths: transform_pb = get_transform_pb(document_path, transform_paths) write_pbs.append(transform_pb) return write_pbs
def test_found(self): from google.cloud.firestore_v1beta1.proto import document_pb2 from google.cloud._helpers import _datetime_to_pb_timestamp from google.cloud.firestore_v1beta1.document import DocumentSnapshot now = datetime.datetime.utcnow() read_time = _datetime_to_pb_timestamp(now) delta = datetime.timedelta(seconds=100) update_time = _datetime_to_pb_timestamp(now - delta) create_time = _datetime_to_pb_timestamp(now - 2 * delta) ref_string = self._dummy_ref_string() document_pb = document_pb2.Document( name=ref_string, fields={ "foo": document_pb2.Value(double_value=1.5), "bar": document_pb2.Value(string_value=u"skillz"), }, create_time=create_time, update_time=update_time, ) response_pb = _make_batch_response(found=document_pb, read_time=read_time) reference_map = {ref_string: mock.sentinel.reference} snapshot = self._call_fut(response_pb, reference_map) self.assertIsInstance(snapshot, DocumentSnapshot) self.assertIs(snapshot._reference, mock.sentinel.reference) self.assertEqual(snapshot._data, {"foo": 1.5, "bar": u"skillz"}) self.assertTrue(snapshot._exists) self.assertEqual(snapshot.read_time, read_time) self.assertEqual(snapshot.create_time, create_time) self.assertEqual(snapshot.update_time, update_time)
def test_update_document(self): # Setup Expected Response name = "name3373707" expected_response = {"name": name} expected_response = document_pb2.Document(**expected_response) # Mock the API response channel = ChannelStub(responses=[expected_response]) patch = mock.patch("google.api_core.grpc_helpers.create_channel") with patch as create_channel: create_channel.return_value = channel client = firestore_client.FirestoreClient() # Setup Request document = {} update_mask = {} response = client.update_document(document, update_mask) assert expected_response == response assert len(channel.requests) == 1 expected_request = firestore_pb2.UpdateDocumentRequest( document=document, update_mask=update_mask) actual_request = channel.requests[0][1] assert expected_request == actual_request
def pbs_for_set(document_path, document_data, option): """Make ``Write`` protobufs for ``set()`` methods. Args: document_path (str): A fully-qualified document path. document_data (dict): Property names and values to use for replacing a document. option (optional[~.firestore_v1beta1.client.WriteOption]): A write option to make assertions / preconditions on the server state of the document before applying changes. Returns: List[google.cloud.firestore_v1beta1.types.Write]: One or two ``Write`` protobuf instances for ``set()``. """ transform_paths, actual_data = remove_server_timestamp(document_data) update_pb = write_pb2.Write(update=document_pb2.Document( name=document_path, fields=encode_dict(actual_data), ), ) if option is not None: option.modify_write(update_pb) write_pbs = [update_pb] if transform_paths: # NOTE: We **explicitly** don't set any write option on # the ``transform_pb``. transform_pb = get_transform_pb(document_path, transform_paths) write_pbs.append(transform_pb) return write_pbs
def test_get_document(self, mock_create_stub): # Mock gRPC layer grpc_stub = mock.Mock() mock_create_stub.return_value = grpc_stub client = firestore_client.FirestoreClient() # Mock request name = client.any_path_path('[PROJECT]', '[DATABASE]', '[DOCUMENT]', '[ANY_PATH]') # Mock response name_2 = 'name2-1052831874' expected_response = {'name': name_2} expected_response = document_pb2.Document(**expected_response) grpc_stub.GetDocument.return_value = expected_response response = client.get_document(name) self.assertEqual(expected_response, response) grpc_stub.GetDocument.assert_called_once() args, kwargs = grpc_stub.GetDocument.call_args self.assertEqual(len(args), 2) self.assertEqual(len(kwargs), 1) self.assertIn('metadata', kwargs) actual_request = args[0] expected_request = firestore_pb2.GetDocumentRequest(name=name) self.assertEqual(expected_request, actual_request)
def _write_pb_for_set(document_path, document_data): from google.cloud.firestore_v1beta1.proto import document_pb2 from google.cloud.firestore_v1beta1.proto import write_pb2 from google.cloud.firestore_v1beta1 import _helpers return write_pb2.Write(update=document_pb2.Document( name=document_path, fields=_helpers.encode_dict(document_data), ), )
def test_success(self): from google.cloud.firestore_v1beta1.proto import document_pb2 prefix = self._dummy_ref_string('sub-collection') actual_id = 'this-is-the-one' name = '{}/{}'.format(prefix, actual_id) document_pb = document_pb2.Document(name=name) document_id = self._call_fut(document_pb, prefix) self.assertEqual(document_id, actual_id)
def _write_pb_for_create(document_path, document_data): from google.cloud.firestore_v1beta1.proto import common_pb2 from google.cloud.firestore_v1beta1.proto import document_pb2 from google.cloud.firestore_v1beta1.proto import write_pb2 from google.cloud.firestore_v1beta1 import _helpers return write_pb2.Write( update=document_pb2.Document( name=document_path, fields=_helpers.encode_dict(document_data)), current_document=common_pb2.Precondition(exists=False), )
def _write_pb_for_update(document_path, update_values, field_paths): from google.cloud.firestore_v1beta1.proto import common_pb2 from google.cloud.firestore_v1beta1.proto import document_pb2 from google.cloud.firestore_v1beta1.proto import write_pb2 from google.cloud.firestore_v1beta1 import _helpers return write_pb2.Write( update=document_pb2.Document( name=document_path, fields=_helpers.encode_dict(update_values) ), update_mask=common_pb2.DocumentMask(field_paths=field_paths), current_document=common_pb2.Precondition(exists=True), )
def _helper(self, option=None, do_transform=False, **write_kwargs): from google.cloud.firestore_v1beta1.gapic import enums from google.cloud.firestore_v1beta1.proto import common_pb2 from google.cloud.firestore_v1beta1.proto import document_pb2 from google.cloud.firestore_v1beta1.proto import write_pb2 from google.cloud.firestore_v1beta1.client import Client from google.cloud.firestore_v1beta1.constants import SERVER_TIMESTAMP document_path = _make_ref_string( u'toy', u'car', u'onion', u'garlic') field_path1 = 'bitez.yum' value = b'\x00\x01' field_path2 = 'blog.internet' field_updates = {field_path1: value} if do_transform: field_updates[field_path2] = SERVER_TIMESTAMP # NOTE: ``Client.write_option()`` is a ``@staticmethod`` so # we don't need a client instance. write_pbs = self._call_fut( Client, document_path, field_updates, option) map_pb = document_pb2.MapValue(fields={ 'yum': _value_pb(bytes_value=value), }) expected_update_pb = write_pb2.Write( update=document_pb2.Document( name=document_path, fields={'bitez': _value_pb(map_value=map_pb)}, ), update_mask=common_pb2.DocumentMask(field_paths=[field_path1]), **write_kwargs ) expected_pbs = [expected_update_pb] if do_transform: server_val = enums.DocumentTransform.FieldTransform.ServerValue expected_transform_pb = write_pb2.Write( transform=write_pb2.DocumentTransform( document=document_path, field_transforms=[ write_pb2.DocumentTransform.FieldTransform( field_path=field_path2, set_to_server_value=server_val.REQUEST_TIME, ), ], ), ) expected_pbs.append(expected_transform_pb) self.assertEqual(write_pbs, expected_pbs)
def _helper(self, option=None, do_transform=False, **write_kwargs): from google.cloud.firestore_v1beta1.gapic import enums from google.cloud.firestore_v1beta1.proto import document_pb2 from google.cloud.firestore_v1beta1.proto import write_pb2 from google.cloud.firestore_v1beta1.constants import SERVER_TIMESTAMP document_path = _make_ref_string( u'little', u'town', u'of', u'ham') field_name1 = 'cheese' value1 = 1.5 field_name2 = 'crackers' value2 = True field_name3 = 'butter' document_data = { field_name1: value1, field_name2: value2, } if do_transform: document_data[field_name3] = SERVER_TIMESTAMP write_pbs = self._call_fut(document_path, document_data, option) expected_update_pb = write_pb2.Write( update=document_pb2.Document( name=document_path, fields={ field_name1: _value_pb(double_value=value1), field_name2: _value_pb(boolean_value=value2), }, ), **write_kwargs ) expected_pbs = [expected_update_pb] if do_transform: server_val = enums.DocumentTransform.FieldTransform.ServerValue expected_transform_pb = write_pb2.Write( transform=write_pb2.DocumentTransform( document=document_path, field_transforms=[ write_pb2.DocumentTransform.FieldTransform( field_path=field_name3, set_to_server_value=server_val.REQUEST_TIME, ), ], ), ) expected_pbs.append(expected_transform_pb) self.assertEqual(write_pbs, expected_pbs)
def test_failure(self): from google.cloud.firestore_v1beta1.proto import document_pb2 actual_prefix = self._dummy_ref_string('the-right-one') wrong_prefix = self._dummy_ref_string('the-wrong-one') name = '{}/{}'.format(actual_prefix, 'sorry-wont-works') document_pb = document_pb2.Document(name=name) with self.assertRaises(ValueError) as exc_info: self._call_fut(document_pb, wrong_prefix) exc_args = exc_info.exception.args self.assertEqual(len(exc_args), 4) self.assertEqual(exc_args[1], name) self.assertEqual(exc_args[3], wrong_prefix)
def test_get_testprotos(test_proto): testcase = test_proto.get firestore_api = mock.Mock(spec=["get_document"]) response = document_pb2.Document() firestore_api.get_document.return_value = response client, document = _make_client_document(firestore_api, testcase) document.get() # No '.textprotos' for errors, field_paths. firestore_api.get_document.assert_called_once_with( document._document_path, mask=None, transaction=None, metadata=client._rpc_metadata, )
def get_update_pb(self, document_path, exists=None, allow_empty_mask=False): if exists is not None: current_document = common_pb2.Precondition(exists=exists) else: current_document = None update_pb = write_pb2.Write( update=document_pb2.Document( name=document_path, fields=encode_dict(self.set_fields) ), update_mask=self._get_update_mask(allow_empty_mask), current_document=current_document, ) return update_pb
def _write_pb_for_set(document_path, document_data, merge): from google.cloud.firestore_v1beta1.proto import common_pb2 from google.cloud.firestore_v1beta1.proto import document_pb2 from google.cloud.firestore_v1beta1.proto import write_pb2 from google.cloud.firestore_v1beta1 import _helpers write_pbs = write_pb2.Write(update=document_pb2.Document( name=document_path, fields=_helpers.encode_dict(document_data), ), ) if merge: _, _, field_paths = _helpers.process_server_timestamp( document_data, split_on_dots=False) field_paths = _helpers.canonicalize_field_paths(field_paths) mask = common_pb2.DocumentMask(field_paths=sorted(field_paths)) write_pbs.update_mask.CopyFrom(mask) return write_pbs
def add(self, document_data, document_id=None): """Create a document in the Firestore database with the provided data. Args: document_data (dict): Property names and values to use for creating the document. document_id (Optional[str]): The document identifier within the current collection. If not provided, an ID will be automatically assigned by the server (the assigned ID will be a random 20 character string composed of digits, uppercase and lowercase letters). Returns: Tuple[google.protobuf.timestamp_pb2.Timestamp, \ ~.firestore_v1beta1.document.DocumentReference]: Pair of * The ``update_time`` when the document was created (or overwritten). * A document reference for the created document. Raises: ~google.cloud.exceptions.Conflict: If ``document_id`` is provided and the document already exists. """ if document_id is None: parent_path, expected_prefix = self._parent_info() document_pb = document_pb2.Document() created_document_pb = self._client._firestore_api.create_document( parent_path, collection_id=self.id, document_id=None, document=document_pb, mask=None, metadata=self._client._rpc_metadata, ) new_document_id = _helpers.get_doc_id(created_document_pb, expected_prefix) document_ref = self.document(new_document_id) set_result = document_ref.set(document_data) return set_result.update_time, document_ref else: document_ref = self.document(document_id) write_result = document_ref.create(document_data) return write_result.update_time, document_ref
def pbs_for_update(client, document_path, field_updates, option): """Make ``Write`` protobufs for ``update()`` methods. Args: client (~.firestore_v1beta1.client.Client): A client that has a write option factory. document_path (str): A fully-qualified document path. field_updates (dict): Field names or paths to update and values to update with. option (optional[~.firestore_v1beta1.client.WriteOption]): A write option to make assertions / preconditions on the server state of the document before applying changes. Returns: List[google.cloud.firestore_v1beta1.types.Write]: One or two ``Write`` protobuf instances for ``update()``. """ if option is None: # Default uses ``exists=True``. option = client.write_option(exists=True) transform_paths, actual_updates, field_paths = ( process_server_timestamp(field_updates)) if not (transform_paths or actual_updates): raise ValueError('There are only ServerTimeStamp objects or is empty.') update_values, field_paths = FieldPathHelper.to_field_paths(actual_updates) field_paths = canonicalize_field_paths(field_paths) update_pb = write_pb2.Write( update=document_pb2.Document( name=document_path, fields=encode_dict(update_values), ), update_mask=common_pb2.DocumentMask(field_paths=field_paths), ) # Due to the default, we don't have to check if ``None``. option.modify_write(update_pb, field_paths=field_paths) write_pbs = [update_pb] if transform_paths: # NOTE: We **explicitly** don't set any write option on # the ``transform_pb``. transform_pb = get_transform_pb(document_path, transform_paths) write_pbs.append(transform_pb) return write_pbs
def _write_pb_for_set(document_path, document_data, merge): from google.cloud.firestore_v1beta1.proto import common_pb2 from google.cloud.firestore_v1beta1.proto import document_pb2 from google.cloud.firestore_v1beta1.proto import write_pb2 from google.cloud.firestore_v1beta1 import _helpers write_pbs = write_pb2.Write(update=document_pb2.Document( name=document_path, fields=_helpers.encode_dict(document_data))) if merge: field_paths = [ field_path for field_path, value in _helpers.extract_fields( document_data, _helpers.FieldPath()) ] field_paths = [ field_path.to_api_repr() for field_path in sorted(field_paths) ] mask = common_pb2.DocumentMask(field_paths=sorted(field_paths)) write_pbs.update_mask.CopyFrom(mask) return write_pbs
def test_set(self): from google.cloud.firestore_v1beta1.proto import document_pb2 from google.cloud.firestore_v1beta1.proto import write_pb2 client = _make_client() batch = self._make_one(client) self.assertEqual(batch._write_pbs, []) reference = client.document("another", "one") field = "zapzap" value = u"meadows and flowers" document_data = {field: value} ret_val = batch.set(reference, document_data) self.assertIsNone(ret_val) new_write_pb = write_pb2.Write(update=document_pb2.Document( name=reference._document_path, fields={field: _value_pb(string_value=value)}, )) self.assertEqual(batch._write_pbs, [new_write_pb])
def _doc_get_info(ref_string, values): from google.cloud.firestore_v1beta1.proto import document_pb2 from google.cloud._helpers import _datetime_to_pb_timestamp from google.cloud.firestore_v1beta1 import _helpers now = datetime.datetime.utcnow() read_time = _datetime_to_pb_timestamp(now) delta = datetime.timedelta(seconds=100) update_time = _datetime_to_pb_timestamp(now - delta) create_time = _datetime_to_pb_timestamp(now - 2 * delta) document_pb = document_pb2.Document( name=ref_string, fields=_helpers.encode_dict(values), create_time=create_time, update_time=update_time, ) return document_pb, read_time
def pbs_for_set(document_path, document_data, merge=False, exists=None): """Make ``Write`` protobufs for ``set()`` methods. Args: document_path (str): A fully-qualified document path. document_data (dict): Property names and values to use for replacing a document. merge (bool): Whether to merge the fields or replace them exists (bool): If set, a precondition to indicate whether the document should exist or not. Used for create. Returns: List[google.cloud.firestore_v1beta1.types.Write]: One or two ``Write`` protobuf instances for ``set()``. """ transform_paths, actual_data, field_paths = process_server_timestamp( document_data, False) update_pb = write_pb2.Write(update=document_pb2.Document( name=document_path, fields=encode_dict(actual_data), ), ) if exists is not None: update_pb.current_document.CopyFrom( common_pb2.Precondition(exists=exists)) if merge: field_paths = canonicalize_field_paths(field_paths) mask = common_pb2.DocumentMask(field_paths=sorted(field_paths)) update_pb.update_mask.CopyFrom(mask) write_pbs = [update_pb] if transform_paths: # NOTE: We **explicitly** don't set any write option on # the ``transform_pb``. transform_pb = get_transform_pb(document_path, transform_paths) if not actual_data: write_pbs = [transform_pb] return write_pbs write_pbs.append(transform_pb) return write_pbs
def test_get_document(self): # Setup Expected Response name_2 = 'name2-1052831874' expected_response = {'name': name_2} expected_response = document_pb2.Document(**expected_response) # Mock the API response channel = ChannelStub(responses=[expected_response]) client = firestore_client.FirestoreClient(channel=channel) # Setup Request name = client.any_path_path('[PROJECT]', '[DATABASE]', '[DOCUMENT]', '[ANY_PATH]') response = client.get_document(name) assert expected_response == response assert len(channel.requests) == 1 expected_request = firestore_pb2.GetDocumentRequest(name=name) actual_request = channel.requests[0][1] assert expected_request == actual_request
def pbs_for_create(document_path, document_data): """Make ``Write`` protobufs for ``create()`` methods. Args: document_path (str): A fully-qualified document path. document_data (dict): Property names and values to use for creating a document. Returns: List[google.cloud.firestore_v1beta1.types.Write]: One or two ``Write`` protobuf instances for ``create()``. """ transform_paths, actual_data, field_paths = process_server_timestamp( document_data, split_on_dots=False) write_pbs = [] empty_document = not document_data if empty_document or actual_data: update_pb = write_pb2.Write( update=document_pb2.Document( name=document_path, fields=encode_dict(actual_data), ), current_document=common_pb2.Precondition(exists=False), ) write_pbs.append(update_pb) if transform_paths: transform_pb = get_transform_pb(document_path, transform_paths) if not actual_data: transform_pb.current_document.CopyFrom( common_pb2.Precondition(exists=False)) write_pbs.append(transform_pb) return write_pbs