diff --git a/pytest.ini b/pytest.ini index da3dfa5..9bf10c8 100644 --- a/pytest.ini +++ b/pytest.ini @@ -1,3 +1,3 @@ [pytest] -addopts = --flake8 --isort --cov radicale/ tests +addopts = --flake8 --isort --cov radicale/ radicale/tests norecursedirs = dist .cache .git build *.egg-info .eggs venv diff --git a/radicale/storage.py b/radicale/storage.py index c50edf5..b24d3e9 100644 --- a/radicale/storage.py +++ b/radicale/storage.py @@ -35,7 +35,8 @@ import time from contextlib import contextmanager from hashlib import md5 from importlib import import_module -from uuid import uuid4 +from itertools import groupby +from random import getrandbits import vobject @@ -231,6 +232,15 @@ class BaseCollection: for href in set(hrefs): yield self.get(href) + def pre_filtered_list(self, filters): + """List collection items with optional pre filtering. + + This could largely improve performance of reports depending on + the filters and this implementation. + This returns all event by default + """ + return [self.get(href) for href, _ in self.list()] + def has(self, href): """Check if an item exists by its href. @@ -372,25 +382,26 @@ class Collection(BaseCollection): items = [] for content in ("vevent", "vtodo", "vjournal"): items.extend(getattr(collection, "%s_list" % content, [])) - processed_uids = [] - for i, item in enumerate(items): - uid = getattr(item, "uid", None) - if uid in processed_uids: - continue + + def get_uid(item): + return hasattr(item, 'uid') and item.uid.value + + items_by_uid = groupby( + sorted(items, key=get_uid), get_uid) + + for uid, items in items_by_uid: new_collection = vobject.iCalendar() - new_collection.add(item) - if uid: - processed_uids.append(uid) - # search for items with same UID - for oitem in items[i+1:]: - if getattr(oitem, "uid", None) == uid: - new_collection.add(oitem) - self.upload(uuid4().hex, new_collection) + for item in items: + new_collection.add(item) + file_name = hex(getrandbits(32))[2:] + self.upload(file_name, new_collection) + elif tag == "VCARD": self.set_meta("tag", "VADDRESSBOOK") if collection: for card in collection: - self.upload(uuid4().hex, card) + file_name = hex(getrandbits(32))[2:] + self.upload(file_name, card) return self def list(self): diff --git a/tests/__init__.py b/radicale/tests/__init__.py similarity index 100% rename from tests/__init__.py rename to radicale/tests/__init__.py diff --git a/tests/custom/__init__.py b/radicale/tests/custom/__init__.py similarity index 100% rename from tests/custom/__init__.py rename to radicale/tests/custom/__init__.py diff --git a/tests/custom/auth.py b/radicale/tests/custom/auth.py similarity index 100% rename from tests/custom/auth.py rename to radicale/tests/custom/auth.py diff --git a/tests/custom/storage.py b/radicale/tests/custom/storage.py similarity index 100% rename from tests/custom/storage.py rename to radicale/tests/custom/storage.py diff --git a/tests/helpers.py b/radicale/tests/helpers.py similarity index 100% rename from tests/helpers.py rename to radicale/tests/helpers.py diff --git a/tests/static/event1.ics b/radicale/tests/static/event1.ics similarity index 100% rename from tests/static/event1.ics rename to radicale/tests/static/event1.ics diff --git a/tests/static/event2.ics b/radicale/tests/static/event2.ics similarity index 100% rename from tests/static/event2.ics rename to radicale/tests/static/event2.ics diff --git a/tests/static/event3.ics b/radicale/tests/static/event3.ics similarity index 100% rename from tests/static/event3.ics rename to radicale/tests/static/event3.ics diff --git a/tests/static/event4.ics b/radicale/tests/static/event4.ics similarity index 100% rename from tests/static/event4.ics rename to radicale/tests/static/event4.ics diff --git a/tests/static/event5.ics b/radicale/tests/static/event5.ics similarity index 100% rename from tests/static/event5.ics rename to radicale/tests/static/event5.ics diff --git a/tests/static/journal1.ics b/radicale/tests/static/journal1.ics similarity index 100% rename from tests/static/journal1.ics rename to radicale/tests/static/journal1.ics diff --git a/tests/static/journal2.ics b/radicale/tests/static/journal2.ics similarity index 100% rename from tests/static/journal2.ics rename to radicale/tests/static/journal2.ics diff --git a/tests/static/journal3.ics b/radicale/tests/static/journal3.ics similarity index 100% rename from tests/static/journal3.ics rename to radicale/tests/static/journal3.ics diff --git a/tests/static/journal4.ics b/radicale/tests/static/journal4.ics similarity index 100% rename from tests/static/journal4.ics rename to radicale/tests/static/journal4.ics diff --git a/tests/static/journal5.ics b/radicale/tests/static/journal5.ics similarity index 100% rename from tests/static/journal5.ics rename to radicale/tests/static/journal5.ics diff --git a/tests/static/todo1.ics b/radicale/tests/static/todo1.ics similarity index 100% rename from tests/static/todo1.ics rename to radicale/tests/static/todo1.ics diff --git a/tests/static/todo2.ics b/radicale/tests/static/todo2.ics similarity index 100% rename from tests/static/todo2.ics rename to radicale/tests/static/todo2.ics diff --git a/tests/static/todo3.ics b/radicale/tests/static/todo3.ics similarity index 100% rename from tests/static/todo3.ics rename to radicale/tests/static/todo3.ics diff --git a/tests/static/todo4.ics b/radicale/tests/static/todo4.ics similarity index 100% rename from tests/static/todo4.ics rename to radicale/tests/static/todo4.ics diff --git a/tests/static/todo5.ics b/radicale/tests/static/todo5.ics similarity index 100% rename from tests/static/todo5.ics rename to radicale/tests/static/todo5.ics diff --git a/tests/static/todo6.ics b/radicale/tests/static/todo6.ics similarity index 100% rename from tests/static/todo6.ics rename to radicale/tests/static/todo6.ics diff --git a/tests/static/todo7.ics b/radicale/tests/static/todo7.ics similarity index 100% rename from tests/static/todo7.ics rename to radicale/tests/static/todo7.ics diff --git a/tests/static/todo8.ics b/radicale/tests/static/todo8.ics similarity index 100% rename from tests/static/todo8.ics rename to radicale/tests/static/todo8.ics diff --git a/tests/test_auth.py b/radicale/tests/test_auth.py similarity index 100% rename from tests/test_auth.py rename to radicale/tests/test_auth.py diff --git a/tests/test_base.py b/radicale/tests/test_base.py similarity index 100% rename from tests/test_base.py rename to radicale/tests/test_base.py diff --git a/radicale/xmlutils.py b/radicale/xmlutils.py index 71bb8a3..350dd1b 100644 --- a/radicale/xmlutils.py +++ b/radicale/xmlutils.py @@ -837,7 +837,7 @@ def report(path, xml_request, collection): else: # Reference is a collection path = hreference - items = [collection.get(href) for href, etag in collection.list()] + items = collection.pre_filtered_list(filters) for item in items: if filters: