#!/usr/bin/env python # vim: set ts=8 sw=4 sts=4 et ai: # Walter Doekes, 2011 import datetime, locale, logging, os, sys, time try: from cStringIO import StringIO except ImportError: from StringIO import StringIO try: from urlparse import parse_qs except ImportError: from cgi import parse_qs try: from ho import pisa except ImportError, e: raise ImportError('%s\n\n!! Please install python-pisa (the ho.pisa html2pdf converter) !!' % (e,)) DO_PDF = True # Needed to display e.g. font errors. The wanted VAG Round font is # missing a Character to Glyph mapping table (cmap). The reportlab tools # refuse to use the font without it. Next step would be to "fix" the bad # TTF and add the proper cmap (probably constructed from the cp1252 code # page), but that's for another day. class PisaLogHandler(logging.Handler): def emit(self, record): print >>sys.stderr, record.exc_info logging.getLogger("ho.pisa").addHandler(PisaLogHandler()) def generate_weeks(begin_date, weeks, first_day='mon'): first_weekday = ['mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun'].index(first_day) curdate = begin_date - datetime.timedelta(days=((7 + begin_date.weekday() - first_weekday) % 7)) curweekno = (curdate + datetime.timedelta(days=4)).isocalendar()[1] # take week# from middle of week weeks_data = [] for i in xrange(weeks): week_days = [] for j in range(7): week_days.append(curdate) curdate += datetime.timedelta(days=1) yield {'num': curweekno, 'days': week_days} curweekno += 1 if curweekno >= 52 and curdate.month == 1: curweekno = 1 def create_calendar_html(title, weeks): style = [] #style.append('@font-face { font-family:"VAG Round";src:url(/usr/share/fonts/truetype/msttcorefonts/vaground.ttf); }') style.append('@font-face { font-family:"Comic Sans MS";src:url(/usr/share/fonts/truetype/msttcorefonts/comic.ttf); }') style.append('table { padding-top:36px;border-collapse:collapse; }') style.append('th,td { font-family:"VAG Round","Comic Sans MS","Comic Sans",sans-serif;font-size:36px; }') style.append('td { padding-top:12px;border-bottom:4px solid black; }') html = [] html.append('\n' '\n' '%s\n\n' % (title, ''.join(style))) for i, week in enumerate(weeks): if i != 0: html.append('') month = week['days'][0].strftime('%B') if week['days'][0].month != week['days'][6].month: month += '/%s' % (week['days'][6].strftime('%B'),) html.append('' % (week['num'], month)) for day in week['days']: html.append('' % (day.strftime('%a'), day.strftime('%e'))) html.append('
#%d%s
%s%s
') html.append('\n') return '\n'.join(html) def html_to_pdf(html): result = StringIO() #pdf = pisa.pisaDocument(StringIO(html.encode('utf-8')), result) pdf = pisa.pisaDocument(StringIO(html), result) if pdf.err: assert False return result.getvalue() # mimetype='application/pdf' if __name__ == '__main__': is_cgi = bool(os.environ.get('QUERY_STRING') is not None) if is_cgi: import urlparse try: args = parse_qs(os.environ['QUERY_STRING']) except Exception, e: print repr(e) begin_date = args.get('begin_date', [''])[0] or datetime.date.today().strftime('%Y-%m-%d') weeks = args.get('weeks', [''])[0] or '1' localestr = args.get('locale', [None])[0] else: begin_date = len(sys.argv) >= 2 and sys.argv[1] or '' weeks = len(sys.argv) >= 3 and sys.argv[2] or '' localestr = len(sys.argv) >= 4 and sys.argv[3] or os.environ.get('LC_TIME') try: begin_date = datetime.date.fromtimestamp(time.mktime(time.strptime(begin_date, '%Y-%m-%d'))) weeks = int(weeks) if weeks > 200: raise ValueError('Too many weeks!') if localestr: locale.setlocale(locale.LC_TIME, localestr) except Exception, e: if is_cgi: sys.stdout.write('Status: 500 Server Error\r\nContent-Type: text/plain\r\n\r\nBad arguments! (%s)\n' % (e,)) sys.exit(0) else: print >>sys.stderr, 'Usage: %s begin_date weeks [locale] > output.pdf' % (sys.argv[0],) sys.exit(1) else: html = create_calendar_html('Calendar', generate_weeks(begin_date, weeks)) if DO_PDF: if is_cgi: sys.stdout.write('Content-Type: application/pdf\r\nContent-Disposition: attachment; filename=calendar.pdf\r\n\r\n') sys.stdout.write(html_to_pdf(html)) else: if is_cgi: sys.stdout.write('Content-Type: text/html; charset="UTF-8"\r\n\r\n') sys.stdout.write(html)