Attachment 'eventcal-080.py'
Download 1 """
2 eventcal.py Version 0.80 2005. 10. 31.
3
4 This parser gives a parsed format of the event which will be shown at the EventCalendar macro.
5
6 @copyright: 2005 by Seungik Lee <seungiklee<at>gmail.com> http://cds.icu.ac.kr/~silee/
7 @license: GPL
8
9 Usage:
10 To insert an event, enclose the information about ONE event record with 'eventcal' parser.
11 E.g.,
12 {{{#!eventcal
13 = [Title] =
14 [Start Date] ... [End Date]
15 [Start Time] ... [End Time]
16 }}}
17
18 [Title] should be enclosed with heading marker ('='), double quatation mark ("), wiki italic or bold ('', ''')
19 Title can be omitted and it will be titled as 'No Title'
20 e.g., == Title ==, === Title ===, "Title", ''Title'', '''Title'''
21
22 [Start|End Date] should be in YYYY/MM/DD or YYYY-MM-DD. End date can be omitted.
23 e.g, 2005/10/20, 2005-10-20
24
25 [Start|End Time] should be in HH:MM in 24-hour format. Both of start|end Time can be omitted but not either of them.
26 e.g., 08:00, 12:00, 18:00
27
28 In the parsing block of eventcal, it pops out first two date formatted text (startdate and enddate),
29 two time formatted text (starttime, endtime), and quoted or heading titie.
30
31 It ignores further occurrence of the targeted string.
32 The order of each fields (date, time, title) does not matter .
33 The start date|time should precede the end date|time in the occurrence respectively.
34
35 There is no input parameter yet.
36
37 Features:
38 Shows the event information in a parsed format.
39 Validates the date, time format.
40
41 Change Log:
42 Oct. 31, 2005 - Version 0.80
43 - The initial version is released.
44
45 To do list:
46 Clean the ugly codes!!! (need help)
47 raw html codes
48 Date/time Format customization (e.g., 2005/10, Oct. 2005, 18:00, 06:00pm)
49 Custom background color per event
50 Custom icon per event
51 More input parameters
52 Parsing description field
53
54 Notes:
55 Much buggy.. :please report bugs and suggest your ideas.
56
57 Usage Examples:
58
59 {{{#!eventcal
60 === Event Calendar Development === # title
61 * Duration: 2005/10/20 ~ 2005/10/27 # startdate, enddate
62 * It was very hard! # ignored
63 * FYI, today's 2005/10/28 # ignored
64 }}}
65
66 {{{#!eventcal
67 On 2005/10/10 20:00~22:00, we have "3rd Project meeting". Please don't miss it. # startdate, starttime, endtime, title
68 }}}
69
70 {{{#!eventcal
71 '''My Business Trip''' # title
72 From 2005-10-02 to 2005/10/07. See you later~ # startdate, enddate
73 }}}
74
75 {{{#!eventcal
76 Please come to my office on 2005-10-10. Thanks. # (title: 'No Title'), startdate
77 }}}
78
79
80 """
81
82 import datetime, re, wiki
83 import urllib
84 from MoinMoin import config
85
86 class Parser:
87
88 def __init__(self, raw, request, **kw):
89 self.lines = raw
90 self.request = request
91
92 def format(self, formatter):
93 """ Send the "parsed" text.
94 """
95
96 self.formatter = formatter
97
98 # need help on regular expressions for more efficient/flexible form
99 regex_date = r'(\d{4}[/-]\d{2}[/-]\d{2})'
100 regex_time = r'(\d{2}[:]\d{2})'
101 # regex_title = r'["\'=-]+(\s*.*[^"\'=-]+)["\'=-]+'
102 # regex_title = r'["]+ | [\']{2,5} | [=-]+ (\s*.*[^"\'=-]+) [=-]+ | ["]+ | [\']{2,5}'
103 # regex_title = r'[=-]+|[\']{2,5}(\s*.*[^"\'=-]+)[=-]|[\']{2,5}'
104 regex_title = r'["]+(\s*.*?)["]+|[\']{2,}(\s*.*?)[\']{2,}|[=]+(\s*.*?)[=]+'
105
106 msg = ''
107 title = ''
108 startdate = ''
109 enddate = ''
110 starttime = ''
111 endtime = ''
112
113 lines = self.lines
114
115 # retrieve date
116 pattern = re.compile(regex_date, re.UNICODE + re.MULTILINE)
117
118 match = pattern.findall(lines)
119
120 if not len(match):
121 msg = 'at least one date field should be specified'
122 self.printoutput('Parse Error', msg, '', '', 0)
123 return
124
125 # (month, day)-only date should be handled later
126
127 startdate = match[0]
128 if len(match) > 1:
129 enddate = match[1]
130
131 # retrieve time
132 pattern = re.compile(regex_time, re.UNICODE + re.MULTILINE)
133
134 match = pattern.findall(lines)
135
136 if len(match) >= 2:
137 starttime = match[0]
138 endtime = match[1]
139 elif len(match) == 0:
140 starttime = ''
141 endtime = ''
142 else:
143 msg = 'no or 2 time field should be specified'
144 self.printoutput('Parse Error', msg, '', '', 0)
145 return
146
147 # retrieve title
148 pattern = re.compile(regex_title, re.UNICODE + re.MULTILINE + re.DOTALL)
149
150 match = pattern.search(lines)
151
152 if not match:
153 title = 'No title'
154 else:
155 for item in match.groups():
156 if item:
157 title = item
158 break
159
160 # if no enddate, it's 1-day event
161 if (not enddate) and (starttime and endtime):
162 enddate = startdate
163
164
165 # check the validity of date/time
166 try:
167 syear, smonth, sday = getdatefield(startdate
168 )
169 if enddate:
170 eyear, emonth, eday = getdatefield(enddate
171 )
172 except:
173 msg = 'invalid date format'
174 self.printoutput('Parse Error', msg, '', '', 0)
175 return
176
177 if startdate and enddate:
178 if datetime.date(syear, smonth, sday) > datetime.date(eyear, emonth, eday):
179 msg = 'startdate should precede enddate'
180 self.printoutput('Parse Error', msg, '', '', 0)
181 return
182
183 if starttime and endtime:
184 try:
185 shour, smin = gettimefield(starttime
186 )
187 ehour, emin = gettimefield(endtime
188 )
189 except:
190 msg = 'invalid time format'
191 self.printoutput('Parse Error', msg, '', '', 0)
192 return
193
194 if startdate == enddate:
195 if datetime.time(shour, smin) > datetime.time(ehour, emin):
196 msg = 'starttime should precede endtime'
197 self.printoutput('Parse Error', msg, '', '', 0)
198 return
199
200 # format output
201 fromstring = '%s %s' % (startdate, starttime)
202 if enddate:
203 tostring = '%s %s' % (enddate, endtime)
204 else:
205 tostring = ''
206
207 startdateforbookmark = u'%d%02d%02d' % (syear, smonth, sday)
208
209 self.printoutput(title, fromstring, tostring, startdateforbookmark, 1)
210
211 def printoutput(self, title, fromstring, tostring, startdateforbookmark, successflag):
212
213 formatter = self.formatter
214 lines = self.lines
215
216 if startdateforbookmark:
217 bookmark = u'%s%s' % (title.replace(' ', ''), startdateforbookmark)
218 # bookmark = urllib.quote_plus(bookmark.encode(config.charset))
219 html = u'<a name="%s"></a>' % bookmark
220 self.request.write(formatter.rawHTML(html))
221
222 html = [
223 u'<table width="100%%" style="border-width:0px;"><tr><td width="100%%" style="border-width:0px; text-align: left; vertical-align: top;">',
224 u'',
225 ]
226
227 html = u'\n'.join(html)
228 self.request.write(formatter.rawHTML(html))
229
230 wikiparser = wiki.Parser( lines, self.request )
231 wikiparser.format( formatter )
232
233 html = [
234 u'</td>',
235 u'<td style="border-width: 0px; padding: 0px; margin: 0px; border-top-width: 1px; width: 4px;"> </td>',
236 # u'<table width="100%%" height="100%%" style="padding: 0px; margin: 0px;">',
237 # u'<tr><td colspan="2" width="2" style="border-width: 0px; background-color: #c0c0c0;"> </td></tr>',
238 # u'<tr><td width="1"></td><td width="1" style="line-height: 100%%; border-width: 0px; background-color: #c0c0c0;"> </td></tr>',
239 # u'<tr><td colspan="2" style="border-width: 0px; background-color: #c0c0c0;"> </td></tr></table>',
240 # u'<table width="100%%" style="border-width:0px;"><tr><td width="50%%" style="border-width:0px;"> </td>',
241 u'<td style="border-width:0px; border-left-width: 1px; text-align:right; vertical-align: bottom; padding: 0px; margin: 0px;"><table style="border-width:0px; align: right; padding: 0px; margin: 0px;">',
242 u'<tr><td style="border-width:1px; border-left-width: 0px; line-height: 5px; padding: 0px; margin: 0px;" nowrap>',
243 ]
244
245 html = u'\n'.join(html)
246 self.request.write(formatter.rawHTML(html))
247
248 if tostring:
249 fromto = '%s ~ %s' % (fromstring, tostring)
250 else:
251 fromto = '%s' % fromstring
252
253 if successflag:
254 flag = '(!)'
255 else:
256 flag = '{X}'
257
258 wikiparser = wiki.Parser( '%s \'\'\'~-%s-~\'\'\' ~-%s-~' % (flag, title, fromto), self.request )
259 wikiparser.format( formatter )
260
261 html = [
262 #u' <font style="font-size: 8pt;">%s</font>' % msg,
263 u'</td></tr></table></td></tr></table>',
264 u'',
265 ]
266
267 html = u'\n'.join(html)
268
269 self.request.write(formatter.rawHTML(html))
270
271
272 def getdatefield(str_date):
273 str_year = ''
274 str_month = ''
275 str_day = ''
276
277 if len(str_date) == 6:
278 # year+month
279 str_year = str_date[:4]
280 str_month = str_date[4:]
281 str_day = '1'
282
283 elif len(str_date) == 8:
284 # year+month+day
285 str_year = str_date[:4]
286 str_month = str_date[4:6]
287 str_day = str_date[6:]
288
289 elif len(str_date) == 10:
290 # year+?+month+?+day
291 str_year = str_date[:4]
292 str_month = str_date[5:7]
293 str_day = str_date[8:]
294
295 else:
296 raise ValueError
297
298 # It raises exception if the input date is incorrect
299 temp = datetime.date(int(str_year), int(str_month), int(str_day))
300
301 return temp.year, temp.month, temp.day
302
303
304 def gettimefield(str_time):
305 str_hour = ''
306 str_min = ''
307
308 if len(str_time) == 4:
309 # hour+minute
310 str_hour = str_time[:2]
311 str_min = str_time[2:]
312
313 elif len(str_time) == 5:
314 # hour+?+minute
315 str_hour = str_time[:2]
316 str_min = str_time[3:]
317
318 else:
319 raise ValueError
320
321 # It raises exception if the input date is incorrect
322 temp = datetime.time(int(str_hour), int(str_min))
323
324 return temp.hour, temp.minute
Attached Files
To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.You are not allowed to attach a file to this page.