Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add remove_details option
Browse files Browse the repository at this point in the history
DavidMikeSimon committed Dec 19, 2023
1 parent 82fd03b commit 2e6a213
Showing 4 changed files with 42 additions and 6 deletions.
3 changes: 3 additions & 0 deletions vdirsyncer/cli/config.py
Original file line number Diff line number Diff line change
@@ -237,6 +237,9 @@ def __init__(self, full_config: Config, name: str, options: dict[str, str]):
options.pop("conflict_resolution", None)
)

self.required_attendee = options.pop("required_attendee", None)
self.remove_details = options.pop("remove_details", False)

try:
self.collections = options.pop("collections")
except KeyError:
1 change: 1 addition & 0 deletions vdirsyncer/cli/tasks.py
Original file line number Diff line number Diff line change
@@ -79,6 +79,7 @@ def error_callback(e):
force_delete=force_delete,
error_callback=error_callback,
partial_sync=pair.partial_sync,
remove_details=pair.remove_details,
)

if sync_failed:
9 changes: 6 additions & 3 deletions vdirsyncer/sync/__init__.py
Original file line number Diff line number Diff line change
@@ -41,7 +41,7 @@ def __init__(self, storage: Storage, status: SubStatus):
self.status = status
self._item_cache = {} # type: ignore[var-annotated]

async def prepare_new_status(self) -> bool:
async def prepare_new_status(self, remove_details: bool = False) -> bool:
storage_nonempty = False
prefetch = []

@@ -66,6 +66,8 @@ def _store_props(ident: str, props: ItemMetadata) -> None:
# Prefetch items
if prefetch:
async for href, item, etag in self.storage.get_multi(prefetch):
if remove_details:
item = item.without_details()
_store_props(
item.ident,
ItemMetadata(href=href, hash=item.hash, etag=etag),
@@ -104,6 +106,7 @@ async def sync(
force_delete=False,
error_callback=None,
partial_sync="revert",
remove_details: bool=False,
) -> None:
"""Synchronizes two storages.
@@ -145,8 +148,8 @@ async def sync(
a_info = _StorageInfo(storage_a, SubStatus(status, "a"))
b_info = _StorageInfo(storage_b, SubStatus(status, "b"))

a_nonempty = await a_info.prepare_new_status()
b_nonempty = await b_info.prepare_new_status()
a_nonempty = await a_info.prepare_new_status(remove_details=remove_details)
b_nonempty = await b_info.prepare_new_status(remove_details=remove_details)

if status_nonempty and not force_delete:
if a_nonempty and not b_nonempty:
35 changes: 32 additions & 3 deletions vdirsyncer/vobject.py
Original file line number Diff line number Diff line change
@@ -58,6 +58,35 @@ def with_uid(self, new_uid):

return Item("\r\n".join(parsed.dump_lines()))

def without_details(self):
"""Returns a minimal version of this item.
Filters out data to reduce content size and hide private details:
* Description
* Location
* Organizer
* Attendees list
* Redundant timezone data (actual timezone of event is preserved)
"""
parsed = _Component.parse(self.raw)
stack = [parsed]
while stack:
component = stack.pop()

component.subcomponents = [
subcomp for subcomp
in component.subcomponents
if subcomp.name != "VTIMEZONE"
]
for field in ["DESCRIPTION", "ORGANIZER", "ATTENDEE", "LOCATION"]:
# Repeatedly delete because some fields can appear multiple times
while field in component:
del component[field]

stack.extend(component.subcomponents)

return Item("\r\n".join(parsed.dump_lines()))

@cached_property
def raw(self):
"""Raw content of the item, as unicode string.
@@ -241,9 +270,9 @@ class _Component:
Raw outline of the components.
Vdirsyncer's operations on iCalendar and VCard objects are limited to
retrieving the UID and splitting larger files into items. Consequently this
parser is very lazy, with the downside that manipulation of item properties
are extremely costly.
retrieving the UID, removing fields, and splitting larger files into items.
Consequently this parser is very lazy, with the downside that manipulation
of item properties are extremely costly.
Other features:

0 comments on commit 2e6a213

Please sign in to comment.