Attachment 'eventcal-090.py'
Download 1 """
2 eventcal.py Version 0.90 2005. 11. 15.
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 For more information, please visit http://moinmoin.wikiwikiweb.de/MacroMarket/EventCalendar
10
11 Usage:
12 To insert events, enclose the information about the event records with 'eventcal' parser.
13 E.g.,
14 {{{#!eventcal
15 = [Title] =
16 [Start Date] ... [End Date]
17 [Start Time] ... [End Time]
18 }}}
19
20 [Title] should be enclosed with heading marker ('='), double quatation mark ("), wiki italic or bold ('', ''')
21 Title can be omitted and it will be titled as 'No Title'
22 e.g., == Title ==, === Title ===, "Title", ''Title'', '''Title'''
23
24 [Start|End Date] should be in YYYY/MM/DD or YYYY-MM-DD. End date can be omitted.
25 e.g, 2005/10/20, 2005-10-20
26
27 [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.
28 e.g., 08:00, 12:00, 18:00
29
30 In the parsing block of eventcal, it pops out first two date formatted text (startdate and enddate),
31 two time formatted text (starttime, endtime), and quoted or heading titie.
32
33 It ignores further occurrence of the targeted string.
34 The order of each fields (date, time, title) does not matter .
35 The start date|time should precede the end date|time in the occurrence respectively.
36
37 You can separate the events starting a '##eventcal' line without any trailing characters.
38 E.g.,
39 {{{#!eventcal
40 = 1st Event =
41 StartDate1 ~ EndDate1
42 ##eventcal
43 = 2nd Event =
44 StartDate2 ~ EndDate2
45 ...
46 }}}
47
48 Features:
49 Shows the event information in a parsed format.
50 Validates the date, time format.
51
52
53 Notes:
54 Much buggy.. :please report bugs and suggest your ideas.
55
56
57
58 """
59
60 import datetime, re
61 from MoinMoin.parser import wiki
62 import urllib
63 from MoinMoin import config
64
65 class Parser:
66
67 def __init__(self, raw, request, **kw):
68 self.lines = raw
69 self.request = request
70 option_args = {}
71
72 for arg in kw.get('format_args', '').split():
73 try:
74 key, value = arg.split('=')
75 option_args[key.strip()] = value.strip()
76 except ValueError:
77 pass
78
79 self.bgcolor = option_args.get('bgcolor', '')
80 self.icon = option_args.get('icon', '')
81 self.view = option_args.get('view', '')
82
83
84 def format(self, formatter):
85 """ Send the "parsed" text.
86 """
87
88 self.formatter = formatter
89
90 # need help on regular expressions for more efficient/flexible form
91 regex_date = r'(\d{4}[/-]\d{2}[/-]\d{2})'
92 regex_time = r'(\d{2}[:]\d{2})'
93 regex_title = r'["]+(\s*.*?)["]+|[\']{2,5}(\s*.*?)[\']{2,5}|^[=]+(\s*.*?)[=]+$'
94 regex_bgcolor = r'^##bgcolor (\s*.*?)$'
95 regex_icon = r'^##icon (\s*.*?)$'
96 regex_view= r'^##view (\s*.*?)$'
97 regex_eventcal = r'[\{]{3}#!eventcal[^\n]*(\s*.*?[^\}]+)[\}]{3}'
98
99 msg = ''
100
101 # compile regular expression objects
102 pattern_date = re.compile(regex_date, re.UNICODE)
103 pattern_time = re.compile(regex_time, re.UNICODE)
104 pattern_title = re.compile(regex_title, re.UNICODE + re.DOTALL + re.MULTILINE)
105 pattern_bgcolor = re.compile(regex_bgcolor, re.UNICODE + re.MULTILINE + re.IGNORECASE)
106 pattern_icon = re.compile(regex_icon, re.UNICODE + re.MULTILINE + re.IGNORECASE)
107 pattern_view = re.compile(regex_view, re.UNICODE + re.MULTILINE + re.IGNORECASE)
108 pattern_eventcal = re.compile(regex_eventcal, re.UNICODE + re.MULTILINE + re.IGNORECASE)
109
110 # ignores #!eventcal blocks
111 lines = pattern_eventcal.sub(r'\n##eventcal\n\1\n##eventcal\n', self.lines)
112
113 # split events
114 linesall = lines.split(u'##eventcal\n')
115
116 for lines in linesall:
117
118 linetemp = lines.strip()
119 if not linetemp:
120 continue
121
122 title = ''
123 startdate = ''
124 enddate = ''
125 starttime = ''
126 endtime = ''
127 icon = self.icon
128 bgcolor = self.bgcolor
129 view = self.view
130
131 # retrieve view
132 match = pattern_view.search(lines)
133 if match:
134 view = match.group(0)[7:]
135
136 if view == 'none':
137 # no need to check valididy
138 self.printoutput(lines, '', '', '', '', 1, '', '', view)
139 continue
140
141 # retrieve date
142 match = pattern_date.findall(lines)
143
144 if not len(match):
145 msg = 'at least one date field should be specified'
146 self.printoutput(lines, 'Parse Error', msg, '', '', 0, bgcolor, icon, view)
147 continue
148
149 # (month, day)-only date should be handled later
150
151 startdate = match[0]
152 if len(match) > 1:
153 enddate = match[1]
154
155 # retrieve time
156 match = pattern_time.findall(lines)
157
158 if len(match) >= 2:
159 starttime = match[0]
160 endtime = match[1]
161 elif len(match) == 0:
162 starttime = ''
163 endtime = ''
164 else:
165 msg = 'no or 2 time field should be specified'
166 self.printoutput(lines, 'Parse Error', msg, '', '', 0, bgcolor, icon, view)
167 continue
168
169 # retrieve title
170 match = pattern_title.search(lines)
171
172 if not match:
173 title = 'No title'
174 else:
175 for item in match.groups():
176 if item:
177 title = item
178 break
179
180 # retrieve bgcolor
181 match = pattern_bgcolor.search(lines)
182 if match:
183 bgcolor = match.group(0)[10:]
184
185 # retrieve icon
186 match = pattern_icon.search(lines)
187 if match:
188 icon = match.group(0)[7:]
189
190 # if no enddate, it's 1-day event
191 if (not enddate) and (starttime and endtime):
192 enddate = startdate
193
194 # check the validity of date/time
195 try:
196 syear, smonth, sday = getdatefield(startdate
197 )
198 if enddate:
199 eyear, emonth, eday = getdatefield(enddate
200 )
201 except:
202 msg = 'invalid date format'
203 self.printoutput(lines, 'Parse Error', msg, '', '', 0, bgcolor, icon, view)
204 continue
205
206 if startdate and enddate:
207 if datetime.date(syear, smonth, sday) > datetime.date(eyear, emonth, eday):
208 msg = 'startdate should precede enddate'
209 self.printoutput(lines, 'Parse Error', msg, '', '', 0, bgcolor, icon, view)
210 continue
211
212 if starttime and endtime:
213 try:
214 shour, smin = gettimefield(starttime
215 )
216 ehour, emin = gettimefield(endtime
217 )
218 except:
219 msg = 'invalid time format'
220 self.printoutput(lines, 'Parse Error', msg, '', '', 0, bgcolor, icon, view)
221 continue
222
223 if startdate == enddate:
224 if datetime.time(shour, smin) > datetime.time(ehour, emin):
225 msg = 'starttime should precede endtime'
226 self.printoutput(lines, 'Parse Error', msg, '', '', 0, bgcolor, icon, view)
227 continue
228
229 # format output
230 fromstring = '%s %s' % (startdate, starttime)
231 if enddate:
232 tostring = '%s %s' % (enddate, endtime)
233 else:
234 tostring = ''
235
236 startdateforbookmark = u'%d%02d%02d' % (syear, smonth, sday)
237
238 self.printoutput(lines, title, fromstring, tostring, startdateforbookmark, 1, bgcolor, icon, view)
239
240 def printoutput(self, lines, title='', fromstring='', tostring='', startdateforbookmark='', successflag=1, bgcolor='', icon='', view='table'):
241
242 if view == u'footnote':
243 self.outputfootnote(lines, title, fromstring, tostring, startdateforbookmark, successflag)
244 elif view == u'erroronly':
245 self.outputerroronly(lines, title, fromstring, tostring, startdateforbookmark, successflag)
246 elif view == u'none':
247 self.outputnone(lines, title, startdateforbookmark)
248 else:
249 self.outputtable(lines, title, fromstring, tostring, startdateforbookmark, successflag, bgcolor, icon)
250
251
252 def outputtable(self, lines, title, fromstring, tostring, startdateforbookmark, successflag, bgcolor='', icon=''):
253
254 formatter = self.formatter
255 # title += u'[%s]' % self.args
256
257 if startdateforbookmark:
258 bookmark = u'%s%s' % (title.replace(' ', ''), startdateforbookmark)
259 # bookmark = urllib.quote_plus(bookmark.encode(config.charset))
260 html = u'<a name="%s"></a>' % bookmark
261 self.request.write(formatter.rawHTML(html))
262
263 html = [
264 u'<table width="100%%" style="border-width:0px;"><tr><td width="100%%" style="border-width:0px; text-align: left; vertical-align: top;">',
265 u'',
266 ]
267
268 html = u'\n'.join(html)
269 self.request.write(formatter.rawHTML(html))
270
271 wikiparser = wiki.Parser( lines, self.request )
272 wikiparser.format( formatter )
273
274 if tostring:
275 fromto = '%s<br>~ %s' % (fromstring.strip(), tostring.strip())
276 else:
277 fromto = '%s' % fromstring.strip()
278
279 if successflag:
280 if icon:
281 flag = icon
282 else:
283 flag = '(!)'
284 else:
285 flag = '{X}'
286
287 if successflag:
288 if bgcolor:
289 bgcolor = u'background-color: %s;' % bgcolor
290 else:
291 bgcolor = u'background-color: #ddffdd;'
292 else:
293 bgcolor = u'background-color: #ff9933;'
294
295 html = [
296 u'</td>',
297 u'<td style="border-width: 0px; padding: 0px; margin: 0px; border-top-width: 1px; width: 4px;"> </td>',
298 u'<td style="border-width:0px; border-left-width: 1px; vertical-align: bottom; padding: 0px; margin: 0px;"><table style="width: 140px; border-width:0px; padding: 0px; margin: 0px;">',
299 u'<tr><td rowspan="2" style="width: 16px; border-width:1px; border-left-width: 0px; border-right-width: 0px; padding: 0px; margin: 0px; vertical-align: top;">',
300 ]
301
302 html = u'\n'.join(html)
303 self.request.write(formatter.rawHTML(html))
304
305 # flag
306 wikiparser = wiki.Parser( '%s' % flag, self.request )
307 wikiparser.format( formatter )
308
309 # title, fromto string
310 html = [
311 u'</td>',
312 u'<td style="border-width:1px; border-left-width: 0px; border-bottom-width: 0px; line-height: 8px; padding: 0px; margin: 0px; %s"' % bgcolor,
313 u'><font style="font-size: 8pt; font-weight: bold;">%s</font></td></tr>' % title.strip(),
314 u'<tr><td style="border-width:1px; border-left-width: 0px; border-top-width: 0px; line-height: 8px; padding: 0px; margin: 0px; text-align: right;"',
315 u'><font style="font-size: 7pt;">%s</font></td></tr></td></tr></table></td></tr></table>' % fromto,
316 ]
317
318 html = u'\n'.join(html)
319 self.request.write(formatter.rawHTML(html))
320
321 def outputerroronly(self, lines, title, fromstring, tostring, startdateforbookmark, successflag):
322
323 formatter = self.formatter
324
325 if tostring:
326 fromto = '%s ~ %s' % (fromstring.strip(), tostring.strip())
327 else:
328 fromto = '%s' % fromstring.strip()
329
330 if startdateforbookmark:
331 bookmark = u'%s%s' % (title.replace(' ', ''), startdateforbookmark)
332 # bookmark = urllib.quote_plus(bookmark.encode(config.charset))
333 html = u'<a name="%s"></a>' % bookmark
334 self.request.write(formatter.rawHTML(html))
335
336 if successflag:
337 wikiparser = wiki.Parser( lines, self.request )
338 wikiparser.format( formatter )
339 else:
340
341 html = [
342 u'<table width="100%%" style="border-width:0px;"><tr><td width="100%%" style="border-width:0px; text-align: left; vertical-align: top;">',
343 u'',
344 ]
345
346 html = u'\n'.join(html)
347 self.request.write(formatter.rawHTML(html))
348
349 wikiparser = wiki.Parser( lines, self.request )
350 wikiparser.format( formatter )
351
352 flag = '{X}'
353
354 html = [
355 u'</td>',
356 u'<td style="border-width: 0px; padding: 0px; margin: 0px; border-top-width: 1px; width: 4px;"> </td>',
357 u'<td style="border-width:0px; border-left-width: 1px; vertical-align: bottom; padding: 0px; margin: 0px;"><table style="width: 140px; border-width:0px; padding: 0px; margin: 0px;">',
358 u'<tr><td rowspan="2" style="width: 16px; border-width:1px; border-left-width: 0px; border-right-width: 0px; padding: 0px; margin: 0px; vertical-align: top;">',
359 ]
360
361 html = u'\n'.join(html)
362 self.request.write(formatter.rawHTML(html))
363
364 # flag
365 wikiparser = wiki.Parser( '%s' % flag, self.request )
366 wikiparser.format( formatter )
367
368 # title, fromto string
369 html = [
370 u'</td>',
371 u'<td style="border-width:1px; border-left-width: 0px; border-bottom-width: 0px; line-height: 8px; padding: 0px; margin: 0px;"',
372 u'><font style="font-size: 8pt; font-weight: bold;">%s</font></td></tr>' % title.strip(),
373 u'<tr><td style="border-width:1px; border-left-width: 0px; border-top-width: 0px; line-height: 8px; padding: 0px; margin: 0px; text-align: right;"',
374 u'><font style="font-size: 7pt;">%s</font></td></tr></td></tr></table></td></tr></table>' % fromto,
375 ]
376
377 html = u'\n'.join(html)
378 self.request.write(formatter.rawHTML(html))
379
380 def outputnone(self, lines, title, startdateforbookmark):
381
382 formatter = self.formatter
383
384 if startdateforbookmark:
385 bookmark = u'%s%s' % (title.replace(' ', ''), startdateforbookmark)
386 # bookmark = urllib.quote_plus(bookmark.encode(config.charset))
387 html = u'<a name="%s"></a>' % bookmark
388 self.request.write(formatter.rawHTML(html))
389
390 wikiparser = wiki.Parser( lines, self.request )
391 wikiparser.format( formatter )
392
393 def outputfootnote(self, lines, title, fromstring, tostring, startdateforbookmark, successflag):
394
395 formatter = self.formatter
396
397 if tostring:
398 fromto = '%s ~ %s' % (fromstring.strip(), tostring.strip())
399 else:
400 fromto = '%s' % fromstring.strip()
401
402 footnote = u'(Event) %s: %s' % (title, fromto)
403 lines = u'%s [[FootNote(%s)]]' % (lines.rstrip(), footnote)
404
405 if startdateforbookmark:
406 bookmark = u'%s%s' % (title.replace(' ', ''), startdateforbookmark)
407 # bookmark = urllib.quote_plus(bookmark.encode(config.charset))
408 html = u'<a name="%s"></a>' % bookmark
409 self.request.write(formatter.rawHTML(html))
410
411 wikiparser = wiki.Parser( lines, self.request )
412 wikiparser.format( formatter )
413
414
415
416 def getdatefield(str_date):
417 str_year = ''
418 str_month = ''
419 str_day = ''
420
421 if len(str_date) == 6:
422 # year+month
423 str_year = str_date[:4]
424 str_month = str_date[4:]
425 str_day = '1'
426
427 elif len(str_date) == 8:
428 # year+month+day
429 str_year = str_date[:4]
430 str_month = str_date[4:6]
431 str_day = str_date[6:]
432
433 elif len(str_date) == 10:
434 # year+?+month+?+day
435 str_year = str_date[:4]
436 str_month = str_date[5:7]
437 str_day = str_date[8:]
438
439 else:
440 raise ValueError
441
442 # It raises exception if the input date is incorrect
443 temp = datetime.date(int(str_year), int(str_month), int(str_day))
444
445 return temp.year, temp.month, temp.day
446
447
448 def gettimefield(str_time):
449 str_hour = ''
450 str_min = ''
451
452 if len(str_time) == 4:
453 # hour+minute
454 str_hour = str_time[:2]
455 str_min = str_time[2:]
456
457 elif len(str_time) == 5:
458 # hour+?+minute
459 str_hour = str_time[:2]
460 str_min = str_time[3:]
461
462 else:
463 raise ValueError
464
465 # It raises exception if the input date is incorrect
466 temp = datetime.time(int(str_hour), int(str_min))
467
468 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.