1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/EventAggregatorSupport.py Mon Mar 23 01:52:13 2009 +0100
1.3 @@ -0,0 +1,237 @@
1.4 +# -*- coding: iso-8859-1 -*-
1.5 +"""
1.6 + MoinMoin - EventAggregator library
1.7 +
1.8 + @copyright: 2008, 2009 by Paul Boddie <paul@boddie.org.uk>
1.9 + @copyright: 2000-2004 Juergen Hermann <jh@web.de>,
1.10 + 2005-2008 MoinMoin:ThomasWaldmann.
1.11 + @license: GNU GPL (v2 or later), see COPYING.txt for details.
1.12 +"""
1.13 +
1.14 +from MoinMoin.Page import Page
1.15 +from MoinMoin import search, version
1.16 +import calendar
1.17 +import re
1.18 +
1.19 +__version__ = "0.1"
1.20 +
1.21 +# Regular expressions where MoinMoin does not provide the required support.
1.22 +
1.23 +category_regexp = None
1.24 +definition_list_regexp = re.compile(ur'^\s+(?P<term>.*?)::\s(?P<desc>.*?)$', re.UNICODE | re.MULTILINE)
1.25 +date_regexp = re.compile(ur'(?P<year>[0-9]{4})-(?P<month>[0-9]{2})-(?P<day>[0-9]{2})', re.UNICODE)
1.26 +month_regexp = re.compile(ur'(?P<year>[0-9]{4})-(?P<month>[0-9]{2})', re.UNICODE)
1.27 +
1.28 +# Utility functions.
1.29 +
1.30 +def isMoin15():
1.31 + return version.release.startswith("1.5.")
1.32 +
1.33 +def getCategoryPattern(request):
1.34 + global category_regexp
1.35 +
1.36 + try:
1.37 + return request.cfg.cache.page_category_regexact
1.38 + except AttributeError:
1.39 +
1.40 + # Use regular expression from MoinMoin 1.7.1 otherwise.
1.41 +
1.42 + if category_regexp is None:
1.43 + category_regexp = re.compile(u'^%s$' % ur'(?P<all>Category(?P<key>(?!Template)\S+))', re.UNICODE)
1.44 + return category_regexp
1.45 +
1.46 +# The main activity functions.
1.47 +
1.48 +def getPages(pagename, request):
1.49 +
1.50 + "Return the links minus category links for 'pagename' using the 'request'."
1.51 +
1.52 + query = search.QueryParser().parse_query('category:%s' % pagename)
1.53 + if isMoin15():
1.54 + results = search.searchPages(request, query)
1.55 + results.sortByPagename()
1.56 + else:
1.57 + results = search.searchPages(request, query, "page_name")
1.58 +
1.59 + cat_pattern = getCategoryPattern(request)
1.60 + pages = []
1.61 + for page in results.hits:
1.62 + if not cat_pattern.match(page.page_name):
1.63 + pages.append(page)
1.64 + return pages
1.65 +
1.66 +def getPrettyPageName(page):
1.67 +
1.68 + "Return a nicely formatted title/name for the given 'page'."
1.69 +
1.70 + return page.split_title(force=1).replace("_", " ").replace("/", u" » ")
1.71 +
1.72 +def getEventDetails(page):
1.73 +
1.74 + "Return a dictionary of event details from the given 'page'."
1.75 +
1.76 + event_details = {}
1.77 +
1.78 + if page.pi["format"] == "wiki":
1.79 + for match in definition_list_regexp.finditer(page.body):
1.80 +
1.81 + # Permit case-insensitive list terms.
1.82 +
1.83 + term = match.group("term").lower()
1.84 + desc = match.group("desc")
1.85 +
1.86 + # Special value type handling.
1.87 +
1.88 + if term in ("start", "end"):
1.89 + desc = getDate(desc)
1.90 + elif term in ("topics",):
1.91 + desc = [value.strip() for value in desc.split(",")]
1.92 +
1.93 + if desc is not None:
1.94 + event_details[term] = desc
1.95 +
1.96 + return event_details
1.97 +
1.98 +def getDate(s):
1.99 +
1.100 + "Parse the string 's', extracting and returning a date string."
1.101 +
1.102 + m = date_regexp.search(s)
1.103 + if m:
1.104 + return tuple(map(int, m.groups()))
1.105 + else:
1.106 + return None
1.107 +
1.108 +def getMonth(s):
1.109 +
1.110 + "Parse the string 's', extracting and returning a month string."
1.111 +
1.112 + m = month_regexp.search(s)
1.113 + if m:
1.114 + return tuple(map(int, m.groups()))
1.115 + else:
1.116 + return None
1.117 +
1.118 +def daterange(first, last):
1.119 + results = []
1.120 +
1.121 + months_only = len(first) == 2
1.122 + start_year = first[0]
1.123 + end_year = last[0]
1.124 +
1.125 + for year in range(start_year, end_year + 1):
1.126 + if year < end_year:
1.127 + end_month = 12
1.128 + else:
1.129 + end_month = last[1]
1.130 +
1.131 + if year > start_year:
1.132 + start_month = 1
1.133 + else:
1.134 + start_month = first[1]
1.135 +
1.136 + for month in range(start_month, end_month + 1):
1.137 + if months_only:
1.138 + results.append((year, month))
1.139 + else:
1.140 + if month < end_month:
1.141 + _wd, end_day = calendar.monthrange(year, month)
1.142 + else:
1.143 + end_day = last[2]
1.144 +
1.145 + if month > start_month:
1.146 + start_day = 1
1.147 + else:
1.148 + start_day = first[2]
1.149 +
1.150 + for day in range(start_day, end_day + 1):
1.151 + results.append((year, month, day))
1.152 +
1.153 + return results
1.154 +
1.155 +def nextdate(date):
1.156 + year, month, day = date
1.157 + _wd, end_day = calendar.monthrange(year, month)
1.158 + if day == end_day:
1.159 + if month == 12:
1.160 + return (year + 1, 1, 1)
1.161 + else:
1.162 + return (year, month + 1, 1)
1.163 + else:
1.164 + return (year, month, day + 1)
1.165 +
1.166 +def getEvents(request, category_names, calendar_start=None, calendar_end=None):
1.167 +
1.168 + """
1.169 + Using the 'request', generate a list of events found on pages belonging to
1.170 + the specified 'category_names', using the optional 'calendar_start' and
1.171 + 'calendar_end' month tuples of the form (year, month) to indicate a window
1.172 + of interest.
1.173 +
1.174 + Return a list of events, a dictionary mapping months to event lists (within
1.175 + the window of interest), a list of all events within the window of interest,
1.176 + the earliest month of an event within the window of interest, and the latest
1.177 + month of an event within the window of interest.
1.178 + """
1.179 +
1.180 + events = []
1.181 + shown_events = {}
1.182 + all_shown_events = []
1.183 +
1.184 + earliest = None
1.185 + latest = None
1.186 +
1.187 + for category_name in category_names:
1.188 +
1.189 + # Get the pages and page names in the category.
1.190 +
1.191 + pages_in_category = getPages(category_name, request)
1.192 +
1.193 + # Visit each page in the category.
1.194 +
1.195 + for page_in_category in pages_in_category:
1.196 + pagename = page_in_category.page_name
1.197 +
1.198 + # Get a real page, not a result page.
1.199 +
1.200 + real_page_in_category = Page(request, pagename)
1.201 + event_details = getEventDetails(real_page_in_category)
1.202 +
1.203 + # Define the event as the page together with its details.
1.204 +
1.205 + event = (real_page_in_category, event_details)
1.206 + events.append(event)
1.207 +
1.208 + # Test for the suitability of the event.
1.209 +
1.210 + if event_details.has_key("start") and event_details.has_key("end"):
1.211 +
1.212 + start_month = event_details["start"][:2]
1.213 + end_month = event_details["end"][:2]
1.214 +
1.215 + # Compare the months of the dates to the requested calendar
1.216 + # window, if any.
1.217 +
1.218 + if (calendar_start is None or end_month >= calendar_start) and \
1.219 + (calendar_end is None or start_month <= calendar_end):
1.220 +
1.221 + all_shown_events.append(event)
1.222 +
1.223 + if earliest is None or start_month < earliest:
1.224 + earliest = start_month
1.225 + if latest is None or end_month > latest:
1.226 + latest = end_month
1.227 +
1.228 + # Store the event in the month-specific dictionary.
1.229 +
1.230 + first = max(start_month, calendar_start or start_month)
1.231 + last = min(end_month, calendar_end or end_month)
1.232 +
1.233 + for event_month in daterange(first, last):
1.234 + if not shown_events.has_key(event_month):
1.235 + shown_events[event_month] = []
1.236 + shown_events[event_month].append(event)
1.237 +
1.238 + return events, shown_events, all_shown_events, earliest, latest
1.239 +
1.240 +# vim: tabstop=4 expandtab shiftwidth=4
2.1 --- a/README.txt Sun Mar 22 22:46:53 2009 +0100
2.2 +++ b/README.txt Mon Mar 23 01:52:13 2009 +0100
2.3 @@ -8,9 +8,23 @@
2.4 the details of each event, colouring each event period in a specially
2.5 generated colour.
2.6
2.7 +The EventAggregatorSummary action can be used to provide an iCalendar summary
2.8 +of event data based on pages belonging to specific categories, as described
2.9 +above. The category, start and end parameters are read directly from the
2.10 +request as URL or form parameters.
2.11 +
2.12 Installation
2.13 ------------
2.14
2.15 +To install the support library, consider using the setup.py script provided:
2.16 +
2.17 + python setup.py install
2.18 +
2.19 +You may wish to indicate a specific prefix if MoinMoin is not installed in the
2.20 +traditional location:
2.21 +
2.22 + python setup.py install --prefix=path-to-moin-prefix
2.23 +
2.24 To install the macro in a Wiki, consider using the instmacros script provided:
2.25
2.26 ./instmacros path-to-wiki
2.27 @@ -18,6 +32,37 @@
2.28 On non-UNIX platforms, it is necessary to manually copy the contents of the
2.29 macros directory in this distribution into the macros directory of your Wiki.
2.30
2.31 +It is highly recommended that the tables and listings be styled according to
2.32 +the stylesheet provided, and you can use this file as a starting point for
2.33 +your own modifications. To install the stylesheet, consider using the
2.34 +insttheme script provided:
2.35 +
2.36 + ./insttheme path-to-wiki theme-name
2.37 +
2.38 +Again, on non-UNIX platforms, it is necessary to manually copy the files. In
2.39 +this case, just copy the contents of the css directory into the css directory
2.40 +of themes which will support styling of event calendars and listings.
2.41 +
2.42 +To activate the styles provided by the stylesheet in the css directory, you
2.43 +will need to edit the screen.css file in each affected theme's css directory,
2.44 +adding the following before any style rules:
2.45 +
2.46 + /* Event aggregation... */
2.47 +
2.48 + @import "event-aggregator.css";
2.49 +
2.50 +This ensures that the styles are made available to the browser.
2.51 +
2.52 +To install the action in a Wiki, consider using the instactions script provided:
2.53 +
2.54 + ./instactions path-to-wiki
2.55 +
2.56 +On non-UNIX platforms, it is necessary to manually copy the contents of the
2.57 +actions directory in this distribution into the actions directory of your Wiki.
2.58 +
2.59 +Using the Macro
2.60 +---------------
2.61 +
2.62 It should now be possible to edit pages and use the macro as follows. For
2.63 MoinMoin 1.5:
2.64
2.65 @@ -38,26 +83,21 @@
2.66
2.67 <<EventAggregator(CategoryEvent,mode=list)>>
2.68
2.69 -It is highly recommended that the tables and listings be styled according to
2.70 -the stylesheet provided, and you can use this file as a starting point for
2.71 -your own modifications. To install the stylesheet, consider using the
2.72 -insttheme script provided:
2.73 +Using the Action
2.74 +----------------
2.75
2.76 - ./insttheme path-to-wiki theme-name
2.77 +To obtain an iCalendar summary, a collection of parameters can be specified in
2.78 +the URL of any Wiki page. For example:
2.79 +
2.80 + http://example.com/moin/FrontPage?action=EventAggregatorSummary&category=CategoryEvents
2.81
2.82 -Again, on non-UNIX platforms, it is necessary to manually copy the files. In
2.83 -this case, just copy the contents of the css directory into the css directory
2.84 -of themes which will support styling of event calendars and listings.
2.85 +This should produce an iCalendar resource in response. By specifying 'start'
2.86 +and 'end' parameters, a restricted view can be obtained. For example:
2.87
2.88 -To activate the styles provided by the stylesheet in the css directory, you
2.89 -will need to edit the screen.css file in each affected theme's css directory,
2.90 -adding the following before any style rules:
2.91 + http://example.com/moin/FrontPage?action=EventAggregatorSummary&category=CategoryEvents&start=2009-06&end=2009-07
2.92
2.93 - /* Event aggregation... */
2.94 -
2.95 - @import "event-aggregator.css";
2.96 -
2.97 -This ensures that the styles are made available to the browser.
2.98 +This would restrict the initial query to events occurring in the months of
2.99 +June 2009 ('2009-06') and July 2009 ('2009-07').
2.100
2.101 Recommended Software
2.102 --------------------
2.103 @@ -84,9 +124,10 @@
2.104 Contact, Copyright and Licence Information
2.105 ------------------------------------------
2.106
2.107 -See the following Web page for more information about this work:
2.108 +See the following Web pages for more information about this work:
2.109
2.110 http://moinmo.in/MacroMarket/EventAggregator
2.111 +http://moinmo.in/ActionMarket/EventAggregator
2.112
2.113 The author can be contacted at the following e-mail address:
2.114
2.115 @@ -98,9 +139,9 @@
2.116 Release Procedures
2.117 ------------------
2.118
2.119 -Update the EventAggregator.py __version__ attribute.
2.120 +Update the EventAggregatorSupport.py __version__ attribute.
2.121 Change the version number and package filename/directory in the documentation.
2.122 Update the release notes (see above).
2.123 Tag, export.
2.124 Archive, upload.
2.125 -Update the MacroMarket (see above for the URL).
2.126 +Update the MacroMarket and ActionMarket (see above for the URLs).
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
3.2 +++ b/actions/EventAggregatorSummary.py Mon Mar 23 01:52:13 2009 +0100
3.3 @@ -0,0 +1,70 @@
3.4 +# -*- coding: iso-8859-1 -*-
3.5 +"""
3.6 + MoinMoin - EventAggregatorSummary Action
3.7 +
3.8 + @copyright: 2008, 2009 by Paul Boddie <paul@boddie.org.uk>
3.9 + @copyright: 2000-2004 Juergen Hermann <jh@web.de>,
3.10 + 2005-2008 MoinMoin:ThomasWaldmann.
3.11 + @license: GNU GPL (v2 or later), see COPYING.txt for details.
3.12 +"""
3.13 +
3.14 +from MoinMoin import config
3.15 +import EventAggregatorSupport
3.16 +
3.17 +Dependencies = ['pages']
3.18 +
3.19 +# Action function.
3.20 +
3.21 +def execute(pagename, request):
3.22 +
3.23 + """
3.24 + For the given 'pagename' and 'request', write an iCalendar summary of the
3.25 + event data found in the categories specified via the "category" request
3.26 + parameter, using the "start" and "end" parameters (if specified). Multiple
3.27 + "category" parameters can be specified.
3.28 + """
3.29 +
3.30 + category_names = request.form.get("category", [])
3.31 +
3.32 + if request.form.has_key("start"):
3.33 + calendar_start = EventAggregatorSupport.getMonth(request.form["start"][0])
3.34 + else:
3.35 + calendar_start = None
3.36 +
3.37 + if request.form.has_key("end"):
3.38 + calendar_end = EventAggregatorSupport.getMonth(request.form["end"][0])
3.39 + else:
3.40 + calendar_end = None
3.41 +
3.42 + events, shown_events, all_shown_events, earliest, latest = \
3.43 + EventAggregatorSupport.getEvents(request, category_names, calendar_start, calendar_end)
3.44 +
3.45 + # Output iCalendar data...
3.46 +
3.47 + request.emit_http_headers(["Content-Type: text/calendar; charset=%s" % config.charset])
3.48 +
3.49 + request.write("BEGIN:VCALENDAR\r\n")
3.50 + request.write("PRODID:-//MoinMoin//EventAggregatorSummary\r\n")
3.51 + request.write("VERSION:2.0\r\n")
3.52 +
3.53 + for event_page, event_details in all_shown_events:
3.54 +
3.55 + # Get a pretty version of the page name.
3.56 +
3.57 + pretty_pagename = EventAggregatorSupport.getPrettyPageName(event_page)
3.58 +
3.59 + # Output the event details.
3.60 +
3.61 + request.write("BEGIN:VEVENT\r\n")
3.62 + request.write("SUMMARY:%s\r\n" % pretty_pagename)
3.63 + request.write("UID:%s\r\n" % request.getQualifiedURL(event_page.url(request)))
3.64 + request.write("URL:%s\r\n" % request.getQualifiedURL(event_page.url(request)))
3.65 + request.write("DTSTART;VALUE=DATE:%04d%02d%02d\r\n" % event_details["start"])
3.66 + request.write("DTEND;VALUE=DATE:%04d%02d%02d\r\n" % EventAggregatorSupport.nextdate(event_details["end"]))
3.67 + if event_details.has_key("topics"):
3.68 + request.write("CATEGORIES:%s\r\n" % ",".join(event_details["topics"]))
3.69 + request.write("END:VEVENT\r\n")
3.70 +
3.71 + request.write("END:VCALENDAR\r\n")
3.72 +
3.73 +# vim: tabstop=4 expandtab shiftwidth=4
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
4.2 +++ b/instactions Mon Mar 23 01:52:13 2009 +0100
4.3 @@ -0,0 +1,13 @@
4.4 +#!/bin/bash
4.5 +
4.6 +if [[ ! $1 ]] ; then
4.7 + echo "Please specify a directory such as ../mysite/wiki or /tmp/mysite/wiki."
4.8 + echo "This should be the root of your Wiki installation and contain the data"
4.9 + echo "directory."
4.10 + echo
4.11 + echo "You may wish to uncomment and modify the chown command in this script."
4.12 + exit
4.13 +fi
4.14 +
4.15 +cp actions/*.py $1/data/plugin/action/
4.16 +#chown www-data: $1/data/plugin/action/*.py
5.1 --- a/macros/EventAggregator.py Sun Mar 22 22:46:53 2009 +0100
5.2 +++ b/macros/EventAggregator.py Mon Mar 23 01:52:13 2009 +0100
5.3 @@ -8,150 +8,23 @@
5.4 @license: GNU GPL (v2 or later), see COPYING.txt for details.
5.5 """
5.6
5.7 -from MoinMoin.Page import Page
5.8 -from MoinMoin import wikiutil, search, version
5.9 +from MoinMoin import wikiutil
5.10 +import EventAggregatorSupport
5.11 import calendar
5.12 -import re
5.13
5.14 try:
5.15 set
5.16 except NameError:
5.17 from sets import Set as set
5.18
5.19 -__version__ = "0.1"
5.20 -
5.21 Dependencies = ['pages']
5.22
5.23 -# Regular expressions where MoinMoin does not provide the required support.
5.24 -
5.25 -category_regexp = None
5.26 -definition_list_regexp = re.compile(ur'^\s+(?P<term>.*?)::\s(?P<desc>.*?)$', re.UNICODE | re.MULTILINE)
5.27 -date_regexp = re.compile(ur'(?P<year>[0-9]{4})-(?P<month>[0-9]{2})-(?P<day>[0-9]{2})', re.UNICODE)
5.28 -month_regexp = re.compile(ur'(?P<year>[0-9]{4})-(?P<month>[0-9]{2})', re.UNICODE)
5.29 -
5.30 # Date labels.
5.31
5.32 month_labels = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"]
5.33 weekday_labels = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]
5.34
5.35 -# Utility functions.
5.36 -
5.37 -def isMoin15():
5.38 - return version.release.startswith("1.5.")
5.39 -
5.40 -def getCategoryPattern(request):
5.41 - global category_regexp
5.42 -
5.43 - try:
5.44 - return request.cfg.cache.page_category_regexact
5.45 - except AttributeError:
5.46 -
5.47 - # Use regular expression from MoinMoin 1.7.1 otherwise.
5.48 -
5.49 - if category_regexp is None:
5.50 - category_regexp = re.compile(u'^%s$' % ur'(?P<all>Category(?P<key>(?!Template)\S+))', re.UNICODE)
5.51 - return category_regexp
5.52 -
5.53 -# The main activity functions.
5.54 -
5.55 -def getPages(pagename, request):
5.56 -
5.57 - "Return the links minus category links for 'pagename' using the 'request'."
5.58 -
5.59 - query = search.QueryParser().parse_query('category:%s' % pagename)
5.60 - if isMoin15():
5.61 - results = search.searchPages(request, query)
5.62 - results.sortByPagename()
5.63 - else:
5.64 - results = search.searchPages(request, query, "page_name")
5.65 -
5.66 - cat_pattern = getCategoryPattern(request)
5.67 - pages = []
5.68 - for page in results.hits:
5.69 - if not cat_pattern.match(page.page_name):
5.70 - pages.append(page)
5.71 - return pages
5.72 -
5.73 -def getPrettyPageName(page):
5.74 -
5.75 - "Return a nicely formatted title/name for the given 'page'."
5.76 -
5.77 - return page.split_title(force=1).replace("_", " ").replace("/", u" » ")
5.78 -
5.79 -def getEventDetails(page):
5.80 -
5.81 - "Return a dictionary of event details from the given 'page'."
5.82 -
5.83 - event_details = {}
5.84 -
5.85 - if page.pi["format"] == "wiki":
5.86 - for match in definition_list_regexp.finditer(page.body):
5.87 - # Permit case-insensitive list terms.
5.88 - term = match.group("term").lower()
5.89 - desc = match.group("desc")
5.90 - if term in ("start", "end"):
5.91 - desc = getDate(desc)
5.92 - if desc is not None:
5.93 - event_details[term] = desc
5.94 -
5.95 - return event_details
5.96 -
5.97 -def getDate(s):
5.98 -
5.99 - "Parse the string 's', extracting and returning a date string."
5.100 -
5.101 - m = date_regexp.search(s)
5.102 - if m:
5.103 - return tuple(map(int, m.groups()))
5.104 - else:
5.105 - return None
5.106 -
5.107 -def getMonth(s):
5.108 -
5.109 - "Parse the string 's', extracting and returning a month string."
5.110 -
5.111 - m = month_regexp.search(s)
5.112 - if m:
5.113 - return tuple(map(int, m.groups()))
5.114 - else:
5.115 - return None
5.116 -
5.117 -def daterange(first, last):
5.118 - results = []
5.119 -
5.120 - months_only = len(first) == 2
5.121 - start_year = first[0]
5.122 - end_year = last[0]
5.123 -
5.124 - for year in range(start_year, end_year + 1):
5.125 - if year < end_year:
5.126 - end_month = 12
5.127 - else:
5.128 - end_month = last[1]
5.129 -
5.130 - if year > start_year:
5.131 - start_month = 1
5.132 - else:
5.133 - start_month = first[1]
5.134 -
5.135 - for month in range(start_month, end_month + 1):
5.136 - if months_only:
5.137 - results.append((year, month))
5.138 - else:
5.139 - if month < end_month:
5.140 - _wd, end_day = calendar.monthrange(year, month)
5.141 - else:
5.142 - end_day = last[2]
5.143 -
5.144 - if month > start_month:
5.145 - start_day = 1
5.146 - else:
5.147 - start_day = first[2]
5.148 -
5.149 - for day in range(start_day, end_day + 1):
5.150 - results.append((year, month, day))
5.151 -
5.152 - return results
5.153 +# HTML-related functions.
5.154
5.155 def getColour(s):
5.156 colour = [0, 0, 0]
5.157 @@ -169,6 +42,8 @@
5.158 else:
5.159 return (255, 255, 255)
5.160
5.161 +# Macro function.
5.162 +
5.163 def execute(macro, args):
5.164
5.165 """
5.166 @@ -211,9 +86,9 @@
5.167
5.168 for arg in parsed_args:
5.169 if arg.startswith("start="):
5.170 - calendar_start = getMonth(arg[6:])
5.171 + calendar_start = EventAggregatorSupport.getMonth(arg[6:])
5.172 elif arg.startswith("end="):
5.173 - calendar_end = getMonth(arg[4:])
5.174 + calendar_end = EventAggregatorSupport.getMonth(arg[4:])
5.175 elif arg.startswith("mode="):
5.176 mode = arg[5:]
5.177 elif arg.startswith("names="):
5.178 @@ -221,65 +96,8 @@
5.179 else:
5.180 category_names.append(arg)
5.181
5.182 - # Generate a list of events found on pages belonging to the specified
5.183 - # categories, as found in the macro arguments.
5.184 -
5.185 - events = []
5.186 - shown_events = {}
5.187 - all_shown_events = []
5.188 -
5.189 - earliest = None
5.190 - latest = None
5.191 -
5.192 - for category_name in category_names:
5.193 -
5.194 - # Get the pages and page names in the category.
5.195 -
5.196 - pages_in_category = getPages(category_name, request)
5.197 -
5.198 - # Visit each page in the category.
5.199 -
5.200 - for page_in_category in pages_in_category:
5.201 - pagename = page_in_category.page_name
5.202 -
5.203 - # Get a real page, not a result page.
5.204 -
5.205 - real_page_in_category = Page(request, pagename)
5.206 - event_details = getEventDetails(real_page_in_category)
5.207 -
5.208 - # Define the event as the page together with its details.
5.209 -
5.210 - event = (real_page_in_category, event_details)
5.211 - events.append(event)
5.212 -
5.213 - # Test for the suitability of the event.
5.214 -
5.215 - if event_details.has_key("start") and event_details.has_key("end"):
5.216 -
5.217 - start_month = event_details["start"][:2]
5.218 - end_month = event_details["end"][:2]
5.219 -
5.220 - # Compare the months of the dates to the requested calendar
5.221 - # window, if any.
5.222 -
5.223 - if (calendar_start is None or end_month >= calendar_start) and \
5.224 - (calendar_end is None or start_month <= calendar_end):
5.225 -
5.226 - if earliest is None or start_month < earliest:
5.227 - earliest = start_month
5.228 - if latest is None or end_month > latest:
5.229 - latest = end_month
5.230 -
5.231 - # Store the event in the month-specific dictionary.
5.232 -
5.233 - first = max(start_month, calendar_start or start_month)
5.234 - last = min(end_month, calendar_end or end_month)
5.235 -
5.236 - for event_month in daterange(first, last):
5.237 - if not shown_events.has_key(event_month):
5.238 - shown_events[event_month] = []
5.239 - shown_events[event_month].append(event)
5.240 - all_shown_events.append(event)
5.241 + events, shown_events, all_shown_events, earliest, latest = \
5.242 + EventAggregatorSupport.getEvents(request, category_names, calendar_start, calendar_end)
5.243
5.244 # Make a calendar.
5.245
5.246 @@ -295,7 +113,7 @@
5.247 first = calendar_start or earliest
5.248 last = calendar_end or latest
5.249
5.250 - for year, month in daterange(first, last):
5.251 + for year, month in EventAggregatorSupport.daterange(first, last):
5.252
5.253 # Either output a calendar view...
5.254
5.255 @@ -363,7 +181,7 @@
5.256
5.257 event_start = max(event_details["start"], week_start)
5.258 event_end = min(event_details["end"], week_end)
5.259 - event_coverage = set(daterange(event_start, event_end))
5.260 + event_coverage = set(EventAggregatorSupport.daterange(event_start, event_end))
5.261
5.262 # Update the overall coverage.
5.263
5.264 @@ -482,7 +300,7 @@
5.265
5.266 # Get a pretty version of the page name.
5.267
5.268 - pretty_pagename = getPrettyPageName(event_page)
5.269 + pretty_pagename = EventAggregatorSupport.getPrettyPageName(event_page)
5.270
5.271 # Generate a colour for the event.
5.272
5.273 @@ -552,7 +370,7 @@
5.274
5.275 # Get a pretty version of the page name.
5.276
5.277 - pretty_pagename = getPrettyPageName(event_page)
5.278 + pretty_pagename = EventAggregatorSupport.getPrettyPageName(event_page)
5.279
5.280 output.append(fmt.listitem(on=1, attr={"class" : "event-listing"}))
5.281
5.282 @@ -579,46 +397,9 @@
5.283
5.284 # Output top-level information.
5.285
5.286 - # Output iCalendar data...
5.287 -
5.288 - if mode == "ics":
5.289 -
5.290 - # Output the calendar details as preformatted text.
5.291 -
5.292 - output.append(fmt.preformatted(on=1))
5.293 - output.append(fmt.text("BEGIN:VCALENDAR"))
5.294 - output.append(fmt.linebreak())
5.295 - output.append(fmt.text("VERSION:1.0"))
5.296 - output.append(fmt.linebreak())
5.297 -
5.298 - for event_page, event_details in all_shown_events:
5.299 -
5.300 - # Get a pretty version of the page name.
5.301 -
5.302 - pretty_pagename = getPrettyPageName(event_page)
5.303 -
5.304 - # Output the event details.
5.305 -
5.306 - output.append(fmt.text("BEGIN:VEVENT"))
5.307 - output.append(fmt.linebreak())
5.308 - output.append(fmt.text("SUMMARY:%s" % pretty_pagename))
5.309 - output.append(fmt.linebreak())
5.310 - output.append(fmt.text("URL:%s" % request.getQualifiedURL(event_page.url(request))))
5.311 - output.append(fmt.linebreak())
5.312 - output.append(fmt.text("DTSTART:%04d%02d%02d" % event_details["start"]))
5.313 - output.append(fmt.linebreak())
5.314 - output.append(fmt.text("DTEND:%04d%02d%02d" % event_details["end"]))
5.315 - output.append(fmt.linebreak())
5.316 - output.append(fmt.text("END:VEVENT"))
5.317 - output.append(fmt.linebreak())
5.318 -
5.319 - output.append(fmt.text("END:VCALENDAR"))
5.320 - output.append(fmt.linebreak())
5.321 - output.append(fmt.preformatted(on=0))
5.322 -
5.323 # End of list view output.
5.324
5.325 - elif mode == "list":
5.326 + if mode == "list":
5.327 output.append(fmt.bullet_list(on=0))
5.328
5.329 return ''.join(output)
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
6.2 +++ b/setup.py Mon Mar 23 01:52:13 2009 +0100
6.3 @@ -0,0 +1,15 @@
6.4 +#! /usr/bin/env python
6.5 +
6.6 +from distutils.core import setup
6.7 +
6.8 +import EventAggregatorSupport
6.9 +
6.10 +setup(
6.11 + name = "EventAggregator",
6.12 + description = "Aggregate event data and display it in an event calendar (or summarise it in an iCalendar resource)",
6.13 + author = "Paul Boddie",
6.14 + author_email = "paul@boddie.org.uk",
6.15 + url = "http://moinmo.in/MacroMarket/EventAggregator",
6.16 + version = EventAggregatorSupport.__version__,
6.17 + py_modules = ["EventAggregatorSupport"]
6.18 + )