def test_with_empty_list(self):
        from google.cloud.datastore_v1.types import entity as entity_pb2
        from google.cloud.datastore.entity import Entity

        entity = Entity()
        entity["foo"] = []
        entity_pb = self._call_fut(entity)

        expected_pb = entity_pb2.Entity()
        prop = expected_pb._pb.properties.get_or_create("foo")
        prop.array_value.CopyFrom(entity_pb2.ArrayValue(values=[])._pb)

        self._compare_entity_proto(entity_pb, expected_pb)
    def test_index_mismatch_ignores_empty_list(self):
        from google.cloud.datastore_v1.types import entity as entity_pb2

        _PROJECT = "PROJECT"
        _KIND = "KIND"
        _ID = 1234

        array_val_pb = entity_pb2.Value(array_value=entity_pb2.ArrayValue(
            values=[]))

        entity_pb = entity_pb2.Entity(properties={"baz": array_val_pb})
        entity_pb.key.partition_id.project_id = _PROJECT
        entity_pb.key._pb.path.add(kind=_KIND, id=_ID)

        entity = self._call_fut(entity_pb._pb)
        entity_dict = dict(entity)
        self.assertEqual(entity_dict["baz"], [])
def _set_protobuf_value(value_pb, val):
    """Assign 'val' to the correct subfield of 'value_pb'.

    The Protobuf API uses different attribute names based on value types
    rather than inferring the type.

    Some value types (entities, keys, lists) cannot be directly
    assigned; this function handles them correctly.

    :type value_pb: :class:`.entity_pb2.Value`
    :param value_pb: The value protobuf to which the value is being assigned.

    :type val: :class:`datetime.datetime`, boolean, float, integer, string,
               :class:`google.cloud.datastore.key.Key`,
               :class:`google.cloud.datastore.entity.Entity`
    :param val: The value to be assigned.
    """
    attr, val = _pb_attr_value(val)
    if attr == "key_value":
        value_pb.key_value.CopyFrom(val._pb)
    elif attr == "timestamp_value":
        value_pb.timestamp_value.CopyFrom(val)
    elif attr == "entity_value":
        entity_pb = entity_to_protobuf(val)
        value_pb.entity_value.CopyFrom(entity_pb._pb)
    elif attr == "array_value":
        if len(val) == 0:
            array_value = entity_pb2.ArrayValue(values=[])._pb
            value_pb.array_value.CopyFrom(array_value)
        else:
            l_pb = value_pb.array_value.values
            for item in val:
                i_pb = l_pb.add()
                _set_protobuf_value(i_pb, item)
    elif attr == "geo_point_value":
        value_pb.geo_point_value.CopyFrom(val)
    else:  # scalar, just assign
        setattr(value_pb, attr, val)