summaryrefslogtreecommitdiffstats
path: root/conferences.py
diff options
context:
space:
mode:
authorbipasa <bipasac2000@gmail.com>2012-01-13 13:01:12 -0500
committerbipasa <bipasac2000@gmail.com>2012-01-13 13:01:12 -0500
commit34f017590712c9906836ddf996bdc65b55fd745c (patch)
treee0df7c5834999d3445dec91d9b8c3ac65cdab431 /conferences.py
parent405287fa6dd51e682ae4b7e39432f5859865fc24 (diff)
parente8f30c862d050c74b4d72c9353bcf90255baba56 (diff)
Merge branch 'master' of ssh://cvs.cs.unc.edu/cvs/proj/litmus/repo/rthp
Diffstat (limited to 'conferences.py')
-rwxr-xr-xconferences.py170
1 files changed, 170 insertions, 0 deletions
diff --git a/conferences.py b/conferences.py
new file mode 100755
index 0000000..067eb6e
--- /dev/null
+++ b/conferences.py
@@ -0,0 +1,170 @@
1#!/usr/bin/env python
2
3from __future__ import print_function
4
5import sys
6import csv
7from functools import total_ordering
8from datetime import datetime
9from operator import attrgetter
10
11"""Read CSV and make HTML for the conference page.
12
13Handles sorting dates, TBD dates, dates in the past, and more.
14No guarantees that this is bug free :)
15
16Author: Christopher Kenna (2012)
17
18"""
19
20@total_ordering
21class ConferenceDate(object):
22 TBD_STR = 'tbd'
23 TBD_VAL = 'tbd'
24
25 def __init__(self, date):
26 if isinstance(date, datetime):
27 self.dt = date
28 else:
29 self.dt = self.date_from_str(date)
30
31 @classmethod
32 def date_from_str(cls, date_str):
33 try:
34 return datetime.strptime(date_str, '%m/%d/%Y')
35 except ValueError:
36 if cls.TBD_STR == date_str.lower():
37 return cls.TBD_VAL
38 die('bad date: {0}'.format(date_str))
39
40 @classmethod
41 def get_timespan(cls, start, end):
42 ret = []
43 if start is end:
44 ret.append(cls.html_date(start))
45 elif (not start.is_tbd() and not end.is_tbd() and
46 start.dt.month == end.dt.month):
47 ret.append(start.dt.strftime('%b. {0}'.format(start.dt.day)))
48 ret.append('&ndash;')
49 ret.append(end.dt.strftime('{0}, %Y'.format(end.dt.day)))
50 else:
51 ret.extend([cls.html_date(start), '&endash;',
52 cls.html_date(end)])
53 return ' '.join(ret)
54
55 @classmethod
56 def html_date(cls, d):
57 if d.is_tbd():
58 return 'TBD'
59 # using string format to get '2' and not '02'
60 return d.dt.strftime('%b. {0}, %Y'.format(d.dt.day))
61
62 def __eq__(self, other):
63 a_is_tbd, b_is_tbd = self.is_tbd(), other.is_tbd()
64 if a_is_tbd and b_is_tbd:
65 return True
66 elif a_is_tbd or b_is_tbd:
67 return False
68 else:
69 return self.dt == other.dt
70
71 def __lt__(self, other):
72 a_is_tbd, b_is_tbd = self.is_tbd(), other.is_tbd()
73 if not a_is_tbd and not b_is_tbd:
74 return self.dt < other.dt
75 if not a_is_tbd and b_is_tbd:
76 return True
77 else:
78 # (a_is_tbd and not b_is_tbd) or (a_is_tbd and b_is_tbd)
79 return False
80
81 def is_tbd(self):
82 return ConferenceDate.TBD_VAL == self.dt
83
84 def in_past(self):
85 return self < ConferenceDate(datetime.now())
86
87 def in_past_style(self):
88 return 'color: red' if self.in_past() else None
89
90
91@total_ordering
92class Conference(object):
93 def __init__(self, name, url, location, deadline, start, end=None):
94 self.name = name
95 self.url = url
96 self.location = location
97 self.deadline = ConferenceDate(deadline)
98 self.start = ConferenceDate(start)
99 self.end = self.start if end is None else ConferenceDate(end)
100
101 if self.end < self.start:
102 die('start before end for {0}'.format(self.name))
103
104 @classmethod
105 def make_td(cls, contents, style=None):
106 _style = ''
107 if style is not None:
108 _style = ' style="{0}"'.format(style)
109 return '<td{0}>{1}</td>'.format(_style, contents)
110
111 def __eq__(self, other):
112 cmps = ('deadline', 'name', 'url', 'location', 'start', 'end')
113 for s in cmps:
114 ag = attrgetter(s)
115 if ag(self) != ag(other):
116 return False
117 return True
118
119 def __lt__(self, other):
120 cmps = ('deadline', 'name', 'url', 'location', 'start', 'end')
121 for s in cmps:
122 ag = attrgetter(s)
123 a, b = ag(self), ag(other)
124 if a < b:
125 return True
126 elif a > b:
127 return False
128 return False
129
130 def html(self):
131 s = ['<tr>']
132 s.append(self.make_td(ConferenceDate.html_date(self.deadline),
133 style=self.deadline.in_past_style()))
134 s.append(self.make_td('<a href="{0}">{1}</a>'.format(
135 self.url, self.name)))
136 s.append(self.make_td(self.location))
137 s.append(self.make_td(ConferenceDate.get_timespan(self.start, self.end)))
138 s.append('</tr>')
139 return ''.join(s)
140
141
142def die(msg, e=None):
143 print(msg, file=sys.stderr)
144 sys.exit(1)
145
146
147def load_conferences(in_f):
148 c = []
149 r = csv.reader(open(in_f, 'r'))
150 for row in r:
151 try:
152 c.append(Conference(*row))
153 except TypeError as e:
154 print('error on {0}'.format(row), file=sys.stderr)
155 die('error message: {0}'.format(e.message))
156 return c
157
158
159def main():
160 if len(sys.argv) < 2:
161 die('usage: {0} <CSV file>'.format(sys.argv[0]))
162
163 in_f = sys.argv[1]
164 conferences = load_conferences(in_f)
165 for c in sorted(conferences):
166 print(c.html())
167
168
169if __name__ == '__main__':
170 main()