Skip to content

Commit

Permalink
Making sure list value PBs all have same indexed value.
Browse files Browse the repository at this point in the history
Also throwing exception explaining why this must be true.
  • Loading branch information
dhermes committed Jan 15, 2015
1 parent 3e7ade7 commit 7720cc0
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 4 deletions.
17 changes: 15 additions & 2 deletions gcloud/datastore/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,21 @@ def entity_from_protobuf(pb):
for property_pb in pb.property:
value = _get_value_from_property_pb(property_pb)
entity_props[property_pb.name] = value
if not property_pb.value.indexed:
exclude_from_indexes.append(property_pb.name)

# Check if property_pb.value was indexed. Lists need to be
# special-cased and we require all `indexed` values in a list agree.
if isinstance(value, list):
indexed_values = set(value_pb.indexed
for value_pb in property_pb.value.list_value)
if len(indexed_values) != 1:
raise ValueError('For a list_value, subvalues must either all '
'be indexed or all excluded from indexes.')

if not indexed_values.pop():
exclude_from_indexes.append(property_pb.name)
else:
if not property_pb.value.indexed:
exclude_from_indexes.append(property_pb.name)

entity = Entity(key=key, exclude_from_indexes=exclude_from_indexes)
entity.update(entity_props)
Expand Down
47 changes: 45 additions & 2 deletions gcloud/datastore/test_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,29 @@ def test_it(self):
unindexed_prop_pb.value.integer_value = 10
unindexed_prop_pb.value.indexed = False

list_prop_pb1 = entity_pb.property.add()
list_prop_pb1.name = 'baz'
list_pb1 = list_prop_pb1.value.list_value

unindexed_value_pb = list_pb1.add()
unindexed_value_pb.integer_value = 11
unindexed_value_pb.indexed = False

list_prop_pb2 = entity_pb.property.add()
list_prop_pb2.name = 'qux'
list_pb2 = list_prop_pb2.value.list_value

indexed_value_pb = list_pb2.add()
indexed_value_pb.integer_value = 12
indexed_value_pb.indexed = True

entity = self._callFUT(entity_pb)
self.assertEqual(entity.kind, _KIND)
self.assertEqual(entity.exclude_from_indexes, frozenset(['bar']))
self.assertEqual(entity.exclude_from_indexes,
frozenset(['bar', 'baz']))
entity_props = dict(entity)
self.assertEqual(entity_props, {'foo': 'Foo', 'bar': 10})
self.assertEqual(entity_props,
{'foo': 'Foo', 'bar': 10, 'baz': [11], 'qux': [12]})

# Also check the key.
key = entity.key
Expand All @@ -61,6 +79,31 @@ def test_it(self):
self.assertEqual(key.kind, _KIND)
self.assertEqual(key.id, _ID)

def test_mismatched_value_indexed(self):
from gcloud.datastore import _datastore_v1_pb2 as datastore_pb

_DATASET_ID = 'DATASET'
_KIND = 'KIND'
_ID = 1234
entity_pb = datastore_pb.Entity()
entity_pb.key.partition_id.dataset_id = _DATASET_ID
entity_pb.key.path_element.add(kind=_KIND, id=_ID)

list_prop_pb = entity_pb.property.add()
list_prop_pb.name = 'baz'
list_pb = list_prop_pb.value.list_value

unindexed_value_pb1 = list_pb.add()
unindexed_value_pb1.integer_value = 10
unindexed_value_pb1.indexed = False

unindexed_value_pb2 = list_pb.add()
unindexed_value_pb2.integer_value = 11
unindexed_value_pb2.indexed = True

with self.assertRaises(ValueError):
self._callFUT(entity_pb)


class Test_key_from_protobuf(unittest2.TestCase):

Expand Down

0 comments on commit 7720cc0

Please sign in to comment.