Skip to content

Instantly share code, notes, and snippets.

@mstepniowski
Created May 8, 2011 12:52
Show Gist options
  • Save mstepniowski/961355 to your computer and use it in GitHub Desktop.
Save mstepniowski/961355 to your computer and use it in GitHub Desktop.
# 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