diff --git a/tests/unit/utils/test_vobject.py b/tests/unit/utils/test_vobject.py index 6d86921..4660f2a 100644 --- a/tests/unit/utils/test_vobject.py +++ b/tests/unit/utils/test_vobject.py @@ -235,7 +235,7 @@ def test_broken_item(): assert 'Parsing error at line 1' in str(excinfo.value) item = vobject.Item('END:FOO') - assert item.parsed is None + assert not item.is_parseable def test_multiple_items(): diff --git a/vdirsyncer/repair.py b/vdirsyncer/repair.py index 0a775ee..022dccd 100644 --- a/vdirsyncer/repair.py +++ b/vdirsyncer/repair.py @@ -40,7 +40,7 @@ def repair_storage(storage, repair_unsafe_uid): def repair_item(href, item, seen_uids, repair_unsafe_uid): - if item.parsed is None: + if not item.is_parseable: raise IrreparableItem() new_item = item diff --git a/vdirsyncer/sync/__init__.py b/vdirsyncer/sync/__init__.py index e899868..7a35389 100644 --- a/vdirsyncer/sync/__init__.py +++ b/vdirsyncer/sync/__init__.py @@ -27,6 +27,7 @@ sync_logger = logging.getLogger(__name__) class _StorageInfo(object): '''A wrapper class that holds prefetched items, the status and other things.''' + def __init__(self, storage, status): self.storage = storage self.status = status @@ -57,6 +58,12 @@ class _StorageInfo(object): # Prefetch items for href, item, etag in (self.storage.get_multi(prefetch) if prefetch else ()): + if not item.is_parseable: + sync_logger.warning( + 'Storage "{}": item {} is malformed. ' + 'Please try to repair it.' + .format(self.storage.instance_name, href) + ) _store_props(item.ident, ItemMetadata( href=href, hash=item.hash, @@ -122,9 +129,9 @@ def sync(storage_a, storage_b, status, conflict_resolution=None, raise BothReadOnly() if conflict_resolution == 'a wins': - conflict_resolution = lambda a, b: a + def conflict_resolution(a, b): return a elif conflict_resolution == 'b wins': - conflict_resolution = lambda a, b: b + def conflict_resolution(a, b): return b status_nonempty = bool(next(status.iter_old(), None)) diff --git a/vdirsyncer/vobject.py b/vdirsyncer/vobject.py index bba9b3a..fa161ee 100644 --- a/vdirsyncer/vobject.py +++ b/vdirsyncer/vobject.py @@ -32,6 +32,10 @@ class Item(object): native.change_uid(new_c, new_uid or '') return Item(native.write_component(new_c), component=new_c) + @property + def is_parseable(self): + return bool(self._component) + @property def raw(self): '''Raw content of the item, as unicode string. @@ -70,15 +74,6 @@ class Item(object): # 2. The status file would contain really sensitive information. return self.uid or self.hash - @property - def parsed(self): - '''Don't cache because the rv is mutable.''' - # FIXME: remove - try: - return _Component.parse(self.raw) - except Exception: - return None - @property def is_valid(self): return bool(self._component)