# HG changeset patch # User Paul Boddie # Date 1411567503 -7200 # Node ID 044fa59f7f413d78774d96d17063582f2cc4e7a8 # Parent 4cd247d490299b718a5cbca518624b81565c83c5 Moved representation conversion functions into vContent, making use of the node representation in the agent and store modules. diff -r 4cd247d49029 -r 044fa59f7f41 imip_agent.py --- a/imip_agent.py Wed Sep 24 14:58:48 2014 +0200 +++ b/imip_agent.py Wed Sep 24 16:05:03 2014 +0200 @@ -7,7 +7,7 @@ from email.mime.text import MIMEText from pytz import timezone, UnknownTimeZoneError from smtplib import SMTP -from vCalendar import parse, ParseError +from vCalendar import parse, ParseError, to_dict, to_node import imip_store import re import sys @@ -64,28 +64,6 @@ # Content interpretation. -def get_itip_structure(elements): - d = {} - for name, attr, value in elements: - if not d.has_key(name): - d[name] = [] - if isinstance(value, list): - d[name].append((get_itip_structure(value), attr)) - else: - d[name].append((value, attr)) - return d - -def get_structure_items(d): - items = [] - for name, value in d.items(): - if isinstance(value, list): - for v, a in value: - items.append((name, a, v)) - else: - v, a = value - items.append((name, a, get_structure_items(v))) - return items - def get_items(d, name, all=True): if d.has_key(name): values = d[name] @@ -246,7 +224,7 @@ ("METHOD", {}, method), ("VERSION", {}, "2.0") ] - imip_store.to_stream(out, calendar, "VCALENDAR", encoding) + imip_store.to_stream(out, ("VCALENDAR", {}, calendar), encoding) part = MIMEText(out.getvalue(), "calendar", encoding) part.set_param("method", method) return part @@ -263,9 +241,9 @@ try: try: - doctype, attrs, elements = parse(f, encoding=encoding) + doctype, attrs, elements = obj = parse(f, encoding=encoding) if doctype == objtype: - return get_itip_structure(elements) + return to_dict(obj)[objtype][0] finally: f.close() except (ParseError, ValueError): @@ -478,7 +456,9 @@ if not conflict: insert_period(freebusy, (dtstart, dtend, self.uid)) self.store.set_freebusy(attendee, freebusy) - self.store.set_event(attendee, self.uid, get_structure_items(self.details)) + self.store.set_event(attendee, self.uid, to_node( + {"VEVENT" : [(self.details, {})]} + )) attendee_attr["PARTSTAT"] = "ACCEPTED" # If the event cannot be scheduled, it is not registered and a reply @@ -489,7 +469,9 @@ attendee_attr["PARTSTAT"] = "DECLINED" self.details["ATTENDEE"] = [(attendee, attendee_attr)] - calendar.append(("VEVENT", {}, get_structure_items(self.details))) + calendar.append(to_node( + {"VEVENT" : [(self.details, {})]} + )) return calendar diff -r 4cd247d49029 -r 044fa59f7f41 imip_store.py --- a/imip_store.py Wed Sep 24 14:58:48 2014 +0200 +++ b/imip_store.py Wed Sep 24 16:05:03 2014 +0200 @@ -9,8 +9,8 @@ def check_dir(base, dir): return commonprefix([base, abspath(dir)]) == base -def to_stream(out, fragment, objtype, encoding="utf-8"): - iterwrite(out, encoding=encoding).write(objtype, {}, fragment) +def to_stream(out, fragment, encoding="utf-8"): + iterwrite(out, encoding=encoding).append(fragment) class FileStore: @@ -35,9 +35,9 @@ return exists(filename) and open(filename) or None - def set_event(self, user, uid, details): + def set_event(self, user, uid, node): - "Set an event for 'user' having the given 'uid' and 'details'." + "Set an event for 'user' having the given 'uid' and 'node'." dir = self.get_file_object(self.store_dir, user) if not dir: @@ -52,7 +52,7 @@ f = open(filename, "w") try: - to_stream(f, details, "VEVENT") + to_stream(f, node) finally: f.close() diff -r 4cd247d49029 -r 044fa59f7f41 vCalendar.py --- a/vCalendar.py Wed Sep 24 14:58:48 2014 +0200 +++ b/vCalendar.py Wed Sep 24 16:05:03 2014 +0200 @@ -276,4 +276,7 @@ return vContent.iterwrite(stream_or_string, write, encoding, line_length, vCalendarStreamWriter) +to_dict = vContent.to_dict +to_node = vContent.to_node + # vim: tabstop=4 expandtab shiftwidth=4 diff -r 4cd247d49029 -r 044fa59f7f41 vContent.py --- a/vContent.py Wed Sep 24 14:58:48 2014 +0200 +++ b/vContent.py Wed Sep 24 16:05:03 2014 +0200 @@ -620,6 +620,43 @@ else: return codecs.open(stream_or_string, "w", encoding=(encoding or default_encoding)) +def items_to_dict(items): + + """ + Return the given 'items' as a dictionary mapping names to tuples of the form + (value, attributes). + """ + + d = {} + for name, attr, value in items: + if not d.has_key(name): + d[name] = [] + if isinstance(value, list): + d[name].append((items_to_dict(value), attr)) + else: + d[name].append((value, attr)) + return d + +def dict_to_items(d): + + """ + Return 'd' converted to a list of items suitable for serialisation using + iterwrite. + """ + + items = [] + for name, value in d.items(): + if isinstance(value, list): + for v, a in value: + if isinstance(v, dict): + items.append((name, a, dict_to_items(v))) + else: + items.append((name, a, v)) + else: + v, a = value + items.append((name, a, dict_to_items(v))) + return items + # Public functions. def parse(stream_or_string, encoding=None, non_standard_newline=0, parser_cls=None): @@ -708,4 +745,17 @@ return (writer_cls or StreamWriter)(_writer) +def to_dict(node): + + "Return the 'node' converted to a dictionary representation." + + name, attr, items = node + return {name : (isinstance(items, list) and items_to_dict(items) or items, attr)} + +def to_node(d): + + "Return 'd' converted to a items-based representation." + + return dict_to_items(d)[0] + # vim: tabstop=4 expandtab shiftwidth=4