Skip to content

Commit

Permalink
Ensuring query constructor args are correct types.
Browse files Browse the repository at this point in the history
Fixes #887.
  • Loading branch information
dhermes committed May 20, 2015
1 parent 6bc4e02 commit 301378f
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 3 deletions.
29 changes: 26 additions & 3 deletions gcloud/datastore/query.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,9 +90,32 @@ def __init__(self,
self._namespace = namespace
self._ancestor = ancestor
self._filters = list(filters)
self._projection = list(projection)
self._order = list(order)
self._group_by = list(group_by)
self._projection = self._ensure_tuple_or_list('projection', projection)
self._order = self._ensure_tuple_or_list('order', order)
self._group_by = self._ensure_tuple_or_list('group_by', group_by)

@staticmethod
def _ensure_tuple_or_list(arg_name, tuple_or_list):
"""Ensures an input is a tuple or list.
This effectively reduces the iterable types allowed to a very short
whitelist: list and tuple.
:type arg_name: string
:param arg_name: Name of argument to use in error message.
:type tuple_or_list: sequence of string
:param tuple_or_list: Sequence to be verified.
:rtype: list of string
:returns: The ``tuple_or_list`` passed in cast to a ``list``.
:raises: class:`TypeError` if the ``tuple_or_list`` is not a tuple or
list.
"""
if not isinstance(tuple_or_list, (tuple, list)):
raise TypeError('Expected %s to be a tuple or list. '
'Received %r' % (arg_name, tuple_or_list))
return list(tuple_or_list)

@property
def dataset_id(self):
Expand Down
21 changes: 21 additions & 0 deletions gcloud/datastore/test_query.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,27 @@ def test_ctor_explicit(self):
self.assertEqual(query.order, ORDER)
self.assertEqual(query.group_by, GROUP_BY)

def test_ctor_bad_projection(self):
_DATASET = 'DATASET'
_KIND = 'KIND'
BAD_PROJECTION = object()
self.assertRaises(TypeError, self._makeOne, _KIND, _DATASET,
projection=BAD_PROJECTION)

def test_ctor_bad_order(self):
_DATASET = 'DATASET'
_KIND = 'KIND'
BAD_ORDER = object()
self.assertRaises(TypeError, self._makeOne, _KIND, _DATASET,
order=BAD_ORDER)

def test_ctor_bad_group_by(self):
_DATASET = 'DATASET'
_KIND = 'KIND'
BAD_GROUP_BY = object()
self.assertRaises(TypeError, self._makeOne, _KIND, _DATASET,
group_by=BAD_GROUP_BY)

def test_namespace_setter_w_non_string(self):
_DATASET = 'DATASET'
query = self._makeOne(dataset_id=_DATASET)
Expand Down

0 comments on commit 301378f

Please sign in to comment.