API change to use only UIDs

This commit is contained in:
Markus Unterwaditzer 2014-02-15 12:10:30 +01:00
parent 32b0ac5a6b
commit e03a677df4
4 changed files with 55 additions and 66 deletions

View file

@ -1,14 +1,16 @@
class Item(object): class Item(object):
'''wrapper class for VCALENDAR and VCARD''' '''should-be-immutable wrapper class for VCALENDAR and VCARD'''
def __init__(self, raw): def __init__(self, raw):
self.raw = raw self.raw = raw
self._uid = None self._uid = None
@property @property
def uid(self): def uid(self):
for line in self.raw.splitlines(): if self._uid is None:
if line.startswith(b'UID'): for line in self.raw.splitlines():
return line.lstrip(b'UID:').strip() if line.startswith(b'UID'):
self._uid = line.lstrip(b'UID:').strip()
return self._uid
class Storage(object): class Storage(object):
@ -18,18 +20,18 @@ class Storage(object):
def list_items(self): def list_items(self):
''' '''
:returns: list of (href, etag) :returns: list of (uid, etag)
''' '''
raise NotImplementedError() raise NotImplementedError()
def get_items(self, hrefs): def get_items(self, uids):
''' '''
:param hrefs: list of hrefs to fetch :param uids: list of uids to fetch
:returns: list of (object, href, etag) :returns: list of (object, uid, etag)
''' '''
raise NotImplementedError() raise NotImplementedError()
def item_exists(self, href): def item_exists(self, uid):
''' '''
check if item exists check if item exists
:returns: True or False :returns: True or False
@ -40,7 +42,7 @@ class Storage(object):
''' '''
Upload a new object, raise Upload a new object, raise
:exc:`vdirsyncer.exceptions.AlreadyExistingError` if it already exists. :exc:`vdirsyncer.exceptions.AlreadyExistingError` if it already exists.
:returns: (href, etag) :returns: (uid, etag)
''' '''
raise NotImplementedError() raise NotImplementedError()

View file

@ -7,46 +7,40 @@ class FilesystemStorage(Storage):
self.path = path self.path = path
super(FilesystemStorage, self).__init__(**kwargs) super(FilesystemStorage, self).__init__(**kwargs)
def _get_etag(self, href): def _get_filepath(self, uid):
return os.path.getmtime(href) return os.path.join(self.path, uid + self.fileext)
def _get_href(self, obj):
return os.path.join(self.path, obj.uid + self.fileext)
def _get_hrefs(self):
for fname in os.listdir(self.path):
href = os.path.join(self.path, fname)
if os.path.isfile(href):
yield href
def list_items(self): def list_items(self):
for href in self._get_hrefs(): for fname in os.listdir(self.path):
yield href, self._get_etag(href) fpath = os.path.join(self.path, fname)
if os.path.isfile(fpath) and fname.endswith(self.fileext):
uid = fname[:-len(self.fileext)]
yield uid, os.path.getmtime(fpath)
def get_items(self, hrefs): def get_items(self, uids):
for href in hrefs: for uid in uids:
with open(href, 'rb') as f: fpath = self._get_filepath(uid)
yield Item(f.read()), href, self._get_etag(href) with open(fpath, 'rb') as f:
yield Item(f.read()), uid, os.path.getmtime(fpath)
def item_exists(self, href): def item_exists(self, uid):
return os.path.isfile(path) return os.path.isfile(self._get_filepath(uid))
def upload(self, obj): def upload(self, obj):
href = self._get_href(obj) fpath = self._get_filepath(obj.uid)
if os.path.exists(href): if os.path.exists(fpath):
raise exceptions.AlreadyExistingError(href) raise exceptions.AlreadyExistingError(obj.uid)
with open(href, 'wb+') as f: with open(fpath, 'wb+') as f:
f.write(obj.raw) f.write(obj.raw)
return href, self._get_etag(href) return obj.uid, os.path.getmtime(fpath)
def update(self, obj, etag): def update(self, obj, etag):
href = self._get_href(obj) fpath = self._get_filepath(obj)
actual_etag = self._get_etag(href) if not os.path.exists(fpath):
raise exceptions.NotFoundError(href)
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)
if not os.path.exists(href): with open(fpath, 'wb') as f:
raise exceptions.NotFoundError(href)
with open(href, 'wb') as f:
f.write(obj.raw) f.write(obj.raw)
return os.path.getmtime(fpath)
return self._get_etag(href)

View file

@ -4,36 +4,31 @@ import vdirsyncer.exceptions as exceptions
class MemoryStorage(Storage): class MemoryStorage(Storage):
def __init__(self, **kwargs): def __init__(self, **kwargs):
self.items = {} # href => (etag, object) self.items = {} # uid => (etag, object)
super(MemoryStorage, self).__init__(**kwargs) super(MemoryStorage, self).__init__(**kwargs)
def _get_href(self, obj):
return obj.uid + self.fileext
def list_items(self): def list_items(self):
for href, (etag, obj) in self.items.items(): for uid, (etag, obj) in self.items.items():
yield href, etag yield uid, etag
def get_items(self, hrefs): def get_items(self, uids):
for href in hrefs: for uid in uids:
etag, obj = self.items[href] etag, obj = self.items[uid]
return obj, href, etag return obj, uid, etag
def item_exists(self, href): def item_exists(self, uid):
return href in self.items return uid in self.items
def upload(self, obj): def upload(self, obj):
href = self._get_href(obj) if obj.uid in self.items:
if href in self.items:
raise exceptions.AlreadyExistingError(obj) raise exceptions.AlreadyExistingError(obj)
etag = datetime.datetime.now() etag = datetime.datetime.now()
self.items[href] = (etag, obj) self.items[obj.uid] = (etag, obj)
return href, etag return obj.uid, etag
def update(self, obj, etag): def update(self, obj, etag):
href = self._get_href(obj) if obj.uid not in self.items:
if href not in self.items:
raise exceptions.NotFoundError(obj) raise exceptions.NotFoundError(obj)
etag = datetime.datetime.now() etag = datetime.datetime.now()
self.items[href] = (etag, obj) self.items[obj.uid] = (etag, obj)
return href, etag return obj.uid, etag

View file

@ -22,14 +22,12 @@ class StorageTests(object):
'UID:8', 'UID:8',
'UID:9' 'UID:9'
] ]
fileext = '' fileext = '.lol'
s = self._get_storage(fileext=fileext) s = self._get_storage(fileext=fileext)
for item in items: for item in items:
s.upload(Item(item)) s.upload(Item(item))
hrefs = [href for href, etag in s.list_items()] a = set(uid for uid, etag in s.list_items())
prefix = os.path.commonprefix(hrefs) b = set(str(y) for y in range(1, 10))
a = set(x[len(prefix):] for x in hrefs)
b = set(str(y) + fileext for y in range(1, 10))
assert a == b assert a == b