From d15835bf1bb6a0c7b16577e01799738a8031d1cb Mon Sep 17 00:00:00 2001 From: "W. Trevor King" Date: Sun, 30 Jun 2013 10:27:44 -0400 Subject: [PATCH] aggregator: Add an initial Aggregator implementation Currently broken pending support for `for entry in feed`. The version and product identifier fields are required, as specified in RFC 5545, sections 3.7.3 (Product Identifier) and 3.7.4 (Version). They'll also need to have special characters (e.g. commas) escaped, but I'll get to that later. --- pycalendar/aggregator.py | 70 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 pycalendar/aggregator.py diff --git a/pycalendar/aggregator.py b/pycalendar/aggregator.py new file mode 100644 index 0000000..c54b122 --- /dev/null +++ b/pycalendar/aggregator.py @@ -0,0 +1,70 @@ +# Copyright + +class Aggregator (list): + r"""An iCalendar feed aggregator + + Figure out where the example feeds are located, relative to the + directory from which you run this doctest (i.e., the project's + root directory). + + >>> import os + >>> root_dir = os.curdir + >>> data_dir = os.path.abspath(os.path.join(root_dir, 'test', 'data')) + >>> base_url = 'file://{}'.format(data_dir.replace(os.sep, '/')) + + >>> from .feed import Feed + + >>> a = Aggregator( + ... prodid='-//pycalendar//NONSGML testing//EN', + ... feeds=[ + ... Feed(url='{}/{}'.format(base_url, name)) + ... for name in ['geohash.ics',]], + ... ) + >>> a # doctest: +ELLIPSIS + [] + >>> a.fetch() + + Generate aggregate calendars with the ``.write`` method. + + >>> import io + >>> stream = io.StringIO() + >>> a.write(stream=stream) + >>> value = stream.getvalue() + >>> value # doctest: +ELLIPSIS + 'BEGIN:VCALENDAR\r\nVERSION:2.0\r\n...END:VCALENDAR\r\n' + >>> print(value.replace('\r\n', '\n')) + BEGIN:VCALENDAR + VERSION:2.0 + PRODID:-//pycalendar//NONSGML testing//EN + BEGIN:VEVENT + UID:2013-06-30@geohash.invalid + DTSTAMP:2013-06-30T00:00:00Z + DTSTART;VALUE=DATE:20130630 + DTEND;VALUE=DATE:20130701 + SUMMARY:XKCD geohashing\, Boston graticule + URL:http://xkcd.com/426/ + LOCATION:Snow Hill\, Dover\, Massachusetts + GEO:42.226663,-71.28676 + END:VEVENT + END:VCALENDAR + + """ + def __init__(self, prodid, version='2.0', feeds=None): + super(Aggregator, self).__init__() + self.prodid = prodid + self.version = version + if feeds: + self.extend(feeds) + + def fetch(self): + for feed in self: + feed.fetch() + + def write(self, stream): + stream.write('BEGIN:VCALENDAR\r\n') + stream.write('VERSION:{}\r\n'.format(self.version)) + stream.write('PRODID:{}\r\n'.format(self.prodid)) + for feed in self: + for entry in feed: + entry.write(stream=stream) + stream.write('END:VCALENDAR\r\n') -- 2.26.2