mirror of
https://github.com/samsonjs/vdirsyncer.git
synced 2026-04-27 14:57:41 +00:00
Make etags always strings.
This somewhat helps with environments where ducktyping is not an option (e.g. databases)
This commit is contained in:
parent
08d3a6f2e0
commit
3670bed66d
4 changed files with 22 additions and 9 deletions
|
|
@ -41,6 +41,8 @@ class StorageTests(object):
|
||||||
hrefs.sort()
|
hrefs.sort()
|
||||||
assert hrefs == sorted(s.list())
|
assert hrefs == sorted(s.list())
|
||||||
for href, etag in hrefs:
|
for href, etag in hrefs:
|
||||||
|
assert isinstance(href, (str, unicode))
|
||||||
|
assert isinstance(etag, (str, unicode))
|
||||||
assert s.has(href)
|
assert s.has(href)
|
||||||
obj, etag2 = s.get(href)
|
obj, etag2 = s.get(href)
|
||||||
assert etag == etag2
|
assert etag == etag2
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,9 @@ class Storage(object):
|
||||||
- ETAG: Checksum of item, or something similar that changes when the
|
- ETAG: Checksum of item, or something similar that changes when the
|
||||||
object does.
|
object does.
|
||||||
|
|
||||||
|
All of the above properties should be strings. If bytestrings, an ASCII
|
||||||
|
encoding is assumed.
|
||||||
|
|
||||||
:param collection: If None, the given URL or path is already directly
|
:param collection: If None, the given URL or path is already directly
|
||||||
referring to a collection. Otherwise it will be treated as a basepath
|
referring to a collection. Otherwise it will be treated as a basepath
|
||||||
to many collections (e.g. a vdir) and the given collection name will be
|
to many collections (e.g. a vdir) and the given collection name will be
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,10 @@ import vdirsyncer.log as log
|
||||||
logger = log.get('storage.filesystem')
|
logger = log.get('storage.filesystem')
|
||||||
|
|
||||||
|
|
||||||
|
def _get_etag(fpath):
|
||||||
|
return '{:.9f}'.format(os.path.getmtime(fpath))
|
||||||
|
|
||||||
|
|
||||||
class FilesystemStorage(Storage):
|
class FilesystemStorage(Storage):
|
||||||
|
|
||||||
'''Saves data in vdir collection
|
'''Saves data in vdir collection
|
||||||
|
|
@ -61,13 +65,13 @@ class FilesystemStorage(Storage):
|
||||||
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):
|
||||||
yield fname, os.path.getmtime(fpath)
|
yield fname, _get_etag(fpath)
|
||||||
|
|
||||||
def get(self, href):
|
def get(self, href):
|
||||||
fpath = self._get_filepath(href)
|
fpath = self._get_filepath(href)
|
||||||
with open(fpath, 'rb') as f:
|
with open(fpath, 'rb') as f:
|
||||||
return (Item(f.read().decode(self.encoding)),
|
return (Item(f.read().decode(self.encoding)),
|
||||||
os.path.getmtime(fpath))
|
_get_etag(fpath))
|
||||||
|
|
||||||
def has(self, href):
|
def has(self, href):
|
||||||
return os.path.isfile(self._get_filepath(href))
|
return os.path.isfile(self._get_filepath(href))
|
||||||
|
|
@ -79,7 +83,7 @@ class FilesystemStorage(Storage):
|
||||||
raise exceptions.AlreadyExistingError(obj.uid)
|
raise exceptions.AlreadyExistingError(obj.uid)
|
||||||
with open(fpath, 'wb+') as f:
|
with open(fpath, 'wb+') as f:
|
||||||
f.write(obj.raw.encode(self.encoding))
|
f.write(obj.raw.encode(self.encoding))
|
||||||
return href, os.path.getmtime(fpath)
|
return href, _get_etag(fpath)
|
||||||
|
|
||||||
def update(self, href, obj, etag):
|
def update(self, href, obj, etag):
|
||||||
fpath = self._get_filepath(href)
|
fpath = self._get_filepath(href)
|
||||||
|
|
@ -88,19 +92,19 @@ class FilesystemStorage(Storage):
|
||||||
.format(href, obj.uid))
|
.format(href, obj.uid))
|
||||||
if not os.path.exists(fpath):
|
if not os.path.exists(fpath):
|
||||||
raise exceptions.NotFoundError(obj.uid)
|
raise exceptions.NotFoundError(obj.uid)
|
||||||
actual_etag = os.path.getmtime(fpath)
|
actual_etag = _get_etag(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.encode('utf-8'))
|
f.write(obj.raw.encode('utf-8'))
|
||||||
return os.path.getmtime(fpath)
|
return _get_etag(fpath)
|
||||||
|
|
||||||
def delete(self, href, etag):
|
def delete(self, href, etag):
|
||||||
fpath = self._get_filepath(href)
|
fpath = self._get_filepath(href)
|
||||||
if not os.path.isfile(fpath):
|
if not os.path.isfile(fpath):
|
||||||
raise exceptions.NotFoundError(href)
|
raise exceptions.NotFoundError(href)
|
||||||
actual_etag = os.path.getmtime(fpath)
|
actual_etag = _get_etag(fpath)
|
||||||
if etag != actual_etag:
|
if etag != actual_etag:
|
||||||
raise exceptions.WrongEtagError(etag, actual_etag)
|
raise exceptions.WrongEtagError(etag, actual_etag)
|
||||||
os.remove(fpath)
|
os.remove(fpath)
|
||||||
|
|
|
||||||
|
|
@ -7,11 +7,15 @@
|
||||||
:license: MIT, see LICENSE for more details.
|
:license: MIT, see LICENSE for more details.
|
||||||
'''
|
'''
|
||||||
|
|
||||||
import datetime
|
import random
|
||||||
from vdirsyncer.storage.base import Storage
|
from vdirsyncer.storage.base import Storage
|
||||||
import vdirsyncer.exceptions as exceptions
|
import vdirsyncer.exceptions as exceptions
|
||||||
|
|
||||||
|
|
||||||
|
def _get_etag():
|
||||||
|
return '{:.9f}'.format(random.random())
|
||||||
|
|
||||||
|
|
||||||
class MemoryStorage(Storage):
|
class MemoryStorage(Storage):
|
||||||
|
|
||||||
'''
|
'''
|
||||||
|
|
@ -37,7 +41,7 @@ class MemoryStorage(Storage):
|
||||||
href = self._get_href(obj.uid)
|
href = self._get_href(obj.uid)
|
||||||
if href in self.items:
|
if href in self.items:
|
||||||
raise exceptions.AlreadyExistingError(obj.uid)
|
raise exceptions.AlreadyExistingError(obj.uid)
|
||||||
etag = datetime.datetime.now()
|
etag = _get_etag()
|
||||||
self.items[href] = (etag, obj)
|
self.items[href] = (etag, obj)
|
||||||
return href, etag
|
return href, etag
|
||||||
|
|
||||||
|
|
@ -48,7 +52,7 @@ class MemoryStorage(Storage):
|
||||||
if etag != actual_etag:
|
if etag != actual_etag:
|
||||||
raise exceptions.WrongEtagError(etag, actual_etag)
|
raise exceptions.WrongEtagError(etag, actual_etag)
|
||||||
|
|
||||||
new_etag = datetime.datetime.now()
|
new_etag = _get_etag()
|
||||||
self.items[href] = (new_etag, obj)
|
self.items[href] = (new_etag, obj)
|
||||||
return new_etag
|
return new_etag
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue