Skip to content

Commit

Permalink
Adding _FutureDict type for storage batches.
Browse files Browse the repository at this point in the history
  • Loading branch information
dhermes committed Apr 12, 2015
1 parent 4d2c187 commit 4d263b7
Show file tree
Hide file tree
Showing 4 changed files with 106 additions and 0 deletions.
2 changes: 2 additions & 0 deletions gcloud/storage/_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ def _set_properties(self, value):
:param value: The properties to be set.
"""
self._properties = value
if hasattr(value, 'owner'):
value.owner = self
# If the values are reset, the changes must as well.
self._changes = set()

Expand Down
55 changes: 55 additions & 0 deletions gcloud/storage/batch.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,61 @@ class NoContent(object):
status = 204


class _FutureDict(object):
"""Class to hold a future value for a deferred request.
Used by for requests that get sent in a :class:`Batch`.
:type owner: object
:param owner: Optional. A blob or bucket (or other type) that depends on
this future.
"""

def __init__(self, owner=None):
self.owner = owner

@staticmethod
def get(key, default=None):
"""Stand-in for dict.get.
:type key: object
:param key: Hashable dictionary key.
:type default: object
:param default: Fallback value to dict.get.
:raises: :class:`KeyError` always since the future is intended to fail
as a dictionary.
"""
raise KeyError('Cannot get(%r, default=%r) on a future' % (
key, default))

def __getitem__(self, key):
"""Stand-in for dict[key].
:type key: object
:param key: Hashable dictionary key.
:raises: :class:`KeyError` always since the future is intended to fail
as a dictionary.
"""
raise KeyError('Cannot get item %r from a future' % (key,))

def __setitem__(self, key, value):
"""Stand-in for dict[key] = value.
:type key: object
:param key: Hashable dictionary key.
:type value: object
:param value: Dictionary value.
:raises: :class:`KeyError` always since the future is intended to fail
as a dictionary.
"""
raise KeyError('Cannot set %r -> %r on a future' % (key, value))


class Batch(Connection):
"""Proxy an underlying connection, batching up change operations.
Expand Down
17 changes: 17 additions & 0 deletions gcloud/storage/test__helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,23 @@ def test_path_is_abstract(self):
mixin = self._makeOne()
self.assertRaises(NotImplementedError, lambda: mixin.path)

def test__set_properties_no_future(self):
mixin = self._makeOne()
self.assertEqual(mixin._properties, {})
VALUE = {'foo': 'bar'}
mixin._set_properties(VALUE)
self.assertEqual(mixin._properties, VALUE)
self.assertFalse(hasattr(VALUE, 'owner'))

def test__set_properties_future(self):
from gcloud.storage.batch import _FutureDict
mixin = self._makeOne()
future = _FutureDict()
self.assertEqual(future.owner, None)
mixin._set_properties(future)
self.assertEqual(mixin._properties, future)
self.assertEqual(future.owner, mixin)

def test_reload(self):
connection = _Connection({'foo': 'Foo'})
derived = self._derivedClass(connection, '/path')()
Expand Down
32 changes: 32 additions & 0 deletions gcloud/storage/test_batch.py
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,38 @@ def test_unicode(self):
"""


class Test__FutureDict(unittest2.TestCase):

def _makeOne(self, *args, **kw):
from gcloud.storage.batch import _FutureDict
return _FutureDict(*args, **kw)

def test_ctor_defaults(self):
future = self._makeOne()
self.assertEqual(future.owner, None)

def test_ctor_owner(self):
OWNER = object()
future = self._makeOne(owner=OWNER)
self.assertTrue(future.owner is OWNER)

def test_get(self):
future = self._makeOne()
self.assertRaises(KeyError, future.get, None)

def test___getitem__(self):
future = self._makeOne()
value = orig_value = object()
with self.assertRaises(KeyError):
value = future[None]
self.assertTrue(value is orig_value)

def test___setitem__(self):
future = self._makeOne()
with self.assertRaises(KeyError):
future[None] = None


class _Connection(object):

project = 'TESTING'
Expand Down

0 comments on commit 4d263b7

Please sign in to comment.