From 2c3defa01d58cde54633eeec1b6012dd9f2bdd1d Mon Sep 17 00:00:00 2001 From: lucemia Date: Wed, 3 Dec 2014 15:43:01 +0800 Subject: [PATCH] Fix bug gcloud-datastore will raise exception while attemping to save property values set as empty list. --- gcloud/datastore/connection.py | 7 ++++++ gcloud/datastore/test_connection.py | 36 +++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/gcloud/datastore/connection.py b/gcloud/datastore/connection.py index 9642be52afc1..f07eaf834d84 100644 --- a/gcloud/datastore/connection.py +++ b/gcloud/datastore/connection.py @@ -433,6 +433,10 @@ def save_entity(self, dataset_id, key_pb, properties, will be replaced by those passed in 'properties'; properties not passed in 'properties' no longer be set for the entity. + .. note:: + When saving an entity to the backend, property values set as + empty lists or None cannot be saved and will be ignored. + :type dataset_id: string :param dataset_id: The dataset in which to save the entity. @@ -460,6 +464,9 @@ def save_entity(self, dataset_id, key_pb, properties, insert.key.CopyFrom(key_pb) for name, value in properties.items(): + if isinstance(value, list) and len(value) == 0: + continue + prop = insert.property.add() # Set the name of the property. prop.name = name diff --git a/gcloud/datastore/test_connection.py b/gcloud/datastore/test_connection.py index 5a5e8e085bbc..943bd06a298c 100644 --- a/gcloud/datastore/test_connection.py +++ b/gcloud/datastore/test_connection.py @@ -917,6 +917,42 @@ def test_allocate_ids_non_empty(self): request.ParseFromString(cw['body']) self.assertEqual(list(request.key), before_key_pbs) + def test_save_entity_w_empty_list(self): + from gcloud.datastore.connection import datastore_pb + from gcloud.datastore.key import Key + + DATASET_ID = 'DATASET' + key_pb = Key(path=[{'kind': 'Kind', 'id': 1234}]).to_protobuf() + rsp_pb = datastore_pb.CommitResponse() + conn = self._makeOne() + URI = '/'.join([ + conn.API_BASE_URL, + 'datastore', + conn.API_VERSION, + 'datasets', + DATASET_ID, + 'commit', + ]) + http = conn._http = Http({'status': '200'}, rsp_pb.SerializeToString()) + result = conn.save_entity(DATASET_ID, key_pb, + {'foo': u'Foo', 'bar': []}) + self.assertEqual(result, True) + cw = http._called_with + self._verifyProtobufCall(cw, URI, conn) + rq_class = datastore_pb.CommitRequest + request = rq_class() + request.ParseFromString(cw['body']) + self.assertEqual(request.transaction, '') + mutation = request.mutation + self.assertEqual(len(mutation.insert_auto_id), 0) + upserts = list(mutation.upsert) + self.assertEqual(len(upserts), 1) + upsert = upserts[0] + self.assertEqual(upsert.key, key_pb) + props = list(upsert.property) + self.assertEqual(len(props), 1) + self.assertNotEqual(props[0].name, 'bar') + def test_save_entity_wo_transaction_w_upsert(self): from gcloud.datastore.connection import datastore_pb from gcloud.datastore.key import Key