From 1a79c899bac0f0e3e25bd7bee2af42091297f18e Mon Sep 17 00:00:00 2001 From: Tres Seaver Date: Thu, 9 Oct 2014 10:16:41 -0400 Subject: [PATCH 01/10] Add explicit support for 'entity_value' in protobufs. --- gcloud/datastore/helpers.py | 6 ++++++ gcloud/datastore/test_helpers.py | 23 +++++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/gcloud/datastore/helpers.py b/gcloud/datastore/helpers.py index 2e8aa5f80bda..cae7070c8762 100644 --- a/gcloud/datastore/helpers.py +++ b/gcloud/datastore/helpers.py @@ -5,6 +5,7 @@ from google.protobuf.internal.type_checkers import Int64ValueChecker import pytz +from gcloud.datastore.entity import Entity from gcloud.datastore.key import Key INT_VALUE_CHECKER = Int64ValueChecker() @@ -60,6 +61,8 @@ def get_protobuf_attribute_and_value(val): name, value = 'integer', long(val) # Always cast to a long. elif isinstance(val, basestring): name, value = 'string', val + elif isinstance(val, Entity): + name, value = 'entity', val else: raise ValueError("Unknown protobuf attr type %s" % type(val)) @@ -103,5 +106,8 @@ def get_value_from_protobuf(pb): elif pb.value.HasField('string_value'): return pb.value.string_value + elif pb.value.HasField('entity_value'): + return Entity.from_protobuf(pb.value.entity_value) # dataset? + else: return None diff --git a/gcloud/datastore/test_helpers.py b/gcloud/datastore/test_helpers.py index 3a77c570b5a9..c8ea33bc362a 100644 --- a/gcloud/datastore/test_helpers.py +++ b/gcloud/datastore/test_helpers.py @@ -83,6 +83,13 @@ def test_unicode(self): self.assertEqual(name, 'string_value') self.assertEqual(value, u'str') + def test_entity(self): + from gcloud.datastore.entity import Entity + entity = Entity() + name, value = self._callFUT(entity) + self.assertEqual(name, 'entity_value') + self.assertTrue(value is entity) + def test_object(self): self.assertRaises(ValueError, self._callFUT, object()) @@ -146,6 +153,22 @@ def test_unicode(self): pb = self._makePB('string_value', u'str') self.assertEqual(self._callFUT(pb), u'str') + def test_entity(self): + from gcloud.datastore.datastore_v1_pb2 import Property + from gcloud.datastore.entity import Entity + + _DATASET = 'DATASET' + _KIND = 'KIND' + _ID = 1234 + pb = Property() + entity_pb = pb.value.entity_value + prop_pb = entity_pb.property.add() + prop_pb.name = 'foo' + prop_pb.value.string_value = 'Foo' + entity = self._callFUT(pb) + self.assertTrue(isinstance(entity, Entity)) + self.assertEqual(entity['foo'], 'Foo') + def test_unknown(self): from gcloud.datastore.datastore_v1_pb2 import Property pb = Property() From e5954fcd22941b4221387a76a1e562b2e8097d70 Mon Sep 17 00:00:00 2001 From: Tres Seaver Date: Thu, 9 Oct 2014 10:18:35 -0400 Subject: [PATCH 02/10] Lint removal. --- gcloud/datastore/helpers.py | 2 +- gcloud/datastore/test_helpers.py | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/gcloud/datastore/helpers.py b/gcloud/datastore/helpers.py index cae7070c8762..29d66f337ce5 100644 --- a/gcloud/datastore/helpers.py +++ b/gcloud/datastore/helpers.py @@ -107,7 +107,7 @@ def get_value_from_protobuf(pb): return pb.value.string_value elif pb.value.HasField('entity_value'): - return Entity.from_protobuf(pb.value.entity_value) # dataset? + return Entity.from_protobuf(pb.value.entity_value) # XXX dataset? else: return None diff --git a/gcloud/datastore/test_helpers.py b/gcloud/datastore/test_helpers.py index c8ea33bc362a..664eac3a2892 100644 --- a/gcloud/datastore/test_helpers.py +++ b/gcloud/datastore/test_helpers.py @@ -157,9 +157,6 @@ def test_entity(self): from gcloud.datastore.datastore_v1_pb2 import Property from gcloud.datastore.entity import Entity - _DATASET = 'DATASET' - _KIND = 'KIND' - _ID = 1234 pb = Property() entity_pb = pb.value.entity_value prop_pb = entity_pb.property.add() From c8f9a7a8cbf756c08c133f210cda73987b554547 Mon Sep 17 00:00:00 2001 From: Tres Seaver Date: Thu, 9 Oct 2014 11:30:08 -0400 Subject: [PATCH 03/10] Add helpers.set_protobuf_value. Handles compount fields (entity, key) not assignable via setattr. --- gcloud/datastore/helpers.py | 36 +++++++++++ gcloud/datastore/test_helpers.py | 105 +++++++++++++++++++++++++++++++ 2 files changed, 141 insertions(+) diff --git a/gcloud/datastore/helpers.py b/gcloud/datastore/helpers.py index 29d66f337ce5..fc183088335a 100644 --- a/gcloud/datastore/helpers.py +++ b/gcloud/datastore/helpers.py @@ -111,3 +111,39 @@ def get_value_from_protobuf(pb): else: return None + + +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:`gcloud.datastore.datastore_v1_pb2.Value` + :param value: The value protobuf to which the value is being assigned. + + :type val: `datetime.datetime`, bool, float, integer, string + :class:`gcloud.datastore.key.Key`, + :class:`gcloud.datastore.entity.Entity`, + :param val: The value to be assigned. + """ + attr, val = get_protobuf_attribute_and_value(val) + if attr == 'key_value': + value_pb.key_value.CopyFrom(val) + elif attr == 'entity_value': + e_pb = value_pb.entity_value + e_pb.Clear() + key = val.key() + if key is None: + e_pb.key.CopyFrom(Key().to_protobuf()) + else: + e_pb.key.CopyFrom(key.to_protobuf()) + for k, v in val.items(): + p_pb = e_pb.property.add() + p_pb.name = k + set_protobuf_value(p_pb.value, v) + else: # scalar, just assign + setattr(value_pb, attr, val) diff --git a/gcloud/datastore/test_helpers.py b/gcloud/datastore/test_helpers.py index 664eac3a2892..2d4bb9a62086 100644 --- a/gcloud/datastore/test_helpers.py +++ b/gcloud/datastore/test_helpers.py @@ -168,5 +168,110 @@ def test_entity(self): def test_unknown(self): from gcloud.datastore.datastore_v1_pb2 import Property + pb = Property() self.assertEqual(self._callFUT(pb), None) # XXX desirable? + + +class Test_set_protobuf_value(unittest2.TestCase): + + def _callFUT(self, value_pb, val): + from gcloud.datastore.helpers import set_protobuf_value + + return set_protobuf_value(value_pb, val) + + def _makePB(self): + from gcloud.datastore.datastore_v1_pb2 import Value + + return Value() + + def test_datetime(self): + import calendar + import datetime + import pytz + + pb = self._makePB() + utc = datetime.datetime(2014, 9, 16, 10, 19, 32, 4375, pytz.utc) + self._callFUT(pb, utc) + value = pb.timestamp_microseconds_value + self.assertEqual(value / 1000000, calendar.timegm(utc.timetuple())) + self.assertEqual(value % 1000000, 4375) + + def test_key(self): + from gcloud.datastore.dataset import Dataset + from gcloud.datastore.key import Key + + _DATASET = 'DATASET' + _KIND = 'KIND' + _ID = 1234 + _PATH = [{'kind': _KIND, 'id': _ID}] + pb = self._makePB() + key = Key(dataset=Dataset(_DATASET), path=_PATH) + self._callFUT(pb, key) + value = pb.key_value + self.assertEqual(value, key.to_protobuf()) + + def test_bool(self): + pb = self._makePB() + self._callFUT(pb, False) + value = pb.boolean_value + self.assertEqual(value, False) + + def test_float(self): + pb = self._makePB() + self._callFUT(pb, 3.1415926) + value = pb.double_value + self.assertEqual(value, 3.1415926) + + def test_int(self): + pb = self._makePB() + self._callFUT(pb, 42) + value = pb.integer_value + self.assertEqual(value, 42) + + def test_long(self): + pb = self._makePB() + must_be_long = (1 << 63) - 1 + self._callFUT(pb, must_be_long) + value = pb.integer_value + self.assertEqual(value, must_be_long) + + def test_native_str(self): + pb = self._makePB() + self._callFUT(pb, 'str') + value = pb.string_value + self.assertEqual(value, 'str') + + def test_unicode(self): + pb = self._makePB() + self._callFUT(pb, u'str') + value = pb.string_value + self.assertEqual(value, u'str') + + def test_entity_empty_wo_key(self): + from gcloud.datastore.entity import Entity + from gcloud.datastore.key import Key + + pb = self._makePB() + entity = Entity() + self._callFUT(pb, entity) + value = pb.entity_value + self.assertEqual(value.key, Key().to_protobuf()) + props = list(value.property) + self.assertEqual(len(props), 0) + + def test_entity_w_key(self): + from gcloud.datastore.entity import Entity + from gcloud.datastore.key import Key + + pb = self._makePB() + key = Key(path=[{'kind': 'KIND', 'id': 123}]) + entity = Entity().key(key) + entity['foo'] = 'Foo' + self._callFUT(pb, entity) + value = pb.entity_value + self.assertEqual(value.key, key.to_protobuf()) + props = list(value.property) + self.assertEqual(len(props), 1) + self.assertEqual(props[0].name, 'foo') + self.assertEqual(props[0].value.string_value, 'Foo') From 37304c9c4941ac52a2c0ce0246b6da20c1141a6d Mon Sep 17 00:00:00 2001 From: Tres Seaver Date: Thu, 9 Oct 2014 11:41:19 -0400 Subject: [PATCH 04/10] Use helpers.set_protobuf_value to support composite types. --- gcloud/datastore/connection.py | 3 +-- gcloud/datastore/query.py | 3 +-- gcloud/datastore/test_connection.py | 26 ++++++++++++++++++++++++++ gcloud/datastore/test_query.py | 23 +++++++++++++++++++++++ 4 files changed, 51 insertions(+), 4 deletions(-) diff --git a/gcloud/datastore/connection.py b/gcloud/datastore/connection.py index 529bdcfaff06..7f97efa2141c 100644 --- a/gcloud/datastore/connection.py +++ b/gcloud/datastore/connection.py @@ -323,8 +323,7 @@ def save_entity(self, dataset_id, key_pb, properties): prop.name = name # Set the appropriate value. - pb_attr, pb_value = helpers.get_protobuf_attribute_and_value(value) - setattr(prop.value, pb_attr, pb_value) + helpers.set_protobuf_value(prop.value, value) # If this is in a transaction, we should just return True. The # transaction will handle assigning any keys as necessary. diff --git a/gcloud/datastore/query.py b/gcloud/datastore/query.py index 76a6ed12ae0e..990c075652d1 100644 --- a/gcloud/datastore/query.py +++ b/gcloud/datastore/query.py @@ -131,8 +131,7 @@ def filter(self, expression, value): property_filter.operator = operator # Set the value to filter on based on the type. - attr_name, pb_value = helpers.get_protobuf_attribute_and_value(value) - setattr(property_filter.value, attr_name, pb_value) + helpers.set_protobuf_value(property_filter.value, value) return clone def ancestor(self, ancestor): diff --git a/gcloud/datastore/test_connection.py b/gcloud/datastore/test_connection.py index d0cb0da81921..2a2af9209cfb 100644 --- a/gcloud/datastore/test_connection.py +++ b/gcloud/datastore/test_connection.py @@ -699,6 +699,32 @@ def mutation(self): mutation = conn.mutation() self.assertEqual(len(mutation.upsert), 1) + def test_save_entity_w_transaction_nested_entity(self): + from gcloud.datastore.connection import datastore_pb + from gcloud.datastore.dataset import Dataset + from gcloud.datastore.entity import Entity + from gcloud.datastore.key import Key + + mutation = datastore_pb.Mutation() + + class Xact(object): + def mutation(self): + return mutation + DATASET_ID = 'DATASET' + nested = Entity() + nested['bar'] = 'Bar' + key_pb = Key(dataset=Dataset(DATASET_ID), + path=[{'kind': 'Kind', 'id': 1234}]).to_protobuf() + rsp_pb = datastore_pb.CommitResponse() + conn = self._makeOne() + conn.transaction(Xact()) + http = conn._http = Http({'status': '200'}, rsp_pb.SerializeToString()) + result = conn.save_entity(DATASET_ID, key_pb, {'foo': nested}) + self.assertEqual(result, True) + self.assertEqual(http._called_with, None) + mutation = conn.mutation() + self.assertEqual(len(mutation.upsert), 1) + def test_delete_entities_wo_transaction(self): from gcloud.datastore.connection import datastore_pb from gcloud.datastore.dataset import Dataset diff --git a/gcloud/datastore/test_query.py b/gcloud/datastore/test_query.py index 74f6f795f2a6..219b63c1e28c 100644 --- a/gcloud/datastore/test_query.py +++ b/gcloud/datastore/test_query.py @@ -71,6 +71,29 @@ def test_filter_w_known_operator(self): self.assertEqual(p_pb.property.name, 'firstname') self.assertEqual(p_pb.value.string_value, 'John') + def test_filter_w_known_operator_and_entity(self): + import operator + from gcloud.datastore.entity import Entity + query = self._makeOne() + other = Entity() + other['firstname'] = 'John' + other['lastname'] = 'Smith' + after = query.filter('other =', other) + self.assertFalse(after is query) + self.assertTrue(isinstance(after, self._getTargetClass())) + q_pb = after.to_protobuf() + self.assertEqual(q_pb.filter.composite_filter.operator, 1) # AND + f_pb, = list(q_pb.filter.composite_filter.filter) + p_pb = f_pb.property_filter + self.assertEqual(p_pb.property.name, 'other') + other_pb = p_pb.value.entity_value + props = sorted(other_pb.property, key=operator.attrgetter('name')) + self.assertEqual(len(props), 2) + self.assertEqual(props[0].name, 'firstname') + self.assertEqual(props[0].value.string_value, 'John') + self.assertEqual(props[1].name, 'lastname') + self.assertEqual(props[1].value.string_value, 'Smith') + def test_ancestor_w_non_key_non_list(self): query = self._makeOne() # XXX s.b. ValueError From f5ee0d70c0bd3ad024f6b55ccef933f508cda2ad Mon Sep 17 00:00:00 2001 From: Tres Seaver Date: Thu, 9 Oct 2014 15:48:06 -0400 Subject: [PATCH 05/10] Fix docstring param name. Incorporates feedback from @dhermes. --- gcloud/datastore/helpers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcloud/datastore/helpers.py b/gcloud/datastore/helpers.py index fc183088335a..1cdfae66c9f9 100644 --- a/gcloud/datastore/helpers.py +++ b/gcloud/datastore/helpers.py @@ -123,7 +123,7 @@ def set_protobuf_value(value_pb, val): this function handles them correctly. :type value_pb: :class:`gcloud.datastore.datastore_v1_pb2.Value` - :param value: The value protobuf to which the value is being assigned. + :param value_pb: The value protobuf to which the value is being assigned. :type val: `datetime.datetime`, bool, float, integer, string :class:`gcloud.datastore.key.Key`, From 8fe416896a3dc483b6ccc6b8b00dc26d6929cf3c Mon Sep 17 00:00:00 2001 From: Tres Seaver Date: Thu, 9 Oct 2014 15:51:19 -0400 Subject: [PATCH 06/10] Drop XXX comment. Entities are not required to have datasets w/ active connections. --- gcloud/datastore/helpers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcloud/datastore/helpers.py b/gcloud/datastore/helpers.py index 1cdfae66c9f9..e68f500c4143 100644 --- a/gcloud/datastore/helpers.py +++ b/gcloud/datastore/helpers.py @@ -107,7 +107,7 @@ def get_value_from_protobuf(pb): return pb.value.string_value elif pb.value.HasField('entity_value'): - return Entity.from_protobuf(pb.value.entity_value) # XXX dataset? + return Entity.from_protobuf(pb.value.entity_value) else: return None From 1679154e7170da2fb0e978380ac6a51852aa407a Mon Sep 17 00:00:00 2001 From: Tres Seaver Date: Thu, 9 Oct 2014 16:28:46 -0400 Subject: [PATCH 07/10] Don't set default key on entity protobuf if entity has no key. Incorporates feedback from @dhermes. --- gcloud/datastore/helpers.py | 4 +--- gcloud/datastore/test_helpers.py | 3 +-- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/gcloud/datastore/helpers.py b/gcloud/datastore/helpers.py index e68f500c4143..b296c8286610 100644 --- a/gcloud/datastore/helpers.py +++ b/gcloud/datastore/helpers.py @@ -137,9 +137,7 @@ def set_protobuf_value(value_pb, val): e_pb = value_pb.entity_value e_pb.Clear() key = val.key() - if key is None: - e_pb.key.CopyFrom(Key().to_protobuf()) - else: + if key is not None: e_pb.key.CopyFrom(key.to_protobuf()) for k, v in val.items(): p_pb = e_pb.property.add() diff --git a/gcloud/datastore/test_helpers.py b/gcloud/datastore/test_helpers.py index 2d4bb9a62086..9fff489df6c3 100644 --- a/gcloud/datastore/test_helpers.py +++ b/gcloud/datastore/test_helpers.py @@ -250,13 +250,12 @@ def test_unicode(self): def test_entity_empty_wo_key(self): from gcloud.datastore.entity import Entity - from gcloud.datastore.key import Key pb = self._makePB() entity = Entity() self._callFUT(pb, entity) value = pb.entity_value - self.assertEqual(value.key, Key().to_protobuf()) + self.assertEqual(value.key.SerializeToString(), '') props = list(value.property) self.assertEqual(len(props), 0) From 49f04b56c77348c7cf31c7213c5b45457b208fd1 Mon Sep 17 00:00:00 2001 From: Tres Seaver Date: Thu, 9 Oct 2014 16:33:41 -0400 Subject: [PATCH 08/10] Rename helper functions with leading underscore. Signal that they are *not* part of the gcloud-python API. --- gcloud/datastore/connection.py | 2 +- gcloud/datastore/entity.py | 2 +- gcloud/datastore/helpers.py | 14 +++++++------- gcloud/datastore/query.py | 2 +- gcloud/datastore/test_helpers.py | 16 ++++++++-------- 5 files changed, 18 insertions(+), 18 deletions(-) diff --git a/gcloud/datastore/connection.py b/gcloud/datastore/connection.py index 7f97efa2141c..a43b3860807f 100644 --- a/gcloud/datastore/connection.py +++ b/gcloud/datastore/connection.py @@ -323,7 +323,7 @@ def save_entity(self, dataset_id, key_pb, properties): prop.name = name # Set the appropriate value. - helpers.set_protobuf_value(prop.value, value) + helpers._set_protobuf_value(prop.value, value) # If this is in a transaction, we should just return True. The # transaction will handle assigning any keys as necessary. diff --git a/gcloud/datastore/entity.py b/gcloud/datastore/entity.py index 06913fb3223b..be6ac340ffde 100644 --- a/gcloud/datastore/entity.py +++ b/gcloud/datastore/entity.py @@ -157,7 +157,7 @@ def from_protobuf(cls, pb, dataset=None): # pylint: disable=invalid-name entity = cls.from_key(key) for property_pb in pb.property: - value = helpers.get_value_from_protobuf(property_pb) + value = helpers._get_value_from_protobuf(property_pb) entity[property_pb.name] = value return entity diff --git a/gcloud/datastore/helpers.py b/gcloud/datastore/helpers.py index b296c8286610..c9d9fd22bfd1 100644 --- a/gcloud/datastore/helpers.py +++ b/gcloud/datastore/helpers.py @@ -11,7 +11,7 @@ INT_VALUE_CHECKER = Int64ValueChecker() -def get_protobuf_attribute_and_value(val): +def _get_protobuf_attribute_and_value(val): """Given a value, return the protobuf attribute name and proper value. The Protobuf API uses different attribute names @@ -28,9 +28,9 @@ def get_protobuf_attribute_and_value(val): For example: - >>> get_protobuf_attribute_and_value(1234) + >>> _get_protobuf_attribute_and_value(1234) ('integer_value', 1234) - >>> get_protobuf_attribute_and_value('my_string') + >>> _get_protobuf_attribute_and_value('my_string') ('string_value', 'my_string') :type val: `datetime.datetime`, :class:`gcloud.datastore.key.Key`, @@ -69,7 +69,7 @@ def get_protobuf_attribute_and_value(val): return name + '_value', value -def get_value_from_protobuf(pb): +def _get_value_from_protobuf(pb): """Given a protobuf for a Property, get the correct value. The Cloud Datastore Protobuf API returns a Property Protobuf @@ -113,7 +113,7 @@ def get_value_from_protobuf(pb): return None -def set_protobuf_value(value_pb, val): +def _set_protobuf_value(value_pb, val): """Assign 'val' to the correct subfield of 'value_pb'. The Protobuf API uses different attribute names @@ -130,7 +130,7 @@ def set_protobuf_value(value_pb, val): :class:`gcloud.datastore.entity.Entity`, :param val: The value to be assigned. """ - attr, val = get_protobuf_attribute_and_value(val) + attr, val = _get_protobuf_attribute_and_value(val) if attr == 'key_value': value_pb.key_value.CopyFrom(val) elif attr == 'entity_value': @@ -142,6 +142,6 @@ def set_protobuf_value(value_pb, val): for k, v in val.items(): p_pb = e_pb.property.add() p_pb.name = k - set_protobuf_value(p_pb.value, v) + _set_protobuf_value(p_pb.value, v) else: # scalar, just assign setattr(value_pb, attr, val) diff --git a/gcloud/datastore/query.py b/gcloud/datastore/query.py index 990c075652d1..2b867b71700f 100644 --- a/gcloud/datastore/query.py +++ b/gcloud/datastore/query.py @@ -131,7 +131,7 @@ def filter(self, expression, value): property_filter.operator = operator # Set the value to filter on based on the type. - helpers.set_protobuf_value(property_filter.value, value) + helpers._set_protobuf_value(property_filter.value, value) return clone def ancestor(self, ancestor): diff --git a/gcloud/datastore/test_helpers.py b/gcloud/datastore/test_helpers.py index 9fff489df6c3..5065a92b15ca 100644 --- a/gcloud/datastore/test_helpers.py +++ b/gcloud/datastore/test_helpers.py @@ -1,12 +1,12 @@ import unittest2 -class Test_get_protobuf_attribute_and_value(unittest2.TestCase): +class Test__get_protobuf_attribute_and_value(unittest2.TestCase): def _callFUT(self, val): - from gcloud.datastore.helpers import get_protobuf_attribute_and_value + from gcloud.datastore.helpers import _get_protobuf_attribute_and_value - return get_protobuf_attribute_and_value(val) + return _get_protobuf_attribute_and_value(val) def test_datetime_naive(self): import calendar @@ -94,12 +94,12 @@ def test_object(self): self.assertRaises(ValueError, self._callFUT, object()) -class Test_get_value_from_protobuf(unittest2.TestCase): +class Test__get_value_from_protobuf(unittest2.TestCase): def _callFUT(self, pb): - from gcloud.datastore.helpers import get_value_from_protobuf + from gcloud.datastore.helpers import _get_value_from_protobuf - return get_value_from_protobuf(pb) + return _get_value_from_protobuf(pb) def _makePB(self, attr_name, value): from gcloud.datastore.datastore_v1_pb2 import Property @@ -176,9 +176,9 @@ def test_unknown(self): class Test_set_protobuf_value(unittest2.TestCase): def _callFUT(self, value_pb, val): - from gcloud.datastore.helpers import set_protobuf_value + from gcloud.datastore.helpers import _set_protobuf_value - return set_protobuf_value(value_pb, val) + return _set_protobuf_value(value_pb, val) def _makePB(self): from gcloud.datastore.datastore_v1_pb2 import Value From 275f6bd42755776e5d754d35bca59b0dfc5dbf07 Mon Sep 17 00:00:00 2001 From: Tres Seaver Date: Thu, 9 Oct 2014 16:35:05 -0400 Subject: [PATCH 09/10] Update doctring to indicate that helper functions are not API. Note that these are functions, not methods. --- gcloud/datastore/helpers.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/gcloud/datastore/helpers.py b/gcloud/datastore/helpers.py index c9d9fd22bfd1..792b3d494c42 100644 --- a/gcloud/datastore/helpers.py +++ b/gcloud/datastore/helpers.py @@ -1,4 +1,7 @@ -"""Helper methods for dealing with Cloud Datastore's Protobuf API.""" +"""Helper functions for dealing with Cloud Datastore's Protobuf API. + +These functions are *not* part of the API. +""" import calendar from datetime import datetime, timedelta @@ -16,7 +19,7 @@ def _get_protobuf_attribute_and_value(val): The Protobuf API uses different attribute names based on value types rather than inferring the type. - This method simply determines the proper attribute name + This function simply determines the proper attribute name based on the type of the value provided and returns the attribute name as well as a properly formatted value. @@ -24,7 +27,7 @@ def _get_protobuf_attribute_and_value(val): Certain value types need to be coerced into a different type (such as a `datetime.datetime` into an integer timestamp, or a `gcloud.datastore.key.Key` into a Protobuf representation. - This method handles that for you. + This function handles that for you. For example: @@ -74,7 +77,7 @@ def _get_value_from_protobuf(pb): The Cloud Datastore Protobuf API returns a Property Protobuf which has one value set and the rest blank. - This method retrieves the the one value provided. + This function retrieves the the one value provided. Some work is done to coerce the return value into a more useful type (particularly in the case of a timestamp value, or a key value). From fef83a154d298fdb1bada1e05b2de9c62c5f2a01 Mon Sep 17 00:00:00 2001 From: Tres Seaver Date: Thu, 9 Oct 2014 16:48:27 -0400 Subject: [PATCH 10/10] Rename datastore.helpers -> _helpers. Further emphasize non-API nature. --- gcloud/datastore/{helpers.py => _helpers.py} | 0 gcloud/datastore/connection.py | 4 ++-- gcloud/datastore/entity.py | 4 ++-- gcloud/datastore/query.py | 4 ++-- gcloud/datastore/{test_helpers.py => test__helpers.py} | 6 +++--- 5 files changed, 9 insertions(+), 9 deletions(-) rename gcloud/datastore/{helpers.py => _helpers.py} (100%) rename gcloud/datastore/{test_helpers.py => test__helpers.py} (97%) diff --git a/gcloud/datastore/helpers.py b/gcloud/datastore/_helpers.py similarity index 100% rename from gcloud/datastore/helpers.py rename to gcloud/datastore/_helpers.py diff --git a/gcloud/datastore/connection.py b/gcloud/datastore/connection.py index a43b3860807f..7015d205db45 100644 --- a/gcloud/datastore/connection.py +++ b/gcloud/datastore/connection.py @@ -1,6 +1,6 @@ from gcloud import connection from gcloud.datastore import datastore_v1_pb2 as datastore_pb -from gcloud.datastore import helpers +from gcloud.datastore import _helpers from gcloud.datastore.dataset import Dataset @@ -323,7 +323,7 @@ def save_entity(self, dataset_id, key_pb, properties): prop.name = name # Set the appropriate value. - helpers._set_protobuf_value(prop.value, value) + _helpers._set_protobuf_value(prop.value, value) # If this is in a transaction, we should just return True. The # transaction will handle assigning any keys as necessary. diff --git a/gcloud/datastore/entity.py b/gcloud/datastore/entity.py index be6ac340ffde..034e11f10212 100644 --- a/gcloud/datastore/entity.py +++ b/gcloud/datastore/entity.py @@ -151,13 +151,13 @@ def from_protobuf(cls, pb, dataset=None): # pylint: disable=invalid-name """ # This is here to avoid circular imports. - from gcloud.datastore import helpers + from gcloud.datastore import _helpers key = Key.from_protobuf(pb.key, dataset=dataset) entity = cls.from_key(key) for property_pb in pb.property: - value = helpers._get_value_from_protobuf(property_pb) + value = _helpers._get_value_from_protobuf(property_pb) entity[property_pb.name] = value return entity diff --git a/gcloud/datastore/query.py b/gcloud/datastore/query.py index 2b867b71700f..aeeb6e540d8e 100644 --- a/gcloud/datastore/query.py +++ b/gcloud/datastore/query.py @@ -2,7 +2,7 @@ import copy from gcloud.datastore import datastore_v1_pb2 as datastore_pb -from gcloud.datastore import helpers +from gcloud.datastore import _helpers from gcloud.datastore.entity import Entity from gcloud.datastore.key import Key @@ -131,7 +131,7 @@ def filter(self, expression, value): property_filter.operator = operator # Set the value to filter on based on the type. - helpers._set_protobuf_value(property_filter.value, value) + _helpers._set_protobuf_value(property_filter.value, value) return clone def ancestor(self, ancestor): diff --git a/gcloud/datastore/test_helpers.py b/gcloud/datastore/test__helpers.py similarity index 97% rename from gcloud/datastore/test_helpers.py rename to gcloud/datastore/test__helpers.py index 5065a92b15ca..a31711fd9661 100644 --- a/gcloud/datastore/test_helpers.py +++ b/gcloud/datastore/test__helpers.py @@ -4,7 +4,7 @@ class Test__get_protobuf_attribute_and_value(unittest2.TestCase): def _callFUT(self, val): - from gcloud.datastore.helpers import _get_protobuf_attribute_and_value + from gcloud.datastore._helpers import _get_protobuf_attribute_and_value return _get_protobuf_attribute_and_value(val) @@ -97,7 +97,7 @@ def test_object(self): class Test__get_value_from_protobuf(unittest2.TestCase): def _callFUT(self, pb): - from gcloud.datastore.helpers import _get_value_from_protobuf + from gcloud.datastore._helpers import _get_value_from_protobuf return _get_value_from_protobuf(pb) @@ -176,7 +176,7 @@ def test_unknown(self): class Test_set_protobuf_value(unittest2.TestCase): def _callFUT(self, value_pb, val): - from gcloud.datastore.helpers import _set_protobuf_value + from gcloud.datastore._helpers import _set_protobuf_value return _set_protobuf_value(value_pb, val)