diff --git a/README.md b/README.md index 56bc98f..63c3b75 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,6 @@ +> ⚠️ **Maintenance Notice:** This is an actively maintained fork of 39aldo39/Radicale-DecSync, updated for compatibility with Python 3.12+ and Radicale 3.x. +> ⚠️ **Disclaimer:** I am not adding functionality. These are bug fix and compatibility releases. Thank you for any input. + Radicale DecSync ================ diff --git a/radicale_storage_decsync/__init__.py b/radicale_storage_decsync/__init__.py index b5e7ba2..73ea089 100644 --- a/radicale_storage_decsync/__init__.py +++ b/radicale_storage_decsync/__init__.py @@ -94,17 +94,26 @@ def resources_listener(path, datetime, key, value, extra): self.load_hrefs(sync_type) def upload(self, href, orig_item, update_decsync=True): - item = super().upload(href, orig_item) + result = super().upload(href, orig_item) + if isinstance(result, tuple): + item = next((x for x in result if hasattr(x, "uid")), result[1]) + else: + item = result if update_decsync: - tag = self.get_meta("tag") - if tag == "VCALENDAR": - supported_components = (self.get_meta("C:supported-calendar-component-set") or "VEVENT,VTODO,VJOURNAL").split(",") - component_name = item.component_name - if len(supported_components) > 1 and component_name != "VEVENT": - raise RuntimeError("Component " + component_name + " is not supported by old DecSync collections. Create a new collection in Radicale for support.") - self.set_href(item.uid, href) - self.decsync.set_entry(["resources", item.uid], None, item.serialize()) - return item + if hasattr(self, 'decsync'): + tag = self.get_meta("tag") + if tag == "VCALENDAR": + supported = (self.get_meta("C:supported-calendar-component-set") or "VEVENT,VTODO,VJOURNAL").split(",") + if len(supported) > 1 and item.component_name != "VEVENT": + raise RuntimeError("Component not supported by old DecSync.") + self.set_href(item.uid, href) + # Ensure structured data (lists/tuples) are stringified before serialization + for component in item.vobject_item.getChildren(): + component_value = getattr(component, 'value', None) + if isinstance(component_value, (list, tuple)): + component.value = ";".join(str(x) for x in component_value) + self.decsync.set_entry(["resources", item.uid], None, item.serialize()) + return result def delete(self, href=None, update_decsync=True): if update_decsync: @@ -157,8 +166,8 @@ def __init__(self, configuration): self.decsync_dir = "" def discover(self, path, depth="0", child_context_manager=( - lambda path, href=None: contextlib.ExitStack())): - collections = list(super().discover(path, depth, child_context_manager)) + lambda path, href=None: contextlib.ExitStack()),user_groups=set()): + collections = list(super().discover(path, depth, child_context_manager, user_groups)) for collection in collections: yield collection @@ -171,7 +180,11 @@ def discover(self, path, depth="0", child_context_manager=( return elif len(attributes) == 1: username = attributes[0] - known_paths = [collection.path for collection in collections] + known_paths = [] + for collection in collections: + if isinstance(collection, tuple): + collection = next((x for x in collection if hasattr(x, "path")), collection[0]) + known_paths.append(collection.path) for sync_type in ["contacts", "calendars", "tasks", "memos"]: for collection in Decsync.list_collections(self.decsync_dir, sync_type): child_path = "/%s/%s-%s/" % (username, sync_type, collection) @@ -193,7 +206,11 @@ def discover(self, path, depth="0", child_context_manager=( props["C:supported-calendar-component-set"] = "VJOURNAL" else: raise RuntimeError("Unknown sync type " + sync_type) - child = super().create_collection(child_path, props=props) + result = super().create_collection(child_path, props=props) + if isinstance(result, tuple): + child = next((x for x in result if hasattr(x, "decsync")), result[0]) + else: + child = result child.decsync.init_stored_entries() child.decsync.execute_stored_entries_for_path_exact(["info"], child) child.decsync.execute_stored_entries_for_path_prefix(["resources"], child) @@ -246,12 +263,16 @@ def create_collection(self, href, items=None, props=None): raise RuntimeError("Unknown tag " + tag) if collection.startswith(sync_type + "-"): - path = "/%s/%s/" % (username, collection) + path = href else: path = "/%s/%s-%s/" % (username, sync_type, collection) - col = super().create_collection(path, None, props) + result = super().create_collection(path, None, props) + if isinstance(result, tuple): + col = next((x for x in result if hasattr(x, "get_href")), result[0]) + else: + col = result if items is not None: for item in items: href = col.get_href(item.uid) - col.upload(href, item) - return col + col.upload(href, item) + return result diff --git a/setup.py b/setup.py index fc2c387..40773d7 100644 --- a/setup.py +++ b/setup.py @@ -4,7 +4,7 @@ setup( name="radicale_storage_decsync", - version="2.1.0", + version="2.1.0+diagonalarg.2", author="Aldo Gunsing", author_email="dev@aldogunsing.nl", url="https://github.com/39aldo39/Radicale-DecSync", @@ -16,7 +16,7 @@ packages=["radicale_storage_decsync"], install_requires=[ "radicale>=3", - "libdecsync>=2.0.0" + "libdecsync @ git+https://github.com/DiagonalArg/libdecsync-bindings-python3.git@master" ], classifiers=[ "Programming Language :: Python :: 3",