Created
May 8, 2011 12:52
-
-
Save mstepniowski/961355 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Required libraries: | |
# | |
# * vobject <http://vobject.skyhouseconsulting.com/> | |
# | |
# Copyright (C) 2011 Marek Stepniowski <marek@stepniowski.com> | |
# | |
# This program is free software. It comes without any warranty, to | |
# the extent permitted by applicable law. You can redistribute it | |
# and/or modify it under the terms of the Do What The Fuck You Want | |
# To Public License, Version 2, as published by Sam Hocevar. See | |
# http://sam.zoy.org/wtfpl/COPYING for more details. */ | |
import datetime | |
import re | |
import unittest | |
import vobject | |
def generate_uid_from_name(event): | |
result = event['name'].lower() | |
result = re.sub(r'[^a-zA-Z0-9-.]', '-', result) | |
return 'europython-2011-' + re.sub(r'-+', '-', result) | |
def generate_ical(events, | |
get_uid=generate_uid_from_name, | |
tz=vobject.icalendar.utc): | |
"""Generates an iCalendar feed for a list of `events`. After | |
saving the feed to a file, it can be imported directly to iCal, | |
Outlook, Google Calendar and other calendaring programs. Users can | |
also subscribe to such feed via URL. The file will then be | |
downloaded regularly and the calendar will be automatically | |
updated. | |
Each event should be a dict with "name", "speaker", "description", | |
"dtstart" and "dtend" keys. All dates should be in UTC timezone. | |
Example:: | |
{'name': 'Good API design', | |
'speaker': 'Alex Martelli', | |
'description': '...', | |
'dtstart': datetime.datetime(2011, 6, 20, 9, 30), | |
'dtend': datetime.datetime(2011, 6, 20, 10, 30)} | |
A unique identificator for each event is generated using `get_uid` | |
function (by default it's a slug of the title). The UID is used | |
when the user subscribes to the calendar to identify the events | |
that should be updated. | |
""" | |
calendar = vobject.iCalendar() | |
for event in events: | |
vevent = calendar.add('vevent') | |
vevent.add('summary').value = u'%s (by %s)' % (event['name'], | |
event['speaker']) | |
vevent.add('description').value = event['description'] | |
vevent.add('dtstart').value = event['dtstart'].replace(tzinfo=tz) | |
vevent.add('dtend').value = event['dtend'].replace(tzinfo=tz) | |
vevent.add('uid').value = get_uid(event) | |
calendar.add('X-WR-CALNAME').value = 'EuroPython 2011' | |
return calendar.serialize() | |
class TestGenerateICal(unittest.TestCase): | |
def test_generate_uid_from_name(self): | |
result = generate_uid_from_name({'name': 'Good API design', | |
'speaker': 'Alex Martelli', | |
'description': '...', | |
'dtstart': datetime.datetime(2011, 6, 20, 7, 30), | |
'dtend': datetime.datetime(2011, 6, 20, 8, 30)}) | |
self.assertEqual(result, 'europython-2011-good-api-design') | |
def test_generate_single_event(self): | |
result = generate_ical([{'name': 'Good API design', | |
'speaker': 'Alex Martelli', | |
'description': '...', | |
'dtstart': datetime.datetime(2011, 6, 20, 7, 30), | |
'dtend': datetime.datetime(2011, 6, 20, 8, 30)}], | |
get_uid=lambda e: 'UID') | |
self.assertEqual(result, 'BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:-//PYVOBJECT//NONSGML Version 1//EN\r\nBEGIN:VEVENT\r\nUID:UID\r\nDTSTART:20110620T073000Z\r\nDTEND:20110620T083000Z\r\nDESCRIPTION:...\r\nSUMMARY:Good API design (by Alex Martelli)\r\nEND:VEVENT\r\nX-WR-CALNAME:EuroPython 2011\r\nEND:VCALENDAR\r\n') | |
def test_generate_multiple_events(self): | |
result = generate_ical([{'name': 'Good API design', | |
'speaker': 'Alex Martelli', | |
'description': '...', | |
'dtstart': datetime.datetime(2011, 6, 20, 7, 30), | |
'dtend': datetime.datetime(2011, 6, 20, 8, 30)}, | |
{'name': 'Functional Programming with Python', | |
'speaker': 'John Pinner', | |
'description': '...', | |
'dtstart': datetime.datetime(2011, 6, 21, 7, 0), | |
'dtend': datetime.datetime(2011, 6, 21, 11, 0)}], | |
get_uid=lambda e: 'UID') | |
self.assertEqual(result, 'BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:-//PYVOBJECT//NONSGML Version 1//EN\r\nBEGIN:VEVENT\r\nUID:UID\r\nDTSTART:20110620T073000Z\r\nDTEND:20110620T083000Z\r\nDESCRIPTION:...\r\nSUMMARY:Good API design (by Alex Martelli)\r\nEND:VEVENT\r\nBEGIN:VEVENT\r\nUID:UID\r\nDTSTART:20110621T070000Z\r\nDTEND:20110621T110000Z\r\nDESCRIPTION:...\r\nSUMMARY:Functional Programming with Python (by John Pinner)\r\nEND:VEVENT\r\nX-WR-CALNAME:EuroPython 2011\r\nEND:VCALENDAR\r\n') | |
if __name__ == "__main__": | |
unittest.main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment