Skip to content

Commit 7720cc0

Browse files
committed
Making sure list value PBs all have same indexed value.
Also throwing exception explaining why this must be true.
1 parent 3e7ade7 commit 7720cc0

File tree

2 files changed

+60
-4
lines changed

2 files changed

+60
-4
lines changed

gcloud/datastore/helpers.py

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,21 @@ def entity_from_protobuf(pb):
5252
for property_pb in pb.property:
5353
value = _get_value_from_property_pb(property_pb)
5454
entity_props[property_pb.name] = value
55-
if not property_pb.value.indexed:
56-
exclude_from_indexes.append(property_pb.name)
55+
56+
# Check if property_pb.value was indexed. Lists need to be
57+
# special-cased and we require all `indexed` values in a list agree.
58+
if isinstance(value, list):
59+
indexed_values = set(value_pb.indexed
60+
for value_pb in property_pb.value.list_value)
61+
if len(indexed_values) != 1:
62+
raise ValueError('For a list_value, subvalues must either all '
63+
'be indexed or all excluded from indexes.')
64+
65+
if not indexed_values.pop():
66+
exclude_from_indexes.append(property_pb.name)
67+
else:
68+
if not property_pb.value.indexed:
69+
exclude_from_indexes.append(property_pb.name)
5770

5871
entity = Entity(key=key, exclude_from_indexes=exclude_from_indexes)
5972
entity.update(entity_props)

gcloud/datastore/test_helpers.py

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,11 +48,29 @@ def test_it(self):
4848
unindexed_prop_pb.value.integer_value = 10
4949
unindexed_prop_pb.value.indexed = False
5050

51+
list_prop_pb1 = entity_pb.property.add()
52+
list_prop_pb1.name = 'baz'
53+
list_pb1 = list_prop_pb1.value.list_value
54+
55+
unindexed_value_pb = list_pb1.add()
56+
unindexed_value_pb.integer_value = 11
57+
unindexed_value_pb.indexed = False
58+
59+
list_prop_pb2 = entity_pb.property.add()
60+
list_prop_pb2.name = 'qux'
61+
list_pb2 = list_prop_pb2.value.list_value
62+
63+
indexed_value_pb = list_pb2.add()
64+
indexed_value_pb.integer_value = 12
65+
indexed_value_pb.indexed = True
66+
5167
entity = self._callFUT(entity_pb)
5268
self.assertEqual(entity.kind, _KIND)
53-
self.assertEqual(entity.exclude_from_indexes, frozenset(['bar']))
69+
self.assertEqual(entity.exclude_from_indexes,
70+
frozenset(['bar', 'baz']))
5471
entity_props = dict(entity)
55-
self.assertEqual(entity_props, {'foo': 'Foo', 'bar': 10})
72+
self.assertEqual(entity_props,
73+
{'foo': 'Foo', 'bar': 10, 'baz': [11], 'qux': [12]})
5674

5775
# Also check the key.
5876
key = entity.key
@@ -61,6 +79,31 @@ def test_it(self):
6179
self.assertEqual(key.kind, _KIND)
6280
self.assertEqual(key.id, _ID)
6381

82+
def test_mismatched_value_indexed(self):
83+
from gcloud.datastore import _datastore_v1_pb2 as datastore_pb
84+
85+
_DATASET_ID = 'DATASET'
86+
_KIND = 'KIND'
87+
_ID = 1234
88+
entity_pb = datastore_pb.Entity()
89+
entity_pb.key.partition_id.dataset_id = _DATASET_ID
90+
entity_pb.key.path_element.add(kind=_KIND, id=_ID)
91+
92+
list_prop_pb = entity_pb.property.add()
93+
list_prop_pb.name = 'baz'
94+
list_pb = list_prop_pb.value.list_value
95+
96+
unindexed_value_pb1 = list_pb.add()
97+
unindexed_value_pb1.integer_value = 10
98+
unindexed_value_pb1.indexed = False
99+
100+
unindexed_value_pb2 = list_pb.add()
101+
unindexed_value_pb2.integer_value = 11
102+
unindexed_value_pb2.indexed = True
103+
104+
with self.assertRaises(ValueError):
105+
self._callFUT(entity_pb)
106+
64107

65108
class Test_key_from_protobuf(unittest2.TestCase):
66109

0 commit comments

Comments
 (0)