[foundation-web] mkical.py: Make it print a textual calendar
- From: Tobias Mueller <tobiasmue src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [foundation-web] mkical.py: Make it print a textual calendar
- Date: Mon, 3 May 2010 02:18:11 +0000 (UTC)
commit fe53e3051bf870cd94613321eeead5b74f90acbf
Author: Tobias Mueller <tobiasmue gnome org>
Date: Mon May 3 00:34:38 2010 +0100
mkical.py: Make it print a textual calendar
It works quite well, with the exception of multiple events in one week.
foundation.gnome.org/elections/2010/mkical.py | 120 ++++++++++++++++++++++++-
1 files changed, 116 insertions(+), 4 deletions(-)
---
diff --git a/foundation.gnome.org/elections/2010/mkical.py b/foundation.gnome.org/elections/2010/mkical.py
index 4c128fb..f42d6d4 100644
--- a/foundation.gnome.org/elections/2010/mkical.py
+++ b/foundation.gnome.org/elections/2010/mkical.py
@@ -4,8 +4,11 @@ This Python script creates a simple iCal file based on hardcoded events
in this file.
'''
+import calendar
import datetime
import logging
+import math
+import os
import vobject
@@ -149,10 +152,112 @@ def create_ical(eventlist):
return stream
+def wraptext(s, width):
+ '''Wraps a string @s at @width characters.
+
+ >>> wraptext('fooo', 2)
+ ['fo','oo']
+ '''
+ l = len(s)
+ nr_frames = int(math.ceil(float(l)/width))
+ print nr_frames
+ frames = []
+ for i in xrange(nr_frames):
+ start, end = i*width, (i+1) * width
+ frames.append(s[start:end])
+ # One could (and prolly should) yield that
+ return frames
+
+def ordinal(n):
+ n = int(n)
+ if 10 <= n % 100 < 20:
+ return str(n) + 'th'
+ else:
+ return str(n) + {1 : 'st', 2 : 'nd', 3 : 'rd'}.get(n % 10, "th")
+
+
+def cal_for_month(month, events, width=80, year=datetime.datetime.now().year):
+ '''Generates a textual calendar for the @month in @year.
+ It will return a string with the calendar on the left hand side and the
+ events on the right hand side.
+ @events shall be a list with tuples: timestamp, summary, description.
+
+ Returns a string with the calendar
+ '''
+ log = logging.getLogger('cal_for_month')
+
+ cal = calendar.TextCalendar()
+ calstrings = cal.formatmonth(year, month, 3).splitlines()
+
+ for (timestamp, summary, description) in events:
+ log.debug('creating %s, %s', timestamp, summary)
+ year, month, day = timestamp.year, timestamp.month, timestamp.day
+ maxwidth = max([len(cs) for cs in calstrings])
+ rightwidth = 80 - maxwidth
+ for i, line in enumerate(calstrings):
+ needles = (" %d " % day,
+ " %d\n" % day)
+ replacement = "(%d)" % day
+ # Find the day so that we can highlight it and add a comment
+ day_in_week = False
+ for needle in needles:
+ if needle in line+"\n":
+ # k, this looks a bit weird but we have that corner
+ # case with the day being at the end of the line
+ # which in turn will have been split off
+ day_in_week = True
+ break # Set the needle to the found one
+ if day_in_week == False: # Nothing found, try next week
+ log.debug('Day (%d) not found in %s', day, line)
+ continue
+ else:
+ log.debug('Day (%d) found in %s', day, line)
+ new_line = (line+"\n").replace(needle, replacement).rstrip()
+ new_line += " %s (%s)" % (summary, ordinal(day))
+ # Replace in-place for two events in the same week
+ # FIXME: This has bugs :-(
+ calstrings[i] = new_line
+
+ return os.linesep.join(calstrings)
+
+def create_textcal(eventlist):
+ '''Generates a multiline string containing a calendar with the
+ events written on the side
+ The list shall contain elements with a tuple with a
+ (date, string, string) object, serving as date when the event takes place,
+ summary and description respectively.
+ '''
+ log = logging.getLogger('textcal')
+ log.debug('Generating from %s', eventlist)
+ months = set(map(lambda x: x[0].month, eventlist))
+ year = set(map(lambda x: x[0].year, eventlist)).pop()
+
+ final_cal = []
+ for month in months:
+ events = filter(lambda x: x[0].month == month, eventlist)
+ log.debug('Events for %d: %s', month, events)
+ month_cal = cal_for_month(month, events, year=year)
+ final_cal.append(month_cal)
+
+ return os.linesep.join(final_cal)
if __name__ == "__main__":
+ from optparse import OptionParser
+ parser = OptionParser("usage: %prog [options]")
+ parser.add_option("-l", "--loglevel", dest="loglevel", help="Sets the loglevel to one of debug, info, warn, error, critical",
+ default=None)
+ parser.add_option("-i", "--ical",
+ action="store_true", dest="ical", default=False,
+ help="print iCal file to stdout")
+ parser.add_option("-t", "--textcal",
+ action="store_true", dest="tcal", default=False,
+ help="print textual calendar to stdout")
+ (options, args) = parser.parse_args()
- logging.basicConfig( level=logging.CRITICAL )
+ loglevel = {'debug': logging.DEBUG, 'info': logging.INFO,
+ 'warn': logging.WARN, 'error': logging.ERROR,
+ 'critical': logging.CRITICAL}.get(options.loglevel, "warn")
+ logging.basicConfig( level=loglevel )
log = logging.getLogger()
eventlist = [
@@ -166,6 +271,13 @@ if __name__ == "__main__":
PRELIMINARY_RESULTS,
CHALLENGE_CLOSED,
]
-
- ical = create_ical( eventlist )
- print ical
+
+ if not any([options.ical, options.tcal]):
+ parser.error("You want to select either ical or textcal output. See --help for details")
+ if options.ical:
+ ical = create_ical( eventlist )
+ print ical
+ if options.tcal:
+ tcal = create_textcal( eventlist )
+ print tcal
+
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]