1. Ian Lewis
  2. django-ical

Commits

Ian Lewis  committed acd1db5

Initial commit

  • Participants
  • Branches default

Comments (0)

Files changed (5)

File .hgignore

View file
+syntax: glob
+*.orig
+*.rej
+*~
+*.bak
+*.marks
+*.o
+*.pyc
+*.swp
+*.egg-info
+build
+temp
+dist
+
+syntax: regexp
+.*\#.*\#$ 

File django_ical/__init__.py

Empty file added.

File django_ical/feedgenerator.py

View file
+#:coding=utf-8:
+
+from icalendar import Calendar, Event
+
+from django.utils.feedgenerator import SyndicationFeed
+
+__all__ = (
+    'ICal20Feed',
+)
+
+FEED_FIELD_MAP = (
+    ('product_id',          'prodid'),
+    ('method',              'method'),
+    ('title',               'x-wr-calname'),
+    ('description',         'x-wr-caldesc'),
+    ('timezone',            'x-wr-timezone'),
+)
+
+ITEM_EVENT_FIELD_MAP = (
+    # item_guid は unique_id になる
+    ('unique_id',           'uid'),
+    ('title',               'summary'),
+    ('description',         'description'),
+    ('start_datetime',      'dtstart'),
+    ('end_datetime',        'dtend'),
+    ('updated',             'last-modified'),
+    ('created',             'created'),
+    ('timestamp',           'dtstamp'),
+    ('transparency',        'transp'),
+    ('location',            'location'),
+    ('link',                'url'),
+)
+
+class ICal20Feed(SyndicationFeed):
+    mime_type='text/calendar; charset=utf8'
+
+    def write(self, outfile, encoding):
+        cal = Calendar()
+        cal.add('version', '2.0')
+        cal.add('calscale', 'GREGORIAN')
+
+        for ifield, efield in FEED_FIELD_MAP:
+            val = self.feed.get(ifield)
+            if val is not None:
+                cal.add(efield, val)
+
+        self.write_items(cal)
+
+        outfile.write(cal.as_string()) 
+
+    def write_items(self, calendar):
+        """
+        Write all events to the calendar
+        """
+        for item in self.items:
+            event = Event()
+            for ifield, efield in ITEM_EVENT_FIELD_MAP:
+                val = item.get(ifield)
+                if val is not None:
+                    event.add(efield, val)
+            calendar.add_component(event)

File django_ical/views.py

View file
+#:coding=utf-8:
+
+from datetime import datetime
+
+from django.contrib.syndication.views import Feed
+
+# ICAL用の Django Syndication フレームワークに拡張するフィールド
+FEED_EXTRA_FIELDS = (
+    'method',
+    'product_id',
+    'timezone',
+)
+ICAL_EXTRA_FIELDS = (
+    'timestamp',        # dtstamp
+    'created',          # created
+    'updated',          # last-modified
+    'start_datetime',   # dtstart
+    'end_datetime',     # dtend
+    'transparency',     # transp
+    'location',         # location
+)
+
+class ICalFeed(Feed):
+    """
+    ====================
+    icalendar 用のFeed
+    ====================
+
+    既存フィールド
+    ---------------------
+    title => X-WR-CALNAME
+    description => X-WR-CALDESC
+
+    item_guid => UID
+    item_title => SUMMARY
+    item_description => DESCRIPTION
+    item_link => URL
+     
+    拡張フィールド
+    -------------------------
+    method => METHOD
+    timezone => X-WR-TIMEZONE
+
+    item_class => CLASS
+    item_timestamp => DTSTAMP
+    item_created => CREATED
+    item_updated => LAST-MODIFIED
+    item_start_datetime => DTSTART
+    item_end_datetime => DTEND
+    item_transparency => TRANSP
+    """
+    def _get_dynamic_attr(self, attname, obj, default=None):
+        """
+        django.contrib.syndication.views.Feed からコピー
+        """
+        try:
+            attr = getattr(self, attname)
+        except AttributeError:
+            return default
+        if callable(attr):
+            # Check func_code.co_argcount rather than try/excepting the
+            # function and catching the TypeError, because something inside
+            # the function may raise the TypeError. This technique is more
+            # accurate.
+            if hasattr(attr, 'func_code'):
+                argcount = attr.func_code.co_argcount
+            else:
+                argcount = attr.__call__.func_code.co_argcount
+            if argcount == 2: # one argument is 'self'
+                return attr(obj)
+            else:
+                return attr()
+        return attr
+
+    def method(self, obj):
+        return 'PUBLISH'
+
+    def feed_extra_kwargs(self, obj):
+        kwargs = {}
+        for field in FEED_EXTRA_FIELDS:
+            val = self._get_dynamic_attr(field, obj)
+            if val:
+                kwargs[field] = val
+        return kwargs
+
+    def item_timestamp(self, obj):
+        return datetime.now()
+
+    def item_extra_kwargs(self, obj):
+        kwargs = {}
+        for field in ICAL_EXTRA_FIELDS:
+            val = self._get_dynamic_attr('item_' + field, obj)
+            if val:
+                kwargs[field] = val
+        return kwargs

File setup.py

View file
+#!/usr/bin/env python
+
+from setuptools import setup, find_packages
+ 
+setup (
+    name='django-ical',
+    version='1.0',
+    description="iCal feeds for Django based on Django's syndication feed framework.",
+    author='Ian Lewis',
+    author_email='IanMLewis@gmail.com',
+    license='MIT License',
+    classifiers=[
+      'Development Status :: 3 - Alpha',
+      'Environment :: Plugins',
+      'Framework :: Django',
+      'Intended Audience :: Developers',
+      'License :: OSI Approved :: BSD License',
+      'Programming Language :: Python',
+      'Topic :: Software Development :: Libraries :: Python Modules',
+    ],
+    install_requires = [
+        'Django>=1.3',
+        'icalendar>=2.0.1',
+    ],
+    packages=find_packages(),
+    #test_suite='tests.main',
+)