2 # -*- coding: iso-8859-15 -*-
5 """This module contains winterrodeln specific functions that are prcocessing the MediaWiki markup.
9 import wrpylib.wrvalidators
10 import wrpylib.mwmarkup
13 def _conv(fnct, value, fieldname):
15 Like one of the to_xxx functions (e.g. to_bool), but adds the field name to the error message"""
16 try: return fnct(value)
17 except formencode.Invalid as e: raise formencode.Invalid(u"Conversion error in field '%s': %s" % (fieldname, unicode(e)), e.value, e.state)
20 def rodelbahnbox_to_sledrun(wikitext, sledrun=None):
21 """Converts a sledrun wiki page containing the {{Rodelbahnbox}}
22 to a sledrun. sledrun may be an instance of WrSledrunCache or an "empty" class (object()) (default).
23 Raises a formencode.Invalid exception if the format is not OK or the Rodelbahnbox is not found.
24 :return: (start, end, sledrun) tuple of the Rodelbahnbox."""
26 class Sledrun(object): pass
30 start, end = wrpylib.mwmarkup.find_template(wikitext, u'Rodelbahnbox')
31 if start is None: raise formencode.Invalid(u"Rodelbahnbox nicht gefunden", wikitext, None)
32 template_title, properties = wrpylib.mwmarkup.split_template(wikitext[start:end])
35 for key, value in properties.iteritems():
36 if key == u'Position': sledrun.position_latitude, sledrun.position_longitude = _conv(wrpylib.wrvalidators.GeoNone().to_python, value, key) # '47.583333 N 15.75 E'
37 elif key == u'Position oben': sledrun.top_latitude, sledrun.top_longitude = _conv(wrpylib.wrvalidators.GeoNone().to_python, value, key) # '47.583333 N 15.75 E'
38 elif key == u'Höhe oben': sledrun.top_elevation = _conv(wrpylib.wrvalidators.UnsignedNone().to_python, value, key) # '2000'
39 elif key == u'Position unten': sledrun.bottom_latitude, sledrun.bottom_longitude = _conv(wrpylib.wrvalidators.GeoNone().to_python, value, key) # '47.583333 N 15.75 E'
40 elif key == u'Höhe unten': sledrun.bottom_elevation = _conv(wrpylib.wrvalidators.UnsignedNone().to_python, value, key) # '1200'
41 elif key == u'Länge': sledrun.length = _conv(wrpylib.wrvalidators.UnsignedNone().to_python, value, key) # 3500
42 elif key == u'Schwierigkeit': sledrun.difficulty = _conv(wrpylib.wrvalidators.GermanDifficulty().to_python, value, key) # 'mittel' elif key == u'Lawinen': sledrun.avalanches = _conv(wrpylib.wrvalidators.GermanAvalanches().to_python, value, key) # 'kaum'
43 elif key == u'Lawinen': sledrun.avalanches = _conv(wrpylib.wrvalidators.GermanAvalanches().to_python, value, key) # 'kaum'
44 elif key == u'Betreiber': sledrun.operator = _conv(wrpylib.wrvalidators.UnicodeNone().to_python, value, key) # 'Max Mustermann'
45 elif key == u'Öffentliche Anreise': sledrun.public_transport = _conv(wrpylib.wrvalidators.GermanPublicTransport().to_python, value, key) # 'Mittelmäßig'
46 elif key == u'Aufstieg möglich': sledrun.walkup_possible = _conv(wrpylib.wrvalidators.GermanBoolNone().to_python, value, key) # 'Ja'
47 elif key == u'Aufstieg getrennt': sledrun.walkup_separate, sledrun.walkup_separate_comment = _conv(wrpylib.wrvalidators.GermanTristateFloatComment().to_python, value, key) # 'Ja'
48 elif key == u'Gehzeit': sledrun.walkup_time = _conv(wrpylib.wrvalidators.UnsignedNone().to_python, value, key) # 90
49 elif key == u'Aufstiegshilfe': sledrun.lift, sledrun.lift_details = _conv(wrpylib.wrvalidators.GermanLift().to_python, value, key) # 'Gondel (unterer Teil)'
50 elif key == u'Beleuchtungsanlage': sledrun.night_light, sledrun.night_light_comment = _conv(wrpylib.wrvalidators.GermanTristateFloatComment().to_python, value, key)
51 elif key == u'Beleuchtungstage': sledrun.night_light_days, sledrun.night_light_days_comment = _conv(wrpylib.wrvalidators.UnsignedCommentNone(7).to_python, value, key) # '3 (Montag, Mittwoch, Freitag)'
52 elif key == u'Rodelverleih': sledrun.sled_rental, sledrun.sled_rental_comment = _conv(wrpylib.wrvalidators.SledRental().to_python, value, key) # 'Talstation Serlesbahnan'
53 elif key == u'Gütesiegel': sledrun.cachet = _conv(wrpylib.wrvalidators.GermanCachet().to_python, value, key) # 'Tiroler Naturrodelbahn-Gütesiegel 2009 mittel'
54 elif key == u'Webauskunft': sledrun.information_web = _conv(wrpylib.wrvalidators.UrlNeinNone().to_python, value, key) # 'http://www.nösslachhütte.at/page9.php'
55 elif key == u'Telefonauskunft': sledrun.information_phone = _conv(wrpylib.wrvalidators.PhoneCommentListNeinLoopNone(comments_are_optional=False).to_python, value, key) # '+43-664-5487520 (Mitterer Alm)'
56 elif key == u'Bild': sledrun.image = _conv(wrpylib.wrvalidators.UnicodeNone().to_python, value, key)
57 elif key == u'In Übersichtskarte': sledrun.show_in_overview = _conv(wrpylib.wrvalidators.GermanBoolNone().to_python, value, key)
58 elif key == u'Forumid': sledrun.forum_id = _conv(wrpylib.wrvalidators.UnsignedNeinNone().to_python, value, key)
59 else: raise formencode.Invalid(u"Unbekannte Eigenschaft der Rodelbahnbox: '%s' (mit Wert '%s')" % (key, value), value, None)
60 return start, end, sledrun
63 def sledrun_to_rodelbahnbox(sledrun, version):
64 """Converts a sledrun class to the {{Rodelbahnbox}} representation.
65 The sledrun class has to have properties like position_latitude, ...
66 See the table sledruncache for field (column) values.
67 :param sledrun: an arbitrary class that contains the right properties
68 :param version: a string specifying the version of the rodelbahnbox zu produce.
69 Version '1.3' and '1.4' are supported."""
72 keys.append(u'Position')
73 values.append(wrpylib.wrvalidators.GeoNone().from_python((sledrun.position_latitude, sledrun.position_longitude)))
74 keys.append(u'Position oben')
75 values.append(wrpylib.wrvalidators.GeoNone().from_python((sledrun.top_latitude, sledrun.top_longitude)))
76 keys.append(u'Höhe oben')
77 values.append(wrpylib.wrvalidators.UnsignedNone().from_python(sledrun.top_elevation))
78 keys.append(u'Position unten')
79 values.append(wrpylib.wrvalidators.GeoNone().from_python((sledrun.bottom_latitude, sledrun.bottom_longitude)))
80 keys.append(u'Höhe unten')
81 values.append(wrpylib.wrvalidators.UnsignedNone().from_python(sledrun.bottom_elevation))
83 values.append(wrpylib.wrvalidators.UnsignedNone().from_python(sledrun.length))
84 keys.append(u'Schwierigkeit')
85 values.append(wrpylib.wrvalidators.GermanDifficulty().from_python(sledrun.difficulty))
86 keys.append(u'Lawinen')
87 values.append(wrpylib.wrvalidators.GermanAvalanches().from_python(sledrun.avalanches))
88 keys.append(u'Betreiber')
89 values.append(wrpylib.wrvalidators.UnicodeNone().from_python(sledrun.operator))
90 keys.append(u'Öffentliche Anreise')
91 values.append(wrpylib.wrvalidators.GermanPublicTransport().from_python(sledrun.public_transport))
93 keys.append(u'Aufstieg möglich')
94 values.append(wrpylib.wrvalidators.GermanBoolNone().from_python(sledrun.walkup_possible))
95 keys.append(u'Aufstieg getrennt')
96 values.append(wrpylib.wrvalidators.GermanTristateFloatComment().from_python((sledrun.walkup_separate, sledrun.walkup_separate_comment)))
97 keys.append(u'Gehzeit')
98 values.append(wrpylib.wrvalidators.UnsignedNone().from_python(sledrun.walkup_time))
99 keys.append(u'Aufstiegshilfe')
100 values.append(wrpylib.wrvalidators.GermanLift().from_python((sledrun.lift, sledrun.lift_details)))
101 keys.append(u'Beleuchtungsanlage')
102 values.append(wrpylib.wrvalidators.GermanTristateFloatComment().from_python((sledrun.night_light, sledrun.night_light_comment)))
103 keys.append(u'Beleuchtungstage')
104 values.append(wrpylib.wrvalidators.UnsignedCommentNone(max=7).from_python((sledrun.night_light_days, sledrun.night_light_days_comment)))
105 keys.append(u'Rodelverleih')
106 values.append(wrpylib.wrvalidators.SledRental().from_python((sledrun.sled_rental, sledrun.sled_rental_comment)))
107 keys.append(u'Gütesiegel')
108 values.append(wrpylib.wrvalidators.GermanCachet().from_python(sledrun.cachet))
109 keys.append(u'Webauskunft')
110 values.append(wrpylib.wrvalidators.UrlNeinNone().from_python(sledrun.information_web))
111 keys.append(u'Telefonauskunft')
112 values.append(wrpylib.wrvalidators.PhoneCommentListNeinLoopNone(comments_are_optional=False).from_python(sledrun.information_phone))
114 values.append(wrpylib.wrvalidators.UnicodeNone().from_python(sledrun.image))
115 keys.append(u'In Übersichtskarte')
116 values.append(wrpylib.wrvalidators.GermanBoolNone().from_python(sledrun.show_in_overview))
117 keys.append(u'Forumid')
118 values.append(wrpylib.wrvalidators.UnsignedNeinNone().from_python(sledrun.forum_id))
119 return wrpylib.mwmarkup.create_template(u'Rodelbahnbox', [], keys, values, True, 20)
122 def gasthausbox_to_inn(wikitext, inn=None):
123 """Converts a inn wiki page containing a {{Gasthausbox}} to an inn.
124 raises a formencode.Invalid exception if an error occurs.
125 :return: (start, end, inn) tuple."""
127 class Inn(object): pass
131 start, end = wrpylib.mwmarkup.find_template(wikitext, u'Gasthausbox')
132 if start is None: raise formencode.Invalid(u"No 'Gasthausbox' found", wikitext, None)
133 template_title, properties = wrpylib.mwmarkup.split_template(wikitext[start:end])
136 for key, value in properties.iteritems():
137 if key == u'Position': inn.position_latitude, inn.position_longitude = _conv(wrpylib.wrvalidators.GeoNone().to_python, value, key) # '47.583333 N 15.75 E'
138 elif key == u'Höhe': inn.position_elevation = _conv(wrpylib.wrvalidators.UnsignedNone().to_python, value, key)
139 elif key == u'Betreiber': inn.operator = _conv(wrpylib.wrvalidators.UnicodeNone().to_python, value, key)
140 elif key == u'Sitzplätze': inn.seats = _conv(wrpylib.wrvalidators.UnsignedNone().to_python, value, key)
141 elif key == u'Übernachtung': inn.overnight, inn.overnight_comment = _conv(wrpylib.wrvalidators.BoolUnicodeTupleValidator().to_python, value, key)
142 elif key == u'Rauchfrei': inn.nonsmoker_area, inn.smoker_area = _conv(wrpylib.wrvalidators.GermanTristateTuple().to_python, value, key)
143 elif key == u'Rodelverleih': inn.sled_rental, inn.sled_rental_comment = _conv(wrpylib.wrvalidators.BoolUnicodeTupleValidator().to_python, value, key)
144 elif key == u'Handyempfang': inn.mobile_provider = _conv(wrpylib.wrvalidators.ValueCommentListNeinLoopNone().to_python, value, key)
145 elif key == u'Homepage': inn.homepage = _conv(wrpylib.wrvalidators.UrlNeinNone().to_python, value, key)
146 elif key == u'E-Mail': inn.email_list = _conv(wrpylib.wrvalidators.EmailCommentListNeinLoopNone(allow_masked_email=True).to_python, value, key)
147 elif key == u'Telefon': inn.phone_list = _conv(wrpylib.wrvalidators.PhoneCommentListNeinLoopNone(comments_are_optional=True).to_python, value, key)
148 elif key == u'Bild': inn.image = _conv(wrpylib.wrvalidators.UnicodeNone().to_python, value, key)
149 elif key == u'Rodelbahnen': inn.sledding_list = _conv(wrpylib.wrvalidators.WikiPageListLoopNone().to_python, value, key)
150 else: raise formencode.Invalid(u"Unbekannte Eigenschaft der Gasthausbox: '%s' (mit Wert '%s')" % (key, value), value, None)
151 return start, end, inn
154 def inn_to_gasthausbox(inn):
155 """Converts the inn class to the {{Gasthausbox}} representation."""
158 keys.append(u'Position')
159 values.append(wrpylib.wrvalidators.GeoNone().from_python((inn.position_latitude, inn.position_longitude)))
161 values.append(wrpylib.wrvalidators.UnsignedNone().from_python(inn.position_elevation))
162 keys.append(u'Betreiber')
163 values.append(wrpylib.wrvalidators.UnicodeNone().from_python(inn.operator))
164 keys.append(u'Sitzplätze')
165 values.append(wrpylib.wrvalidators.UnsignedNone().from_python(inn.seats))
166 keys.append(u'Übernachtung')
167 values.append(wrpylib.wrvalidators.BoolUnicodeTupleValidator().from_python((inn.overnight, inn.overnight_comment)))
168 keys.append(u'Rauchfrei')
169 values.append(wrpylib.wrvalidators.GermanTristateTuple().from_python((inn.nonsmoker_area, inn.smoker_area)))
170 keys.append(u'Rodelverleih')
171 values.append(wrpylib.wrvalidators.BoolUnicodeTupleValidator().from_python((inn.sled_rental, inn.sled_rental_comment)))
172 keys.append(u'Handyempfang')
173 values.append(wrpylib.wrvalidators.ValueCommentListNeinLoopNone().from_python(inn.mobile_provider))
174 keys.append(u'Homepage')
175 values.append(wrpylib.wrvalidators.UrlNeinNone().from_python(inn.homepage))
176 keys.append(u'E-Mail')
177 values.append(wrpylib.wrvalidators.EmailCommentListNeinLoopNone(allow_masked_email=True).from_python(inn.email_list))
178 keys.append(u'Telefon')
179 values.append(wrpylib.wrvalidators.PhoneCommentListNeinLoopNone(comments_are_optional=True).from_python(inn.phone_list))
181 values.append(wrpylib.wrvalidators.UnicodeNone().from_python(inn.image))
182 keys.append(u'Rodelbahnen')
183 values.append(wrpylib.wrvalidators.WikiPageListLoopNone().from_python(inn.sledding_list))
184 result = [u'{{Gasthausbox']
185 return wrpylib.mwmarkup.create_template(u'Gasthausbox', [], keys, values, True)
188 def find_template_latlon_ele(wikitext, template_title):
189 """Finds the first occurance of the '{{template_title|47.076207 N 11.453553 E|1890}}' template
190 and returns the tuple (start, end, lat, lon, ele) or (None, None, None, None, None) if the
191 template was not found. If the template has no valid format, an exception is thrown."""
192 start, end = wrpylib.mwmarkup.find_template(wikitext, template_title)
193 if start is None: return (None,) * 5
194 title, params = wrpylib.mwmarkup.split_template(wikitext[start:end])
195 lat, lon = wrpylib.wrvalidators.GeoNone().to_python(params[u'1'].strip())
196 ele = wrpylib.wrvalidators.UnsignedNone().to_python(params[u'2'].strip())
197 return start, end, lat, lon, ele
200 def create_template_latlon_ele(template_title, lat, lon, ele):
201 geo = wrpylib.wrvalidators.GeoNone().from_python((lat, lon))
202 if len(geo) == 0: geo = u' '
203 ele = wrpylib.wrvalidators.UnsignedNone().from_python(ele)
204 if len(ele) == 0: ele = u' '
205 return wrpylib.mwmarkup.create_template(template_title, [geo, ele])
208 def find_template_PositionOben(wikitext):
209 """Same as find_template_latlon_ele with template '{{Position oben|47.076207 N 11.453553 E|1890}}'"""
210 return find_template_latlon_ele(wikitext, u'Position oben')
213 def create_template_PositionOben(lat, lon, ele):
214 return create_template_latlon_ele(u'Position, oben', lat, lon, ele)
217 def find_template_PositionUnten(wikitext):
218 """Same as find_template_latlon_ele with template '{{Position unten|47.076207 N 11.453553 E|1890}}'"""
219 return find_template_latlon_ele(wikitext, u'Position unten')
222 def find_template_unsigned(wikitext, template_title):
223 """Finds the first occurance of the '{{template_title|1890}}' template
224 and returns the tuple (start, end, unsigned_value) or (None, None, None) if the
225 template was not found. If the template has no valid format, an exception is thrown."""
226 start, end = wrpylib.mwmarkup.find_template(wikitext, template_title)
227 if start is None: return (None,) * 3
228 title, params = wrpylib.mwmarkup.split_template(wikitext[start:end])
229 unsigned_value = wrpylib.wrvalidators.UnsignedNone().to_python(params[u'1'].strip())
230 return start, end, unsigned_value
233 def create_template_unsigned(template_title, unsigned):
234 unsigned = wrpylib.wrvalidators.UnsignedNone().from_python(unsigned)
235 if len(unsigned) == 0: unsigned = u' '
236 return wrpylib.mwmarkup.create_template(template_title, [unsigned])
239 def find_template_Hoehenunterschied(wikitext):
240 """Same as find_template_unsigned with template '{{Höhenunterschied|350}}'"""
241 return find_template_unsigned(wikitext, u'Höhenunterschied')
244 def create_template_Hoehenunterschied(ele_diff):
245 return create_template_unsigned(u'Höhenunterschied', ele_diff)
248 def find_template_Bahnlaenge(wikitext):
249 """Same as find_template_unsigned with template '{{Bahnlänge|4500}}'"""
250 return find_template_unsigned(wikitext, u'Bahnlänge')
253 def create_template_Bahnlaenge(length):
254 return create_template_unsigned(u'Bahnlänge', length)
257 def find_template_Gehzeit(wikitext):
258 """Same as find_template_unsigned with template '{{Gehzeit|60}}'"""
259 return find_template_unsigned(wikitext, u'Gehzeit')
262 def create_template_Gehzeit(walkup_time):
263 return create_template_unsigned(u'Gehzeit', walkup_time)
266 def find_template_Forumlink(wikitext):
267 """Same as find_template_unsigned with template '{{Forumlink|26}}'"""
268 start, end = wrpylib.mwmarkup.find_template(wikitext, u'Forumlink')
269 if start is None: return (None,) * 3
270 title, params = wrpylib.mwmarkup.split_template(wikitext[start:end])
271 forumid = params[u'1'].strip()
272 if forumid == u'<nummer einfügen>': unsigned_value = None
273 else: unsigned_value = wrpylib.wrvalidators.UnsignedNone().to_python(forumid)
274 return start, end, unsigned_value
275 # return find_template_unsigned(wikitext, u'Forumlink')
278 def find_template_Parkplatz(wikitext):
279 """Same as find_template_latlon_ele with template '{{Parkplatz|47.076207 N 11.453553 E|1890}}'"""
280 return find_template_latlon_ele(wikitext, u'Parkplatz')
283 def find_template_Haltestelle(wikitext):
284 """Finds the first occurance of the '{{Haltestelle|Ortsname|Haltestellenname|47.076207 N 11.453553 E|1890}}' template
285 and returns the tuple (start, end, city, stop, lat, lon, ele) or (None, None, None, None, None, None, None) if the
286 template was not found. If the template has no valid format, an exception is thrown."""
287 start, end = wrpylib.mwmarkup.find_template(wikitext, u'Haltestelle')
288 if start is None: return (None,) * 7
289 title, params = wrpylib.mwmarkup.split_template(wikitext[start:end])
290 city = wrpylib.wrvalidators.UnicodeNone().to_python(params[u'1'].strip())
291 stop = wrpylib.wrvalidators.UnicodeNone().to_python(params[u'2'].strip())
292 lat, lon = wrpylib.wrvalidators.GeoNone().to_python(params[u'3'].strip())
293 ele = wrpylib.wrvalidators.UnsignedNone().to_python(params[u'4'].strip())
294 return start, end, city, stop, lat, lon, ele
297 def find_all_templates(wikitext, find_func):
298 """Returns a list of return values of find_func that searches for a template.
300 >>> find_all_tempaltes(wikitext, find_template_Haltestelle)
301 Returns an empty list if the template was not found at all.
304 result = find_func(wikitext)
305 start, end = result[:2]
306 while start is not None:
307 results.append(result)
308 result = find_func(wikitext[end:])
309 if result[0] is None:
312 start = result[0] + end
314 result = (start, end) + result[2:]