mirror of
https://github.com/samsonjs/vdirsyncer.git
synced 2026-04-27 14:57:41 +00:00
API change to use only UIDs
This commit is contained in:
parent
32b0ac5a6b
commit
e03a677df4
4 changed files with 55 additions and 66 deletions
|
|
@ -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):
|
||||||
|
if self._uid is None:
|
||||||
for line in self.raw.splitlines():
|
for line in self.raw.splitlines():
|
||||||
if line.startswith(b'UID'):
|
if line.startswith(b'UID'):
|
||||||
return line.lstrip(b'UID:').strip()
|
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()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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)
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue