Procházet zdrojové kódy

Don't use VObject for collection serialization

Unrud před 8 roky
rodič
revize
e0045ca98d
1 změnil soubory, kde provedl 48 přidání a 61 odebrání
  1. 48 61
      radicale/storage.py

+ 48 - 61
radicale/storage.py

@@ -596,14 +596,56 @@ class BaseCollection:
     def serialize(self):
         """Get the unicode string representing the whole collection."""
         if self.get_meta("tag") == "VCALENDAR":
-            collection = vobject.iCalendar()
+            in_vcalendar = False
+            vtimezones = ""
+            included_tzids = set()
+            vtimezone = []
+            tzid = None
+            components = ""
+            # Concatenate all child elements of VCALENDAR from all items
+            # together, while preventing duplicated VTIMEZONE entries.
+            # VTIMEZONEs are only distinguished by their TZID, if different
+            # timezones share the same TZID this produces errornous ouput.
+            # VObject fails at this too.
             for item in self.get_all():
-                for content in ("vevent", "vtodo", "vjournal"):
-                    for component in getattr(item, "%s_list" % content, ()):
-                        collection.add(component)
-            return collection.serialize()
+                depth = 0
+                for line in item.serialize().split("\r\n"):
+                    if line.startswith("BEGIN:"):
+                        depth += 1
+                    if depth == 1 and line == "BEGIN:VCALENDAR":
+                        in_vcalendar = True
+                    elif in_vcalendar:
+                        if depth == 1 and line.startswith("END:"):
+                            in_vcalendar = False
+                        if depth == 2 and line == "BEGIN:VTIMEZONE":
+                            vtimezone.append(line)
+                        elif vtimezone:
+                            vtimezone.append(line)
+                            if depth == 2 and line.startswith("TZID:"):
+                                tzid = line[len("TZID:"):]
+                            elif depth == 2 and line.startswith("END:"):
+                                if tzid is None or tzid not in included_tzids:
+                                    if vtimezones:
+                                        vtimezones += "\r\n"
+                                    vtimezones += "\r\n".join(vtimezone)
+                                    included_tzids.add(tzid)
+                                vtimezone.clear()
+                                tzid = None
+                        elif depth >= 2:
+                            if components:
+                                components += "\r\n"
+                            components += line
+                    if line.startswith("END:"):
+                        depth -= 1
+            return "\r\n".join(filter(bool, (
+                "BEGIN:VCALENDAR",
+                "VERSION:2.0",
+                "PRODID:-//PYVOBJECT//NONSGML Version 1//EN",
+                vtimezones,
+                components,
+                "END:VCALENDAR")))
         elif self.get_meta("tag") == "VADDRESSBOOK":
-            return "".join(item.serialize() for item in self.get_all())
+            return "".join((item.serialize() for item in self.get_all()))
         return ""
 
     @classmethod
@@ -1272,61 +1314,6 @@ class Collection(BaseCollection):
         last = max(map(os.path.getmtime, relevant_files))
         return time.strftime("%a, %d %b %Y %H:%M:%S GMT", time.gmtime(last))
 
-    def serialize(self):
-        # serialize collection
-        if self.get_meta("tag") == "VCALENDAR":
-            in_vcalendar = False
-            vtimezones = ""
-            included_tzids = set()
-            vtimezone = []
-            tzid = None
-            components = ""
-            # Concatenate all child elements of VCALENDAR from all items
-            # together, while preventing duplicated VTIMEZONE entries.
-            # VTIMEZONEs are only distinguished by their TZID, if different
-            # timezones share the same TZID this produces errornous ouput.
-            # VObject fails at this too.
-            for item in self.get_all():
-                depth = 0
-                for line in item.serialize().split("\r\n"):
-                    if line.startswith("BEGIN:"):
-                        depth += 1
-                    if depth == 1 and line == "BEGIN:VCALENDAR":
-                        in_vcalendar = True
-                    elif in_vcalendar:
-                        if depth == 1 and line.startswith("END:"):
-                            in_vcalendar = False
-                        if depth == 2 and line == "BEGIN:VTIMEZONE":
-                            vtimezone.append(line)
-                        elif vtimezone:
-                            vtimezone.append(line)
-                            if depth == 2 and line.startswith("TZID:"):
-                                tzid = line[len("TZID:"):]
-                            elif depth == 2 and line.startswith("END:"):
-                                if tzid is None or tzid not in included_tzids:
-                                    if vtimezones:
-                                        vtimezones += "\r\n"
-                                    vtimezones += "\r\n".join(vtimezone)
-                                    included_tzids.add(tzid)
-                                vtimezone.clear()
-                                tzid = None
-                        elif depth >= 2:
-                            if components:
-                                components += "\r\n"
-                            components += line
-                    if line.startswith("END:"):
-                        depth -= 1
-            return "\r\n".join(filter(bool, (
-                "BEGIN:VCALENDAR",
-                "VERSION:2.0",
-                "PRODID:-//PYVOBJECT//NONSGML Version 1//EN",
-                vtimezones,
-                components,
-                "END:VCALENDAR")))
-        elif self.get_meta("tag") == "VADDRESSBOOK":
-            return "".join((item.serialize() for item in self.get_all()))
-        return ""
-
     @property
     def etag(self):
         # reuse cached value if the storage is read-only