diff --git a/gcloud/datastore/query.py b/gcloud/datastore/query.py index 4b67333b3cbe..69296e0b6b51 100644 --- a/gcloud/datastore/query.py +++ b/gcloud/datastore/query.py @@ -308,3 +308,31 @@ def fetch(self, limit=None): return [Entity.from_protobuf(entity, dataset=self.dataset()) for entity in entity_pbs] + + def order(self, *properties): + """Adds a sort order to the query. + + Sort fields will be applied in the order specified. + + :type properties: sequence of strings + :param properties: Each value is a string giving the name of the property + on which to sort, optionally preceded by a hyphen + (-) to specify descending order. + Omitting the hyphen implies ascending order. + + :rtype: :class:`Query` + :returns: A new Query instance, ordered as specified. + """ + clone = self._clone() + + for p in properties: + property_order = clone._pb.order.add() + + if p.startswith('-'): + property_order.property.name = p[1:] + property_order.direction = property_order.DESCENDING + else: + property_order.property.name = p + property_order.direction = property_order.ASCENDING + + return clone diff --git a/gcloud/datastore/test_query.py b/gcloud/datastore/test_query.py index 3d350625b762..b3f853b32569 100644 --- a/gcloud/datastore/test_query.py +++ b/gcloud/datastore/test_query.py @@ -225,6 +225,50 @@ def test_fetch_explicit_limit(self): 'query_pb': limited.to_protobuf(), }) + def test_order_empty(self): + _KIND = 'KIND' + before = self._makeOne(_KIND) + after = before.order() + self.assertFalse(after is before) + self.assertTrue(isinstance(after, self._getTargetClass())) + self.assertEqual(before.to_protobuf(), after.to_protobuf()) + + def test_order_single_asc(self): + _KIND = 'KIND' + before = self._makeOne(_KIND) + after = before.order('field') + after_pb = after.to_protobuf() + order_pb = list(after_pb.order) + self.assertEqual(len(order_pb), 1) + prop_pb = order_pb[0] + self.assertEqual(prop_pb.property.name, 'field') + self.assertEqual(prop_pb.direction, prop_pb.ASCENDING) + + def test_order_single_desc(self): + _KIND = 'KIND' + before = self._makeOne(_KIND) + after = before.order('-field') + after_pb = after.to_protobuf() + order_pb = list(after_pb.order) + self.assertEqual(len(order_pb), 1) + prop_pb = order_pb[0] + self.assertEqual(prop_pb.property.name, 'field') + self.assertEqual(prop_pb.direction, prop_pb.DESCENDING) + + def test_order_multiple(self): + _KIND = 'KIND' + before = self._makeOne(_KIND) + after = before.order('foo', '-bar') + after_pb = after.to_protobuf() + order_pb = list(after_pb.order) + self.assertEqual(len(order_pb), 2) + prop_pb = order_pb[0] + self.assertEqual(prop_pb.property.name, 'foo') + self.assertEqual(prop_pb.direction, prop_pb.ASCENDING) + prop_pb = order_pb[1] + self.assertEqual(prop_pb.property.name, 'bar') + self.assertEqual(prop_pb.direction, prop_pb.DESCENDING) + class _Dataset(object):