From 08380c199e8e9cada359d64f9aeab7168b9ace68 Mon Sep 17 00:00:00 2001 From: Markus Unterwaditzer Date: Sat, 31 Jan 2015 10:08:02 +0100 Subject: [PATCH] More performance improvements to singlefile --- CHANGELOG.rst | 2 ++ tests/__init__.py | 9 +-------- vdirsyncer/storage/singlefile.py | 14 +++++++------- vdirsyncer/utils/vobject.py | 15 +++++---------- 4 files changed, 15 insertions(+), 25 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index e4eae80..3e8c629 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -14,6 +14,8 @@ Version 0.4.3 *yet to be released* +- More performance improvements to ``singlefile``-storage. + Version 0.4.2 ============= diff --git a/tests/__init__.py b/tests/__init__.py index 9e53dda..b1202de 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -4,20 +4,13 @@ Test suite for vdirsyncer. ''' from vdirsyncer.utils.compat import text_type -from vdirsyncer.utils.vobject import normalize_item as _normalize_item +from vdirsyncer.utils.vobject import normalize_item def blow_up(*a, **kw): raise AssertionError('Did not expect to be called.') -def normalize_item(item): - if not isinstance(item, text_type): - item = item.raw - return tuple(sorted(_normalize_item( - item, use_icalendar=False).splitlines())) - - def assert_item_equals(a, b): assert normalize_item(a) == normalize_item(b) diff --git a/vdirsyncer/storage/singlefile.py b/vdirsyncer/storage/singlefile.py index 4a781c3..f08d4c2 100644 --- a/vdirsyncer/storage/singlefile.py +++ b/vdirsyncer/storage/singlefile.py @@ -16,9 +16,11 @@ from ..utils.vobject import join_collection, split_collection logger = log.get(__name__) -def _write_after(f): +def _writing_op(f): @functools.wraps(f) def inner(self, *args, **kwargs): + if not self._at_once: + self.list() rv = f(self, *args, **kwargs) if not self._at_once: self._write() @@ -130,19 +132,17 @@ class SingleFileStorage(Storage): except KeyError: raise exceptions.NotFoundError(href) - @_write_after + @_writing_op def upload(self, item): href = item.ident - self.list() if href in self._items: raise exceptions.AlreadyExistingError(href) self._items[href] = item, item.hash return href, item.hash - @_write_after + @_writing_op def update(self, href, item, etag): - self.list() if href not in self._items: raise exceptions.NotFoundError(href) @@ -153,9 +153,8 @@ class SingleFileStorage(Storage): self._items[href] = item, item.hash return item.hash - @_write_after + @_writing_op def delete(self, href, etag): - self.list() if href not in self._items: raise exceptions.NotFoundError(href) @@ -182,6 +181,7 @@ class SingleFileStorage(Storage): @contextlib.contextmanager def at_once(self): + self.list() self._at_once = True try: yield self diff --git a/vdirsyncer/utils/vobject.py b/vdirsyncer/utils/vobject.py index 4b24053..8aa59f8 100644 --- a/vdirsyncer/utils/vobject.py +++ b/vdirsyncer/utils/vobject.py @@ -19,7 +19,6 @@ def _process_properties(*s): return tuple(rv) - IGNORE_PROPS = _process_properties( # PRODID is changed by radicale for some reason after upload 'PRODID', @@ -32,6 +31,8 @@ IGNORE_PROPS = _process_properties( # item does -- however, we can determine that ourselves 'REV' ) +del _process_properties + # Whether the installed icalendar version has # https://github.com/collective/icalendar/pull/136 @@ -107,18 +108,12 @@ class Item(object): return None -def normalize_item(item, ignore_props=IGNORE_PROPS, use_icalendar=True): +def normalize_item(item, ignore_props=IGNORE_PROPS): + '''Create syntactically invalid mess that is equal for similar items.''' if not isinstance(item, Item): item = Item(item) - if use_icalendar and item.parsed is not None: - # We have to explicitly check "is not None" here because VCALENDARS - # with only subcomponents and no own properties are also false-ish. - lines = to_unicode_lines(item.parsed) - else: - lines = sorted(item.raw.splitlines()) - return u'\r\n'.join(line.strip() - for line in lines + for line in sorted(item.raw.splitlines()) if line.strip() and not line.startswith(IGNORE_PROPS))