Storage API improvements

This commit is contained in:
Markus Unterwaditzer 2014-02-16 15:35:51 +01:00
parent ca92d9a428
commit 473596a573
3 changed files with 44 additions and 25 deletions

View file

@ -29,20 +29,28 @@ class Storage(object):
self.fileext = fileext self.fileext = fileext
self.item_class = item_class self.item_class = item_class
def list_items(self): def list(self):
''' '''
:returns: list of (uid, etag) :returns: list of (uid, etag)
''' '''
raise NotImplementedError() raise NotImplementedError()
def get_items(self, uids): def get(self, uid):
''' '''
:param uids: list of uids to fetch :param uid: uid to fetch
:returns: list of (object, uid, etag) :returns: (object, uid, etag)
''' '''
raise NotImplementedError() raise NotImplementedError()
def item_exists(self, uid): def get_multi(self, uids):
'''
:param uids: list of uids to fetch
:returns: iterable of (object, uid, etag)
'''
for uid in uids:
yield self.get(uid)
def has(self, uid):
''' '''
check if item exists check if item exists
:returns: True or False :returns: True or False
@ -67,8 +75,9 @@ class Storage(object):
''' '''
raise NotImplementedError() raise NotImplementedError()
def delete(self, uid): def delete(self, uid, etag):
''' '''
Delete the object, raise exceptions on error, no return value Delete the object, raise exceptions when etag doesn't match, no return
value
''' '''
raise NotImplementedError() raise NotImplementedError()

View file

@ -23,20 +23,19 @@ class FilesystemStorage(Storage):
def _get_filepath(self, uid): def _get_filepath(self, uid):
return os.path.join(self.path, uid + self.fileext) return os.path.join(self.path, uid + self.fileext)
def list_items(self): def list(self):
for fname in os.listdir(self.path): for fname in os.listdir(self.path):
fpath = os.path.join(self.path, fname) fpath = os.path.join(self.path, fname)
if os.path.isfile(fpath) and fname.endswith(self.fileext): if os.path.isfile(fpath) and fname.endswith(self.fileext):
uid = fname[:-len(self.fileext)] uid = fname[:-len(self.fileext)]
yield uid, os.path.getmtime(fpath) yield uid, os.path.getmtime(fpath)
def get_items(self, uids): def get(self, uid):
for uid in uids: fpath = self._get_filepath(uid)
fpath = self._get_filepath(uid) with open(fpath, 'rb') as f:
with open(fpath, 'rb') as f: return Item(f.read()), uid, os.path.getmtime(fpath)
yield Item(f.read()), uid, os.path.getmtime(fpath)
def item_exists(self, uid): def has(self, uid):
return os.path.isfile(self._get_filepath(uid)) return os.path.isfile(self._get_filepath(uid))
def upload(self, obj): def upload(self, obj):
@ -54,9 +53,13 @@ class FilesystemStorage(Storage):
actual_etag = os.path.getmtime(fpath) actual_etag = os.path.getmtime(fpath)
if etag != actual_etag: if etag != actual_etag:
raise exceptions.WrongEtagError(etag, actual_etag) raise exceptions.WrongEtagError(etag, actual_etag)
with open(fpath, 'wb') as f: with open(fpath, 'wb') as f:
f.write(obj.raw) f.write(obj.raw)
return os.path.getmtime(fpath) return os.path.getmtime(fpath)
def delete(self, uid): def delete(self, uid, etag):
os.remove(self._get_filepath(uid)) fpath = self._get_filepath(uid)
if etag != os.path.getmtime(fpath):
raise exceptions.WrongEtagError(etag, actual_etag)
os.remove(fpath)

View file

@ -19,16 +19,15 @@ class MemoryStorage(Storage):
self.items = {} # uid => (etag, object) self.items = {} # uid => (etag, object)
super(MemoryStorage, self).__init__(**kwargs) super(MemoryStorage, self).__init__(**kwargs)
def list_items(self): def list(self):
for uid, (etag, obj) in self.items.items(): for uid, (etag, obj) in self.items.items():
yield uid, etag yield uid, etag
def get_items(self, uids): def get(self, uid):
for uid in uids: etag, obj = self.items[uid]
etag, obj = self.items[uid] return obj, uid, etag
yield obj, uid, etag
def item_exists(self, uid): def has(self, uid):
return uid in self.items return uid in self.items
def upload(self, obj): def upload(self, obj):
@ -41,9 +40,17 @@ class MemoryStorage(Storage):
def update(self, obj, etag): def update(self, obj, etag):
if obj.uid not in self.items: if obj.uid not in self.items:
raise exceptions.NotFoundError(obj) raise exceptions.NotFoundError(obj)
etag = datetime.datetime.now() actual_etag, _ = self.items[obj.uid]
self.items[obj.uid] = (etag, obj) if etag != actual_etag:
raise exceptions.WrongEtagError(etag, actual_etag)
new_etag = datetime.datetime.now()
self.items[obj.uid] = (new_etag, obj)
return etag return etag
def delete(self, uid): def delete(self, uid, etag):
if not self.has(uid):
raise exceptions.NotFoundError(uid)
if etag != self.items[uid][0]:
raise exceptions.WrongEtagError(etag)
del self.items[uid] del self.items[uid]