1.1 --- a/imip_agent.py Wed Sep 24 14:58:48 2014 +0200
1.2 +++ b/imip_agent.py Wed Sep 24 16:05:03 2014 +0200
1.3 @@ -7,7 +7,7 @@
1.4 from email.mime.text import MIMEText
1.5 from pytz import timezone, UnknownTimeZoneError
1.6 from smtplib import SMTP
1.7 -from vCalendar import parse, ParseError
1.8 +from vCalendar import parse, ParseError, to_dict, to_node
1.9 import imip_store
1.10 import re
1.11 import sys
1.12 @@ -64,28 +64,6 @@
1.13
1.14 # Content interpretation.
1.15
1.16 -def get_itip_structure(elements):
1.17 - d = {}
1.18 - for name, attr, value in elements:
1.19 - if not d.has_key(name):
1.20 - d[name] = []
1.21 - if isinstance(value, list):
1.22 - d[name].append((get_itip_structure(value), attr))
1.23 - else:
1.24 - d[name].append((value, attr))
1.25 - return d
1.26 -
1.27 -def get_structure_items(d):
1.28 - items = []
1.29 - for name, value in d.items():
1.30 - if isinstance(value, list):
1.31 - for v, a in value:
1.32 - items.append((name, a, v))
1.33 - else:
1.34 - v, a = value
1.35 - items.append((name, a, get_structure_items(v)))
1.36 - return items
1.37 -
1.38 def get_items(d, name, all=True):
1.39 if d.has_key(name):
1.40 values = d[name]
1.41 @@ -246,7 +224,7 @@
1.42 ("METHOD", {}, method),
1.43 ("VERSION", {}, "2.0")
1.44 ]
1.45 - imip_store.to_stream(out, calendar, "VCALENDAR", encoding)
1.46 + imip_store.to_stream(out, ("VCALENDAR", {}, calendar), encoding)
1.47 part = MIMEText(out.getvalue(), "calendar", encoding)
1.48 part.set_param("method", method)
1.49 return part
1.50 @@ -263,9 +241,9 @@
1.51
1.52 try:
1.53 try:
1.54 - doctype, attrs, elements = parse(f, encoding=encoding)
1.55 + doctype, attrs, elements = obj = parse(f, encoding=encoding)
1.56 if doctype == objtype:
1.57 - return get_itip_structure(elements)
1.58 + return to_dict(obj)[objtype][0]
1.59 finally:
1.60 f.close()
1.61 except (ParseError, ValueError):
1.62 @@ -478,7 +456,9 @@
1.63 if not conflict:
1.64 insert_period(freebusy, (dtstart, dtend, self.uid))
1.65 self.store.set_freebusy(attendee, freebusy)
1.66 - self.store.set_event(attendee, self.uid, get_structure_items(self.details))
1.67 + self.store.set_event(attendee, self.uid, to_node(
1.68 + {"VEVENT" : [(self.details, {})]}
1.69 + ))
1.70 attendee_attr["PARTSTAT"] = "ACCEPTED"
1.71
1.72 # If the event cannot be scheduled, it is not registered and a reply
1.73 @@ -489,7 +469,9 @@
1.74 attendee_attr["PARTSTAT"] = "DECLINED"
1.75
1.76 self.details["ATTENDEE"] = [(attendee, attendee_attr)]
1.77 - calendar.append(("VEVENT", {}, get_structure_items(self.details)))
1.78 + calendar.append(to_node(
1.79 + {"VEVENT" : [(self.details, {})]}
1.80 + ))
1.81
1.82 return calendar
1.83
2.1 --- a/imip_store.py Wed Sep 24 14:58:48 2014 +0200
2.2 +++ b/imip_store.py Wed Sep 24 16:05:03 2014 +0200
2.3 @@ -9,8 +9,8 @@
2.4 def check_dir(base, dir):
2.5 return commonprefix([base, abspath(dir)]) == base
2.6
2.7 -def to_stream(out, fragment, objtype, encoding="utf-8"):
2.8 - iterwrite(out, encoding=encoding).write(objtype, {}, fragment)
2.9 +def to_stream(out, fragment, encoding="utf-8"):
2.10 + iterwrite(out, encoding=encoding).append(fragment)
2.11
2.12 class FileStore:
2.13
2.14 @@ -35,9 +35,9 @@
2.15
2.16 return exists(filename) and open(filename) or None
2.17
2.18 - def set_event(self, user, uid, details):
2.19 + def set_event(self, user, uid, node):
2.20
2.21 - "Set an event for 'user' having the given 'uid' and 'details'."
2.22 + "Set an event for 'user' having the given 'uid' and 'node'."
2.23
2.24 dir = self.get_file_object(self.store_dir, user)
2.25 if not dir:
2.26 @@ -52,7 +52,7 @@
2.27
2.28 f = open(filename, "w")
2.29 try:
2.30 - to_stream(f, details, "VEVENT")
2.31 + to_stream(f, node)
2.32 finally:
2.33 f.close()
2.34
3.1 --- a/vCalendar.py Wed Sep 24 14:58:48 2014 +0200
3.2 +++ b/vCalendar.py Wed Sep 24 16:05:03 2014 +0200
3.3 @@ -276,4 +276,7 @@
3.4
3.5 return vContent.iterwrite(stream_or_string, write, encoding, line_length, vCalendarStreamWriter)
3.6
3.7 +to_dict = vContent.to_dict
3.8 +to_node = vContent.to_node
3.9 +
3.10 # vim: tabstop=4 expandtab shiftwidth=4
4.1 --- a/vContent.py Wed Sep 24 14:58:48 2014 +0200
4.2 +++ b/vContent.py Wed Sep 24 16:05:03 2014 +0200
4.3 @@ -620,6 +620,43 @@
4.4 else:
4.5 return codecs.open(stream_or_string, "w", encoding=(encoding or default_encoding))
4.6
4.7 +def items_to_dict(items):
4.8 +
4.9 + """
4.10 + Return the given 'items' as a dictionary mapping names to tuples of the form
4.11 + (value, attributes).
4.12 + """
4.13 +
4.14 + d = {}
4.15 + for name, attr, value in items:
4.16 + if not d.has_key(name):
4.17 + d[name] = []
4.18 + if isinstance(value, list):
4.19 + d[name].append((items_to_dict(value), attr))
4.20 + else:
4.21 + d[name].append((value, attr))
4.22 + return d
4.23 +
4.24 +def dict_to_items(d):
4.25 +
4.26 + """
4.27 + Return 'd' converted to a list of items suitable for serialisation using
4.28 + iterwrite.
4.29 + """
4.30 +
4.31 + items = []
4.32 + for name, value in d.items():
4.33 + if isinstance(value, list):
4.34 + for v, a in value:
4.35 + if isinstance(v, dict):
4.36 + items.append((name, a, dict_to_items(v)))
4.37 + else:
4.38 + items.append((name, a, v))
4.39 + else:
4.40 + v, a = value
4.41 + items.append((name, a, dict_to_items(v)))
4.42 + return items
4.43 +
4.44 # Public functions.
4.45
4.46 def parse(stream_or_string, encoding=None, non_standard_newline=0, parser_cls=None):
4.47 @@ -708,4 +745,17 @@
4.48
4.49 return (writer_cls or StreamWriter)(_writer)
4.50
4.51 +def to_dict(node):
4.52 +
4.53 + "Return the 'node' converted to a dictionary representation."
4.54 +
4.55 + name, attr, items = node
4.56 + return {name : (isinstance(items, list) and items_to_dict(items) or items, attr)}
4.57 +
4.58 +def to_node(d):
4.59 +
4.60 + "Return 'd' converted to a items-based representation."
4.61 +
4.62 + return dict_to_items(d)[0]
4.63 +
4.64 # vim: tabstop=4 expandtab shiftwidth=4