From b4230c424926be0ebca25135231b78f54a40c7ec Mon Sep 17 00:00:00 2001 From: Unrud Date: Fri, 17 Jan 2020 05:00:31 +0100 Subject: [PATCH] Extract method prepare --- radicale/app/put.py | 189 ++++++++++++++++++++++---------------------- 1 file changed, 96 insertions(+), 93 deletions(-) diff --git a/radicale/app/put.py b/radicale/app/put.py index 2996a3fc..1336b96e 100644 --- a/radicale/app/put.py +++ b/radicale/app/put.py @@ -31,6 +31,96 @@ from radicale import pathutils, storage, xmlutils from radicale.log import logger +def prepare(vobject_items, path, content_type, permissions, parent_permissions, + tag=None, write_whole_collection=None): + if (write_whole_collection or + permissions and not parent_permissions): + write_whole_collection = True + tags = {value: key + for key, value in xmlutils.MIMETYPES.items()} + tag = radicale_item.predict_tag_of_whole_collection( + vobject_items, tags.get(content_type)) + if not tag: + raise ValueError("Can't determine collection tag") + collection_path = pathutils.strip_path(path) + elif (write_whole_collection is not None and + not write_whole_collection or + not permissions and parent_permissions): + write_whole_collection = False + if tag is None: + tag = radicale_item.predict_tag_of_parent_collection( + vobject_items) + collection_path = posixpath.dirname( + pathutils.strip_path(path)) + props = None + stored_exc_info = None + items = [] + try: + if tag: + radicale_item.check_and_sanitize_items( + vobject_items, is_collection=write_whole_collection, + tag=tag) + if write_whole_collection and tag == "VCALENDAR": + vobject_components = [] + vobject_item, = vobject_items + for content in ("vevent", "vtodo", "vjournal"): + vobject_components.extend( + getattr(vobject_item, "%s_list" % content, [])) + vobject_components_by_uid = itertools.groupby( + sorted(vobject_components, + key=radicale_item.get_uid), + radicale_item.get_uid) + for uid, components in vobject_components_by_uid: + vobject_collection = vobject.iCalendar() + for component in components: + vobject_collection.add(component) + item = radicale_item.Item( + collection_path=collection_path, + vobject_item=vobject_collection) + item.prepare() + items.append(item) + elif write_whole_collection and tag == "VADDRESSBOOK": + for vobject_item in vobject_items: + item = radicale_item.Item( + collection_path=collection_path, + vobject_item=vobject_item) + item.prepare() + items.append(item) + elif not write_whole_collection: + vobject_item, = vobject_items + item = radicale_item.Item( + collection_path=collection_path, + vobject_item=vobject_item) + item.prepare() + items.append(item) + + if write_whole_collection: + props = {} + if tag: + props["tag"] = tag + if tag == "VCALENDAR" and vobject_items: + if hasattr(vobject_items[0], "x_wr_calname"): + calname = vobject_items[0].x_wr_calname.value + if calname: + props["D:displayname"] = calname + if hasattr(vobject_items[0], "x_wr_caldesc"): + caldesc = vobject_items[0].x_wr_caldesc.value + if caldesc: + props["C:calendar-description"] = caldesc + radicale_item.check_and_sanitize_props(props) + except Exception: + stored_exc_info = sys.exc_info() + + # Use generator for items and delete references to free memory + # early + def items_generator(): + while items: + yield items.pop(0) + + return (items_generator(), tag, write_whole_collection, props, + stored_exc_info) + + class ApplicationPutMixin: def do_PUT(self, environ, base_prefix, path, user): """Manage PUT request.""" @@ -45,101 +135,11 @@ class ApplicationPutMixin: logger.debug("client timed out", exc_info=True) return httputils.REQUEST_TIMEOUT # Prepare before locking + content_type = environ.get("CONTENT_TYPE", "").split(";")[0] parent_path = pathutils.unstrip_path( posixpath.dirname(pathutils.strip_path(path)), True) permissions = self._rights.authorized(user, path, "Ww") parent_permissions = self._rights.authorized(user, parent_path, "w") - - def prepare(vobject_items, tag=None, write_whole_collection=None): - if (write_whole_collection or - permissions and not parent_permissions): - write_whole_collection = True - content_type = environ.get("CONTENT_TYPE", - "").split(";")[0] - tags = {value: key - for key, value in xmlutils.MIMETYPES.items()} - tag = radicale_item.predict_tag_of_whole_collection( - vobject_items, tags.get(content_type)) - if not tag: - raise ValueError("Can't determine collection tag") - collection_path = pathutils.strip_path(path) - elif (write_whole_collection is not None and - not write_whole_collection or - not permissions and parent_permissions): - write_whole_collection = False - if tag is None: - tag = radicale_item.predict_tag_of_parent_collection( - vobject_items) - collection_path = posixpath.dirname( - pathutils.strip_path(path)) - props = None - stored_exc_info = None - items = [] - try: - if tag: - radicale_item.check_and_sanitize_items( - vobject_items, is_collection=write_whole_collection, - tag=tag) - if write_whole_collection and tag == "VCALENDAR": - vobject_components = [] - vobject_item, = vobject_items - for content in ("vevent", "vtodo", "vjournal"): - vobject_components.extend( - getattr(vobject_item, "%s_list" % content, [])) - vobject_components_by_uid = itertools.groupby( - sorted(vobject_components, - key=radicale_item.get_uid), - radicale_item.get_uid) - for uid, components in vobject_components_by_uid: - vobject_collection = vobject.iCalendar() - for component in components: - vobject_collection.add(component) - item = radicale_item.Item( - collection_path=collection_path, - vobject_item=vobject_collection) - item.prepare() - items.append(item) - elif write_whole_collection and tag == "VADDRESSBOOK": - for vobject_item in vobject_items: - item = radicale_item.Item( - collection_path=collection_path, - vobject_item=vobject_item) - item.prepare() - items.append(item) - elif not write_whole_collection: - vobject_item, = vobject_items - item = radicale_item.Item( - collection_path=collection_path, - vobject_item=vobject_item) - item.prepare() - items.append(item) - - if write_whole_collection: - props = {} - if tag: - props["tag"] = tag - if tag == "VCALENDAR" and vobject_items: - if hasattr(vobject_items[0], "x_wr_calname"): - calname = vobject_items[0].x_wr_calname.value - if calname: - props["D:displayname"] = calname - if hasattr(vobject_items[0], "x_wr_caldesc"): - caldesc = vobject_items[0].x_wr_caldesc.value - if caldesc: - props["C:calendar-description"] = caldesc - radicale_item.check_and_sanitize_props(props) - except Exception: - stored_exc_info = sys.exc_info() - - # Use generator for items and delete references to free memory - # early - def items_generator(): - while items: - yield items.pop(0) - - return (items_generator(), tag, write_whole_collection, props, - stored_exc_info) - try: vobject_items = tuple(vobject.readComponents(content or "")) except Exception as e: @@ -147,7 +147,9 @@ class ApplicationPutMixin: "Bad PUT request on %r: %s", path, e, exc_info=True) return httputils.BAD_REQUEST (prepared_items, prepared_tag, prepared_write_whole_collection, - prepared_props, prepared_exc_info) = prepare(vobject_items) + prepared_props, prepared_exc_info) = prepare( + vobject_items, path, content_type, permissions, + parent_permissions) with self._storage.acquire_lock("w", user): item = next(self._storage.discover(path), None) @@ -188,7 +190,8 @@ class ApplicationPutMixin: prepared_write_whole_collection != write_whole_collection): (prepared_items, prepared_tag, prepared_write_whole_collection, prepared_props, prepared_exc_info) = prepare( - vobject_items, tag, write_whole_collection) + vobject_items, path, content_type, permissions, + parent_permissions, tag, write_whole_collection) props = prepared_props if prepared_exc_info: logger.warning(