Add filesystem storage

This commit is contained in:
Markus Unterwaditzer 2014-02-15 09:20:19 +01:00
parent be81b48060
commit 34e2c8e9dd
3 changed files with 79 additions and 2 deletions

8
vdirsyncer/exceptions.py Normal file
View file

@ -0,0 +1,8 @@
class Error(Exception):
pass
class AlreadyExistingError(Error):
pass
class WrongEtagError(Error):
pass

View file

@ -1,4 +1,21 @@
class Syncer(object):
class Item(object):
'''wrapper class for VCALENDAR and VCARD'''
def __init__(self, raw):
self.raw = raw
self._uid = None
@property
def uid(self):
for line in raw.splitlines():
if line.startswith(b'UID'):
return line.lstrip(b'UID:').strip()
class Storage(object):
def __init__(self, fileext, item_class=Item):
self.fileext = fileext
self.item_class = item_class
def list_items(self):
'''
:returns: list of (href, etag)
@ -15,12 +32,14 @@ class Syncer(object):
def item_exists(self, href):
'''
check if item exists
:returns: True or False
'''
raise NotImplementedError()
def upload(self, obj):
'''
Upload a new object, raise error if it already exists.
Upload a new object, raise
:exc:`vdirsyncer.exceptions.AlreadyExistingError` if it already exists.
:returns: (href, etag)
'''
raise NotImplementedError()

View file

@ -0,0 +1,50 @@
import os
from vdirsyncer.storage.base import Storage, Item
from vdirsyncer.exceptions import AlreadyExistingError
class FilesystemStorage(Storage):
def __init__(self, path, **kwargs):
self.path = path
super(FilesystemStorage, self).__init__(**kwargs)
def _get_etag(self, href):
return os.path.getmtime(href)
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):
for href in self._get_hrefs():
yield href, self._get_etag(href)
def get_items(self, hrefs):
for href in hrefs:
with open(href, 'rb') as f:
yield Item(f.read()), href, self._get_etag(href)
def item_exists(self, href):
return os.path.isfile(path)
def _get_href(self, obj):
return os.path.join(self.path, obj.uid + b'b' + self.fileext)
def upload(self, obj):
href = self._get_href(obj)
if os.path.exists(href):
raise AlreadyExistingError(href)
with open(href, 'wb+') as f:
f.write(obj.raw)
return href, self._get_etag(href)
def update(self, obj, etag):
href = self._get_href(obj)
actual_etag = self._get_etag(href)
if etag != actual_etag:
raise WrongEtagError(etag, actual_etag)
with open(href, 'wb') as f:
f.write(obj.raw)
return self._get_etag(href)