From: philipp Date: Sun, 20 Jun 2010 13:05:46 +0000 (+0000) Subject: On the way to version 1.3. X-Git-Url: https://git.toastfreeware.priv.at/philipp/winterrodeln/wradmin.git/commitdiff_plain/fe4c965cc475f028333ac47d056921985a869fdf?hp=7a285626986c1f9d6dff81d49f79c6b490288733 On the way to version 1.3. git-svn-id: http://www.winterrodeln.org/svn/servermediawiki/trunk/wradmin@567 7aebc617-e5e2-0310-91dc-80fb5f6d2477 --- diff --git a/wradmin/setup.py b/wradmin/setup.py index 58f8be2..06bdc36 100644 --- a/wradmin/setup.py +++ b/wradmin/setup.py @@ -19,7 +19,7 @@ setup( "AuthKit>=0.4.3,<=0.4.99", "SQLAlchemy>=0.5", "lxml>=2.2", - "matplotlib>=0.9", + # "matplotlib>=0.9", "Babel>=0.9" ], setup_requires=["PasteScript>=1.6.3"], diff --git a/wradmin/wradmin/controllers/rodelbahn.py b/wradmin/wradmin/controllers/rodelbahn.py index 7c3b806..237e6e4 100644 --- a/wradmin/wradmin/controllers/rodelbahn.py +++ b/wradmin/wradmin/controllers/rodelbahn.py @@ -20,6 +20,7 @@ class RodelbahnController(BaseController): def index(self): return render('index.html') + def list(self): "Lists all sledding routes" q = model.meta.Session.query(model.WrSleddingCache) @@ -41,6 +42,9 @@ class RodelbahnController(BaseController): def _wikipage_to_wrsleddingcache(self, sledding_wiki): "Converts a sledding route wiki page to a sledding route wrsleddingcache database record." + # TODO: Use mediawiki.wikipage_to_wrsleddingcache + + sl = model.WrSleddingCache() sl.page_id = sledding_wiki.page_id sl.page_title = to_title(sledding_wiki.page_title) diff --git a/wradmin/wradmin/lib/mediawiki.py b/wradmin/wradmin/lib/mediawiki.py index 378dd80..8ab55f6 100644 --- a/wradmin/wradmin/lib/mediawiki.py +++ b/wradmin/wradmin/lib/mediawiki.py @@ -1,14 +1,18 @@ +#!/usr/bin/python2.5 +# -*- coding: iso-8859-15 -*- +# $Id$ "MediaWiki communication functions" +import datetime +import re from authkit.users import UsersReadOnly, md5 -import datetime -import wradmin.model as model -import wradmin.model.validators import formencode, formencode.national - import logging log = logging.getLogger(__name__) +import wradmin.model as model +import wradmin.model.validators + # Converter functions # ------------------- @@ -22,6 +26,19 @@ def to_unsigned(value): return formencode.validators.Int(min=0).to_python(value) +def from_unsigned(value): + """None -> '' + integer -> unicode""" + if value is None: return '' + return unicode(value) + + +def to_string(value): + "Converts an empty string to None." + if len(value) == 0: return None + return value + + def to_date(value): "Parses a date in the form 'yyy-mm-dd'" return model.validators.DateConverter().to_python(value) @@ -52,17 +69,184 @@ def to_email(value): def to_url(value): - return formencode.validators.URL().to_python(value) + # return formencode.validators.URL().to_python(value) # does not accept URLs with accents + if value == '': return None + if not value.startswith('http'): raise formencode.Invalid('URL does not start with http.', value, None) + return value +# deprecated def to_phone(value): return model.validators.AustrianPhoneNumber(messages={'phoneFormat': u"Telefonnummer %%(value)s muss das Format 0123/456789 oder +43/123/456789 haben"}).to_python(value) +# deprecated def to_phone_info(value): return model.validators.PhoneInfo(messages={'phoneInfo': u"Bitte verwenden Sie ein Format wie '0512/123456 (Schnee Alm)'."}).to_python(value) +def to_walkup_separate(value): + """'Ja', 'Nein', 'Teilweise' -> 1, 0, 0.5. A comment is allowed.""" + v = model.validators.ValueCommentList().to_python(value) + if v is None: return None, None + if len(v) > 1: raise formencode.Invalid('Only one field is allowed.', value, None) + return formencode.validators.DictConverter({u'Ja': 1.0, u'Teilweise': 0.5, u'Nein': 0.0}).to_python(v[0][0]), v[0][1] + + +def to_lift(value): + """Example 'Gondel (nur tagsüber); Taxi'""" + v = model.validators.ValueCommentList().to_python(value) + if v is None: return None, None + has_lift = None + for vv, comment in v: + if vv == u'Nein': + if len(vv) != 1: raise formencode.Invalid('"Nein" kann mit keiner anderen Aufstiegshilfe kombiniert werden.', value, None) + lift = False + elif not vv in [u'Sessellift', u'Gondel', u'Linienbus', u'Taxi', u'Sonstige']: + raise formencode.Invalid(u'"%s" ist keine gültige Aufstiegshilfe.' % vv, vv, None) + else: has_lift = True + return has_lift, value + + +def to_night_light(value): + """Examle: 'Teilweise (im unteren Teil)'""" + v = model.validators.ValueCommentList().to_python(value) + if v is None: return None, None + if len(v) > 1: raise formencode.Invalid('Only one field is allowed.', value, None) + return formencode.validators.DictConverter({u'Ja': 1.0, u'Teilweise': 0.5, u'Nein': 0.0}).to_python(v[0][0]), v[0][1] + + +def to_night_light_days(value): + """Example: '3 (Montag, Mittwoch, Freitag)'""" + v = model.validators.ValueCommentList().to_python(value) + if v is None: return None, None + if len(v) > 1: raise formencode.Invalid('Only one field is allowed.', value, None) + return to_unsigned(v[0][0]), v[0][1] + + +def to_sled_rental(value): + """Example: 'Talstation Serlesbahnan; [[Pinnisalm]]'""" + v = model.validators.ValueCommentList().to_python(value) + if v is None: return None, None + sled_rental = True + if len(v) == 1: + if v[0][0] == 'Nein': return False, None + return True, value + + +def to_cachet(value): + if value == '': return None + elif value == 'Nein': return value + elif value.startswith(u'Tiroler Naturrodelbahn-Gütesiegel '): + p = value.split(" ") + to_unsigned(p[2]) # check if year can be parsed + if not p[3] in ['leicht', 'mittel', 'schwer']: raise formencode.Invalid("Unbekannter Schwierigkeitsgrad", value, None) + return value + else: raise formencode.Invalid("Unbekanntes Gütesiegel", value, None) + + +def to_information_web(value): + if value == 'Nein': return value + to_url(value) # is the URL valid? + return value + + +def to_information_phone(value): + v = model.validators.ValueCommentList().to_python(value) + if v is None: return None + c = formencode.national.InternationalPhoneNumber(default_cc=lambda: 43) + for t in v: + if t[0] == 'Nein': + if len(v) != 1: raise formencode.Invalid("Bei 'Nein' ist nur ein Eintrag erlaubt", value, None) + else: + if c.to_python(t[0]) != t[0]: raise formencode.Invalid(u"Telefonnummer hat nicht das gewünschte Format.", value, None) + if (t[1] is None): raise formencode.Invalid(u"Bei Telefonnummern muss ein Kommentar angegeben werden.", value, None) + return value + + +def to_overnight(value): + """'Nein' -> False, None + -> True, """ + if value == '': return None, None + if value == 'Nein': return False, None + return True, value + + +def from_overnight(is_possible, comment): + """is_possible can be None, True or False + comment has to be a unicode string.""" + if is_possible is None: + assert comment is None + return '' + if not is_possible: + assert comment is None + return u'Nein' + return comment + + +def to_sled_rental_inn(value): + """'Nein' -> False, None + -> True, """ + return to_overnight(value) # same implementation as to_overnight + + +def from_sled_rental_inn(is_possible, comment): + return from_overnight(is_possible, comment) # same implementation + + +def to_forum_id(value): + if value == u'Nein': return 0 + return to_unsigned(value) + + +def to_mobile_provider(value): + """A1; T-Mobile A (gut)""" + model.validators.ValueCommentList().to_python(value) # no exception should be raised. + return value + + +def to_email_list(value): + """Converts a list of email addresses with optional comments to the primary (first) adress, + comment for the primary address and the complete list. + >>> email_primary, email_primary_comment, email_list = to_email_list('first@example.com (Nur Winter); second@example.com') + >>> print email_primary + 'first@example.com' + >>> print email_primary_comment + 'Nur Winter' + >>> print email_list + 'first@example.com (Nur Winter); second@example.com' + """ + v = model.validators.ValueCommentList().to_python(value) + if v is None or len(v) == 0: return None, None, None + for e, c in v: to_email(e) # check for valid addresses + return v[0][0], v[0][1], v + + +def to_phone_list(value): + """Converts a list of internationa telephone number with optional comments to the primary (first) number, + comment for the primary number and the complete list. + >>> phone_primary, phone_primary_comment, phone_list = to_phone_list('+43-699-1234567 (nicht nach 20:00 Uhr); +43-512-123456') + >>> print phone_primary + '+43-699-1234567' + >>> print phone_primary_comment + 'nicht nach 20:00 Uhr' + >>> print phone_list + '+43-699-1234567 (nicht nach 20:00 Uhr); +43-512-123456' + """ + v = model.validators.ValueCommentList().to_python(value) + if v is None or len(v) == 0: return None, None, None + ip = formencode.national.InternationalPhoneNumber(default_cc=lambda: 43) + for p, c in v: ip.to_python(p) # check for valid phone numbers + return v[0][0], v[0][1], v + + +def to_wiki_list(value): + """Validates a list of wiki pages like "[[Birgitzer Alm]]; [[Kemater Alm]]" """ + v = value.split(";") + for w in v: + if not w.startswith('[[') or not w.endswith(']]'): raise formencode.Invalid('No valid wiki page name', value, None) + + def conv(fnct, value, fieldname): "Like one of the to_xxx functions (e.g. to_bool), but adds the field name to the error message" try: return fnct(value) @@ -77,6 +261,417 @@ def unicode_e(exception): return unicode(exception) +def wikipage_to_wrsleddingcache1_2(page_id, page_title, page_text): + """Converts a wiki page about a sledding route to a wradmin.model.WrSleddingCache1_2 class + that can be inserted to the wradmin.model.wrsleddingcache1_2_table. + It needs the wiki page id, the wiki page title and the page text ("old_text") as they come from the database.""" + sl = model.WrSleddingCache1_2() + sl.page_id = page_id + sl.page_title = to_title(page_title) + + # Match Rodelbahnbox + wikitext = page_text + regexp = re.compile(u"\{\{(Rodelbahnbox[^\}]*)\}\}", re.DOTALL) + match = regexp.search(wikitext) + if not match: + raise Exception(u"No 'Rodelbahnbox' found") + box = match.group(1) + + # Process Rodelbahnbox + for property in box.split('|'): + property = property.strip() + if property == u'Rodelbahnbox': continue + key_value = property.split('=') + if len(key_value) != 2: + raise Exception(u"Property '%s' has unexpected format" % key_value) + key = key_value[0].strip() + value = key_value[1].strip() + if key == u'Rodelbahnnummer': pass + elif key == u'Länge': sl.length = conv(to_unsigned, value, u'Länge') + elif key == u'Gehzeit': sl.walktime = conv(to_unsigned, value, u'Gehzeit') + elif key == u'Höhe oben': sl.height_top = conv(to_unsigned, value, u'Höhe oben') + elif key == u'Höhe unten': sl.height_bottom = conv(to_unsigned, value, u'Höhe unten') + elif key == u'Aufstieg getrennt': sl.walkup_separate = conv(to_bool, value, u'Aufstieg getrennt') + elif key == u'Lift': sl.lift = conv(to_bool, value, u'Lift') + elif key == u'Beleuchtung': sl.night_light = conv(to_bool, value, u'Beleuchtung') + elif key == u'Rodelverleih': sl.sledge_rental = conv(to_bool, value, u'Rodelverleih') + elif key == u'Öffentliche Anreise': sl.public_transport = conv(to_bool, value, u'Öffentliche Anreise') + elif key == u'Bild': sl.image = conv(to_string, value, key) + elif key == u'Position': (sl.position_latitude, sl.position_longitude) = conv(to_geo, value, u'Position') # '47.583333 N 15.75 E' + elif key == u'Auskunft': sl.information = conv(to_phone_info, value, u'Auskunft') + elif key == u'In Übersichtskarte': sl.show_in_overview = conv(to_bool, value, u'In Übersichtskarte') + elif key == u'Aufnahmedatum': sl.creation_date = conv(to_date, value, u'Aufnahmedatum') # '2006-03-15' + elif key == u'Lawinengefahr': + # sl.avalanches is not part of the 1.2 sleddingcache table. We store it in the WrSleddingCache1_2 anyway. + sl.avalanches = conv(model.validators.GermanAvalanches().to_python, value, key) + else: raise formencode.Invalid(u"Unbekannte Eigenschaft der Rodelbahnbox: '%s' (mit Wert '%s')" % (key, value), value, None) + sl.under_construction = None + + # Match Forumlink (e.g. {{Forumlink|68}}) + match = re.search(u"\{\{Forumlink\|(\d+)\}\}", wikitext) + if match: sl.forum_id = match.group(1) + + return sl + + +def wikipage_to_wrsleddingcache(wiki_page): + """Converts a sled-route wiki page (wradmin.model.page_table) + to a sledding route wrsleddingcache database record (wradmin.model.wrsleddingcache_table). + Raises a RuntimeError if the format is not OK + sledding_wiki is a column of tabe "page". + Returns the WrSleddingCache class""" + sl = model.WrSleddingCache() + sl.page_id = wiki_page.page_id + sl.page_title = to_title(wiki_page.page_title) + errors = [] # List of errors with localized messages + + # Match Rodelbahnbox + wikitext = wiki_page.old_text + regexp = re.compile(u"\{\{(Rodelbahnbox[^\}]*)\}\}", re.DOTALL) + match = regexp.search(wikitext) + if not match: + raise RuntimeError(_(u"No 'Rodelbahnbox' found")) + box = match.group(1) + + # Process Rodelbahnbox + for property in box.split('|'): + property = property.strip() + if property == u'Rodelbahnbox': continue + key_value = property.split('=') + if len(key_value) != 2: + raise RuntimeError(_(u"Property '%s' has unexpected format") % key_value) + key = key_value[0].strip() + value = key_value[1].strip() + if key in [u'Rodelbahnnummer', u'Lift']: + errors.append(_("Property '%s' is not supported anymore, see %s.") % (key, 'http://www.winterrodeln.org/wiki/Vorlage:Rodelbahnbox')) + elif key == u'Position': (sl.position_latitude, sl.position_longitude) = conv(to_geo, value, key) # '47.583333 N 15.75 E' + elif key == u'Position oben': (sl.top_latitude, sl.top_longitude) = conv(to_geo, value, key) # '47.583333 N 15.75 E' + elif key == u'Höhe oben': sl.top_elevation = conv(to_unsigned, value, key) # '2000' + elif key == u'Position unten': (sl.bottom_latitude, sl.bottom_longitude) = conv(to_geo, value, key) # '47.583333 N 15.75 E' + elif key == u'Höhe unten': sl.bottom_elevation = conv(to_unsigned, value, key) # '1200' + elif key == u'Länge': sl.length = conv(to_unsigned, value, key) # 3500 + elif key == u'Schwierigkeit': sl.difficulty = conv(model.validators.GermanDifficulty().to_python, value, key) # 'mittel' + elif key == u'Lawinen': sl.avalanches = conv(model.validators.GermanAvalanches().to_python, value, key) # 'kaum' + elif key == u'Betreiber': sl.operator = value # 'Max Mustermann' + elif key == u'Öffentliche Anreise': sl.public_transport = conv(model.validators.GermanPublicTransport().to_python, value, key) # 'Mittelmäßig' + elif key == u'Gehzeit': sl.walkup_time = conv(to_unsigned, value, key) # 90 + elif key == u'Aufstieg getrennt': sl.walkup_separate, sl.walkup_separate_comment = conv(to_walkup_separate, value, key) # 'Ja' + elif key == u'Aufstiegshilfe': sl.lift, sl.lift_comment = conv(to_lift, value, key) # 'Gondel (unterer Teil)' + elif key == u'Beleuchtungsanlage': sl.night_light, sl.night_light_comment = conv(to_night_light, value, key) + elif key == u'Beleuchtungstage': sl.night_light_days, sl.night_light_days_comment = conv(to_night_light_days, value, key) # '3 (Montag, Mittwoch, Freitag)' + elif key == u'Rodelverleih': sl.sled_rental, sl.sled_rental_comment = conv(to_sled_rental, value, key) # 'Talstation Serlesbahnan' + elif key == u'Gütesiegel': sl.cachet = conv(to_cachet, value, key) # 'Tiroler Naturrodelbahn-Gütesiegel 2009 mittel' + elif key == u'Webauskunft': sl.information_web = conv(to_information_web, value, key) # 'http://www.nösslachhütte.at/page9.php' + elif key == u'Telefonauskunft': sl.information_phone = conv(to_information_phone, value, key) # '+43-664-5487520 (Mitterer Alm)' + elif key == u'Bild': sl.image = conv(to_string, value, key) + elif key == u'In Übersichtskarte': sl.show_in_overview = conv(to_bool, value, key) + elif key == u'Forumid': sl.forum_id = conv(to_forum_id, value, key) + else: raise formencode.Invalid(u"Unbekannte Eigenschaft der Rodelbahnbox: '%s' (mit Wert '%s')" % (key, value), value, None) + sl.under_construction = None + return sl + + +def wrSleddingCache1_2_to_WrSleddingCache(wrSleddingCache1_2): + """Converts the old WrSleddingCache format (1.2) WrSleddingCache1_2 + to the new format (1.3) WrSleddingCache.""" + wrSleddingCache = model.WrSleddingCache() # Create an object in the new format + wrSleddingCache.page_id = wrSleddingCache1_2.page_id + wrSleddingCache.page_title = wrSleddingCache1_2.page_id + wrSleddingCache.position_latitude = wrSleddingCache1_2.position_latitude + wrSleddingCache.position_longitude = wrSleddingCache1_2.position_longitude + wrSleddingCache.top_latitude = None + wrSleddingCache.top_longitude = None + wrSleddingCache.top_elevation = wrSleddingCache1_2.height_top + wrSleddingCache.bottom_latitude = None + wrSleddingCache.bottom_longitude = None + wrSleddingCache.bottom_elevation = wrSleddingCache1_2.height_bottom + wrSleddingCache.length = wrSleddingCache1_2.length + wrSleddingCache.difficulty = None + if 'avalanches' in dir(wrSleddingCache1_2): wrSleddingCache.avalanches = wrSleddingCache1_2.avalanches + else: wrSleddingCache.avalanches = None + wrSleddingCache.operator = None + if wrSleddingCache1_2.public_transport is None: wrSleddingCache.public_transport = None + else: wrSleddingCache.public_transport = 6 if wrSleddingCache1_2.public_transport else 5 + wrSleddingCache.walkup_time = wrSleddingCache1_2.walktime + if wrSleddingCache1_2.walkup_separate is None: wrSleddingCache.walkup_separate = None + wrSleddingCache.walkup_separate = 1.0 if wrSleddingCache1_2.walkup_separate else 0.0 + wrSleddingCache.walkup_separate_comment = None + wrSleddingCache.lift = wrSleddingCache1_2.lift + if wrSleddingCache1_2.lift: wrSleddingCache.lift_details = "Ja" + else: wrSleddingCache.lift_details = None + if wrSleddingCache1_2.night_light is None: wrSleddingCache.night_light = None + else: wrSleddingCache.night_light = 1.0 if wrSleddingCache1_2.night_light else 0.0 + wrSleddingCache.night_light_comment = None + wrSleddingCache.night_light_days = None + wrSleddingCache.night_light_days_comment = None + wrSleddingCache.sled_rental = wrSleddingCache1_2.sledge_rental + wrSleddingCache.sled_rental_comment = None + wrSleddingCache.cachet = None + wrSleddingCache.information_web = None + if wrSleddingCache1_2.information is None: wrSleddingCache.information_phone = None + else: + m = re.match('^([-\d/\+]{5,}) \((.+)\)', wrSleddingCache1_2.information) + if m is None: raise formencode.Invalid('PhoneInfo is invalid', value, None) + (phone, info) = m.groups() + # check phone + phone = wradmin.model.validators.AustrianPhoneNumber().to_python(phone) + # convert phone + c = formencode.national.InternationalPhoneNumber(default_cc=lambda: 43) + phone = c.to_python(phone) + wrSleddingCache.information_phone = '%s (%s)' % (phone, info) + wrSleddingCache.image = wrSleddingCache1_2.image + wrSleddingCache.show_in_overview = wrSleddingCache1_2.show_in_overview + wrSleddingCache.forum_id = wrSleddingCache1_2.forum_id + wrSleddingCache.under_construction = wrSleddingCache1_2.under_construction + return wrSleddingCache + + +def wrSleddingCache_to_Rodelbahnbox(wrSleddingCache): + """Converts the WrSleddingCache class to the {{Rodelbahnbox}} representation. +wrSleddingCache.cachet +wrSleddingCache.forum_id +wrSleddingCache.image +wrSleddingCache.information_phone +wrSleddingCache.information_web +wrSleddingCache.lift +wrSleddingCache.lift_details +wrSleddingCache.night_light +wrSleddingCache.night_light_comment +wrSleddingCache.night_light_days +wrSleddingCache.night_light_days_comment +wrSleddingCache.show_in_overview +wrSleddingCache.sled_rental +wrSleddingCache.sled_rental_comment +wrSleddingCache.under_construction + """ + keys = [] + values = [] + keys.append(u'Position') + values.append(wradmin.model.validators.Geo().from_python((wrSleddingCache.position_latitude, wrSleddingCache.position_longitude))) + keys.append(u'Position oben') + values.append(wradmin.model.validators.Geo().from_python((wrSleddingCache.top_latitude, wrSleddingCache.top_longitude))) + keys.append(u'Höhe oben') + values.append(from_unsigned(wrSleddingCache.top_elevation)) + keys.append(u'Position unten') + values.append(wradmin.model.validators.Geo().from_python((wrSleddingCache.bottom_latitude, wrSleddingCache.bottom_longitude))) + keys.append(u'Höhe unten') + values.append(from_unsigned(wrSleddingCache.bottom_elevation)) + keys.append(u'Länge') + values.append(from_unsigned(wrSleddingCache.length)) + keys.append(u'Schwierigkeit') + values.append(model.validators.GermanDifficulty().from_python(wrSleddingCache.difficulty)) + keys.append(u'Lawinen') + values.append(model.validators.GermanAvalanches().from_python(wrSleddingCache.avalanches)) + keys.append(u'Betreiber') + values.append(formencode.validators.String().from_python(wrSleddingCache.operator)) + keys.append(u'Öffentliche Anreise') + values.append(model.validators.GermanPublicTransport().from_python(wrSleddingCache.public_transport)) + keys.append(u'Gehzeit') + values.append(from_unsigned(wrSleddingCache.walkup_time)) + keys.append(u'Aufstieg getrennt') + v = model.validators.GermanTristateFloat().from_python(wrSleddingCache.walkup_separate) + if not wrSleddingCache.walkup_separate_comment is None: v += ' (%s)' % wrSleddingCache.walkup_separate_comment + values.append(v) + + b = u""" +| Aufstiegshilfe = Gondel (unterer Teil) +| Beleuchtungsanlage = Ja +| Beleuchtungstage = 3 (Montag, Mittwoch, Freitag) +| Rodelverleih = Ja (Talstation Serlesbahnan) +| Gütesiegel = Tiroler Naturrodelbahn-Gütesiegel 2009 mittel +| Webauskunft = http://www.nösslachhütte.at/page9.php +| Telefonauskunft = +43-664-5487520 (Mitterer Alm) +| Bild = Rodelbahn_Mitterer_Alm_04.jpg +| In Übersichtskarte = Ja +| Forumid = 33 +}} + """ + + c = u""" + keys.append(u'Betreiber') + values.append(formencode.validators.String().from_python(wrInnCache.operator)) + keys.append(u'Sitzplätze') + values.append(from_unsigned(wrInnCache.seats)) + keys.append(u'Übernachtung') + values.append(from_overnight(wrInnCache.overnight, wrInnCache.overnight_comment)) + keys.append(u'Rauchfrei') + values.append(wradmin.model.validators.GermanTristate.from_python((wrInnCache.nonsmoker_area, wrInnCache.smoker_area))) + keys.append(u'Rodelverleih') + values.append(from_sled_rental_inn(wrInnCache.sled_rental, wrInnCache.sled_rental_comment)) + keys.append(u'Handyempfang') + values.append(formencode.validators.String().from_python(wrInnCache.mobile_provider)) + keys.append(u'Homepage') + values.append(formencode.validators.String().from_python(wrInnCache.homepage)) + keys.append(u'E-Mail') + values.append(formencode.validators.String().from_python(wrInnCache.email_list)) + keys.append(u'Telefon') + values.append(formencode.validators.String().from_python(wrInnCache.phone_list)) + keys.append(u'Bild') + values.append(formencode.validators.String().from_python(wrInnCache.image)) + keys.append(u'Rodelbahnen') + values.append(formencode.validators.String().from_python(wrInnCache.sledding_list)) + """ + result = [u'{{Rodelbahnbox'] + for i in xrange(len(keys)): result.append(u'| %-20s = %s' % (keys[i], values[i])) + result.append('}}\n') + return '\n'.join(result) + + +def wikipage_to_wrinncache1_2(page_id, page_title, page_text): + """Converts a wiki page about an inn to an wradmin.model.WrInnCache1_2 class + that can be inserted to the wradmin.model.wrinncache1_2_table. + It uses only text operations and does not query or update the database. + It needs the wiki page id, the wiki page title and the page text ("old_text") as they come from the database.""" + inn = model.WrInnCache1_2() + inn.page_id = page_id + inn.page_title = to_title(page_title) + + # Match Gasthausbox + wikitext = page_text + regexp = re.compile(u"\{\{(Gasthausbox[^\}]*)\}\}", re.DOTALL) + match = regexp.search(wikitext) + if not match: + raise Exception(u"No 'Gasthausbox' found") + box = match.group(1) + + # Process Gashausbox + for property in box.split('|'): + property = property.strip() + if property == u'Gasthausbox': continue + key_value = property.split('=') + if len(key_value) != 2: + raise Exception(u"Property '%s' has unexpected format" % key_value) + key = key_value[0].strip() + value = key_value[1].strip() + if key == u'Gasthausnummer': pass + elif key == u'E-Mail': inn.email = conv(to_email, value, u'E-Mail') + elif key == u'Homepage': inn.homepage = conv(to_url, value, u'Homepage') + elif key == u'Höhe': inn.height = conv(to_unsigned, value, u'Höhe') + elif key == u'Bild': inn.image = conv(to_string, value, key) + elif key == u'Position': inn.position_latitude, inn.position_longitude = conv(to_geo, value, u'Position') # '47.583333 N 15.75 E' + elif key == u'Telefon (Festnetz)': inn.phone = conv(to_phone, value, u'Telefon (Festnetz)') + elif key == u'Telefon (Mobil)': inn.mobile_phone = conv(to_phone, value, u'Telefon (Mobil)') + elif key == u'Rauchfrei': inn.nonsmoker_area, inn.smoker_area = conv(to_tristate, value, u'Rauchfrei') + elif key == u'Aufnahmedatum': inn.creation_date = conv(to_date, value, u'Aufnahmedatum') # '2006-03-15' + else: raise formencode.Invalid(u"Unbekannte Eigenschaft der Gasthausbox: '%s' (mit Wert '%s')" % (key, value), value, None) + inn.under_construction = None + return inn + + +def wikipage_to_wrinncache(wiki_page): + """Converts a inn wiki page (wradmin.model.page_table) to a wrinncache database record + (wradmin.model.wrinncache_table).""" + inn = model.WrInnCache() + inn.page_id = inn_wiki.page_id + inn.page_title = to_title(inn_wiki.page_title) + + # Match Gasthausbox + wikitext = inn_wiki.old_text + regexp = re.compile(u"\{\{(Gasthausbox[^\}]*)\}\}", re.DOTALL) + match = regexp.search(wikitext) + if not match: + raise Exception(u"No 'Gasthausbox' found") + box = match.group(1) + + # Process Gashausbox + for property in box.split('|'): + property = property.strip() + if property == u'Gasthausbox': continue + key_value = property.split('=') + if len(key_value) != 2: + raise Exception(u"Property '%s' has unexpected format" % key_value) + key = key_value[0].strip() + value = key_value[1].strip() + if key == u'Position': (inn.position_latitude, inn.position_longitude) = conv(to_geo, value, key) # '47.583333 N 15.75 E' + elif key == u'Höhe': inn.position_elevation = conv(to_unsigned, value, key) + elif key == u'Operator': inn.operator = conv(to_string, value, key) + elif key == u'Sitzplätze': inn.seats = conv(to_unsigned, value, key) + elif key == u'Übernachtung': inn.overnight, inn.overnight_comment = conv(to_overnight, value, key) + elif key == u'Rauchfrei': inn.nonsmoker_area, inn.smoker_area = conv(to_tristate, value, key) + elif key == u'Rodelverleih': inn.sled_rental, inn.sled_rental_comment = conv(to_sled_rental_inn, value, key) + elif key == u'Handyempfang': inn.mobile_provider = conv(to_mobile_provider, value, key) + elif key == u'Homepage': inn.homepage = conv(to_information_web, value, key) + elif key == u'E-Mail': inn.email, inn.email_comment, inn.email_list = conv(to_email_list, value, key) + elif key == u'Telefon': inn.phone, inn.phone_comment, inn.phone_list = conv(to_phone_list, value, key) + elif key == u'Bild': inn.image = conv(to_string, value, key) + elif key == u'Rodelbahnen': inn.sledding_list = conv(to_sledding_list, value, key) + else: raise formencode.Invalid(u"Unbekannte Eigenschaft der Gasthausbox: '%s' (mit Wert '%s')" % (key, value), value, None) + inn.under_construction = None + return inn + + +def wrInnCache1_2_to_WrInnCache(wrInnCache1_2): + """Converts the old WrInnCache format to the new format.""" + wrInnCache = model.WrInnCache() # Create an object in the new format + wrInnCache.page_id = wrInnCache1_2.page_id + wrInnCache.page_title = wrInnCache1_2.page_id + wrInnCache.position_latitude = wrInnCache1_2.position_latitude + wrInnCache.position_longitude = wrInnCache1_2.position_longitude + wrInnCache.position_elevation = wrInnCache1_2.height + wrInnCache.operator = None + wrInnCache.seats = None + wrInnCache.overnight = None + wrInnCache.overnight_comment = None + wrInnCache.smoker_area = wrInnCache1_2.smoker_area + wrInnCache.nonsmoker_area = wrInnCache1_2.nonsmoker_area + wrInnCache.sled_rental = None + wrInnCache.sled_rental_comment = None + wrInnCache.mobile_provider = None + wrInnCache.homepage = wrInnCache1_2.homepage + wrInnCache.email = wrInnCache1_2.email + wrInnCache.email_comment = None + wrInnCache.email_list = wrInnCache1_2.email + phone_list = [] + c = formencode.national.InternationalPhoneNumber(default_cc=lambda: 43) + if not wrInnCache1_2.phone is None: phone_list.append(c.to_python(wrInnCache1_2.phone)) + if not wrInnCache1_2.mobile_phone is None: phone_list.append(c.to_python(wrInnCache1_2.mobile_phone)) + if len(phone_list) >= 1: wrInnCache.phone = phone_list[0] + else: wrInnCache.phone = None + wrInnCache.phone_comment = None + wrInnCache.phone_list = "; ".join(phone_list) + wrInnCache.image = wrInnCache1_2.image + wrInnCache.sledding_list = None + wrInnCache.under_construction = wrInnCache1_2.under_construction + return wrInnCache + + +def wrInnCache_to_Gasthausbox(wrInnCache): + """Converts the WrInnCache class to the {{Gasthausbox}} representation.""" + keys = [] + values = [] + keys.append(u'Position') + values.append(wradmin.model.validators.Geo().from_python((wrInnCache.position_latitude, wrInnCache.position_longitude))) + keys.append(u'Höhe') + values.append(from_unsigned(wrInnCache.position_elevation)) + keys.append(u'Betreiber') + values.append(formencode.validators.String().from_python(wrInnCache.operator)) + keys.append(u'Sitzplätze') + values.append(from_unsigned(wrInnCache.seats)) + keys.append(u'Übernachtung') + values.append(from_overnight(wrInnCache.overnight, wrInnCache.overnight_comment)) + keys.append(u'Rauchfrei') + values.append(wradmin.model.validators.GermanTristate.from_python((wrInnCache.nonsmoker_area, wrInnCache.smoker_area))) + keys.append(u'Rodelverleih') + values.append(from_sled_rental_inn(wrInnCache.sled_rental, wrInnCache.sled_rental_comment)) + keys.append(u'Handyempfang') + values.append(formencode.validators.String().from_python(wrInnCache.mobile_provider)) + keys.append(u'Homepage') + values.append(formencode.validators.String().from_python(wrInnCache.homepage)) + keys.append(u'E-Mail') + values.append(formencode.validators.String().from_python(wrInnCache.email_list)) + keys.append(u'Telefon') + values.append(formencode.validators.String().from_python(wrInnCache.phone_list)) + keys.append(u'Bild') + values.append(formencode.validators.String().from_python(wrInnCache.image)) + keys.append(u'Rodelbahnen') + values.append(formencode.validators.String().from_python(wrInnCache.sledding_list)) + result = [u'{{Gasthausbox'] + for i in xrange(len(keys)): result.append(u'| %-17s = %s' % (keys[i], values[i])) + result.append('}}\n') + return '\n'.join(result) + + + # User management # --------------- diff --git a/wradmin/wradmin/model/__init__.py b/wradmin/wradmin/model/__init__.py index f1839b0..2953011 100644 --- a/wradmin/wradmin/model/__init__.py +++ b/wradmin/wradmin/model/__init__.py @@ -10,6 +10,9 @@ def init_model(engine): meta.engine = engine +# Current table definition +# - version 1.2 +# - version 1.3 (no changes) wrreport_table = sa.Table("wrreport", meta.metadata, sa.Column("id", types.Integer, primary_key=True), sa.Column("page_id", types.Integer, schema.ForeignKey('wrsleddingcache.page_id')), @@ -32,7 +35,9 @@ wrreport_table = sa.Table("wrreport", meta.metadata, ) -wrsleddingcache_table = sa.Table("wrsleddingcache", meta.metadata, +# Old table definition +# - version 1.2 +wrsleddingcache_table1_2 = sa.Table("wrsleddingcache1_2", meta.metadata, sa.Column("page_id", types.Integer, primary_key=True), sa.Column("page_title", types.Unicode(255)), sa.Column("length", types.Integer), @@ -54,7 +59,48 @@ wrsleddingcache_table = sa.Table("wrsleddingcache", meta.metadata, ) -wrinncache_table = sa.Table("wrinncache", meta.metadata, +# Current table definition +# - version 1.3 (changes made from version 1.2) +wrsleddingcache_table = sa.Table("wrsleddingcache", meta.metadata, + sa.Column("page_id", types.Integer, primary_key=True), + sa.Column("page_title", types.Unicode(255)), + sa.Column("position_latitude", types.Float), + sa.Column("position_longitude", types.Float), + sa.Column("top_latitude", types.Float), + sa.Column("top_longitude", types.Float), + sa.Column("top_elevation", types.Integer), + sa.Column("bottom_latitude", types.Float), + sa.Column("bottom_longitude", types.Float), + sa.Column("bottom_elevation", types.Integer), + sa.Column("length", types.Integer), + sa.Column("difficulty", types.Integer), + sa.Column("avalanches", types.Integer), + sa.Column("operator", types.Unicode(255)), + sa.Column("public_transport", types.Integer), + sa.Column("walkup_time", types.Integer), + sa.Column("walkup_separate", types.Float), + sa.Column("walkup_separate_comment", types.Unicode(255)), + sa.Column("lift", types.Boolean), + sa.Column("lift_details", types.Unicode(255)), + sa.Column("night_light", types.Float), + sa.Column("night_light_comment", types.Unicode(255)), + sa.Column("night_light_days", types.Integer), + sa.Column("night_light_days_comment", types.Unicode(255)), + sa.Column("sled_rental", types.Boolean), + sa.Column("sled_rental_comment", types.Unicode(255)), + sa.Column("cachet", types.Unicode(255)), + sa.Column("information_web", types.Unicode(255)), + sa.Column("information_phone", types.Unicode(255)), + sa.Column("image", types.Unicode(255)), + sa.Column("show_in_overview", types.Boolean), + sa.Column("forum_id", types.Integer), + sa.Column("under_construction", types.Boolean), + ) + + +# Old table definition +# - version 1.2 +wrinncache_table1_2 = sa.Table("wrinncache1_2", meta.metadata, sa.Column("page_id", types.Integer, primary_key=True), sa.Column("page_title", types.Unicode(255)), sa.Column("height", types.Integer), @@ -71,6 +117,35 @@ wrinncache_table = sa.Table("wrinncache", meta.metadata, ) +# Current table definition +# - version 1.3 (changes made from version 1.2) +wrinncache_table = sa.Table("wrinncache", meta.metadata, + sa.Column("page_id", types.Integer, primary_key=True), + sa.Column("page_title", types.Unicode(255)), + sa.Column("position_latitude", types.Float), + sa.Column("position_longitude", types.Float), + sa.Column("position_elevation", types.Integer), + sa.Column("seats", types.Integer), + sa.Column("overnight", types.Boolean), + sa.Column("overnight_comment", types.Unicode(255)), + sa.Column("smoker_area", types.Boolean), + sa.Column("nonsmoker_area", types.Boolean), + sa.Column("sled_rental", types.Boolean), + sa.Column("sled_rental_comment", types.Unicode(255)), + sa.Column("mobile_provider", types.Unicode), + sa.Column("homepage", types.Unicode(255)), + sa.Column("email", types.Unicode(255)), + sa.Column("email_comment", types.Unicode(255)), + sa.Column("email_list", types.Unicode), + sa.Column("phone", types.Unicode(30)), + sa.Column("phone_comment", types.Unicode(255)), + sa.Column("phone_list", types.Unicode), + sa.Column("image", types.Unicode(255)), + sa.Column("sledding_list", types.Unicode), + sa.Column("under_construction", types.Boolean), + ) + + page_table = sa.Table("page", meta.metadata, sa.Column("page_id", types.Integer, primary_key=True), sa.Column("page_namespace", types.Integer, nullable=False), @@ -120,16 +195,35 @@ class WrReport(object): pass +# Old version (not mapped) +class WrSleddingCache1_2(object): + pass + + class WrSleddingCache(object): pass +# Old version (not mapped) +class WrInnCache1_2(object): + pass + + class WrInnCache(object): pass +# Page (not mapped) +class Page(object): + pass + + orm.mapper(WrReport, wrreport_table) # We could add a relation but we don't need it yet: # orm.mapper(WrSleddingCache, wrsleddingcache_table, properties = {'reports': orm.relation(WrReport, backref='sledding')}) orm.mapper(WrSleddingCache, wrsleddingcache_table) orm.mapper(WrInnCache, wrinncache_table) + +# Old tables +orm.mapper(WrSleddingCache1_2, wrsleddingcache_table1_2) +orm.mapper(WrInnCache1_2, wrinncache_table1_2) diff --git a/wradmin/wradmin/model/validators.py b/wradmin/wradmin/model/validators.py index 9f555e8..e733948 100644 --- a/wradmin/wradmin/model/validators.py +++ b/wradmin/wradmin/model/validators.py @@ -59,7 +59,7 @@ class DateConverter(GenericDateTimeConverter): GenericDateTimeConverter.__init__(self, '%Y-%m-%d', **keywords) def _to_python(self, value, state): - GenericDateTimeConverter._to_python(self, value, state).date() + return GenericDateTimeConverter._to_python(self, value, state).date() class GermanTristate(formencode.FancyValidator): @@ -206,6 +206,7 @@ class MultiGeo(formencode.FancyValidator): return "\n".join(result) +# deprecated class AustrianPhoneNumber(formencode.FancyValidator): """ Validates and converts phone numbers to +##/###/####### or +##/###/#######-### (having an extension) @@ -252,6 +253,7 @@ class AustrianPhoneNumber(formencode.FancyValidator): return '+%s/%s-%s' % (country, phone, extension) +# Deprecated class PhoneInfo(formencode.FancyValidator): "Validates a info of the form '0644/1234567 (Schnee Alm)'" messages = {'infoFormat': "'%%(value)s' is no valid format, please use a form like '0644/1234567 (Schnee Alm)'"} @@ -266,3 +268,222 @@ class PhoneInfo(formencode.FancyValidator): phone = AustrianPhoneNumber().to_python(phone) return "%s (%s)" % (phone, info) + + +class ValueComment(formencode.FancyValidator): + """Converts value with a potentially optional comment to a python tuple: + u'' <=> (None, None) + u'value' <=> (u'value', None) + u'value (comment)' <=> (u'value', u'comment')""" + + def __init__(self, comment_is_optional=True): + self.comment_is_optional = comment_is_optional + + def _to_python(self, value, state): + self.assert_string(value, state) + if value == u'': return None + left = value.find('(') + right = value.rfind(')') + if left < 0 and right < 0: + if not comment_is_optional: raise formencode.Invalid(u'Mandatory comment not present', value, state) + return value, None + elif left >= 0 and right >= 0 and left < right: + return value[:left].strip(), value[left+1:right].strip() + else: raise formencode.Invalid(u'Invalid format', value, state) + + def from_python(self, value): + assert len(value) == 2 + if value[0] is None: + assert value[1] == None + return u'' + if value[1] is None: + return value[0] + return u'%s (%s)' % (value[0], value[1]) + + +class ValueCommentList(formencode.FancyValidator): + """A value-comment list looks like one of the following lines: + value + value (optional comment) + value1; value2 + value1; value2 (optional comment) + value1 (optional comment1); value2 (optional comment2); value3 (otional comment3) + value1 (optional comment1); value2 (optional comment2); value3 (otional comment3) + This function returns the value-comment list as list of tuples: + [(u'value1', u'comment1'), (u'value2', None)] + If no comment is present, None is specified. + For an empty string, None is returned.""" + messages = {'infoFormat': "'%%(value)s' is no valid format, please use a form like 'value1 (optional comment1); value2 (optional comment2)'"} + + def _to_python(self, value, state): + self.assert_string(value, state) + value_options = [s.strip() for s in value.split(';')] + result = [] + for value_option in value_options: + left = value_option.find('(') + right = value_option.rfind(')') + if left < 0 and right < 0: + result.append((value_option, None)) + elif left >= 0 and right >= 0 and left < right: + result.append((value_option[:left].strip(), value_option[left+1:right].strip())) + else: raise formencode.Invalid(self.message('infoFormat', state) % {'value': value}, value, state) + return result + + def _from_python(self, value, state): + result = [] + for v, c in value: + if c is None: result.append(v) + else: result.append('%s (%s)' % (v, c)) + return "; ".join(result) + + +class GermanDifficulty(formencode.FancyValidator): + """Converts the difficulty represented in a number from 1 to 3 (or None) + to a German representation: + u'' <=> None + u'leicht' <=> 1 + u'mittel' <=> 2 + u'schwer' <=> 3""" + dc = formencode.validators.DictConverter({u'leicht': 1, u'mittel': 2, u'schwer': 3}) + + def _to_python(self, value, state): + """Value has to be one of u'', u'leicht', u'mittel' or u'schwer': + u'' => None + u'leicht' => 1 + u'mittel' => 2 + u'schwer' => 3""" + self.assert_string(value, state) + return self.dc.to_python(value) + + def from_python(self, value): + """value has to be one of None, 1, 2, 3: + None => u'' + 1 => u'leicht' + 2 => u'mittel' + 3 => u'schwer'""" + if value is None: return u'' + return self.dc.from_python(value) + + +class GermanAvalanches(formencode.FancyValidator): + """Converts the avalanches property represented as number from 1 to 4 (or None) + to a German representation: + u'' <=> None + u'kaum' <=> 1 + u'selten' <=> 2 + u'gelegentlich' <=> 3 + u'häufig' <=> 4""" + dc = formencode.validators.DictConverter({u'kaum': 1, u'selten': 2, u'gelegentlich': 3, u'häufig': 4}) + + def _to_python(self, value, state): + """value has to be one of u'', u'kaum', u'selten', u'gelegentlich', u'häufig': + u'' => None + u'kaum' => 1 + u'selten' => 2 + u'gelegentlich' => 3 + u'häufig' => 4""" + self.assert_string(value, state) + return self.dc.to_python(value) + + def from_python(self, value): + """value has to be one of None, 1, 2, 3, 4: + None => u'' + 1 => u'kaum' + 2 => u'selten' + 3 => u'gelegentlich' + 4 => u'häufig'""" + if value is None: return u'' + return self.dc.from_python(value) + + +class GermanPublicTransport(formencode.FancyValidator): + """Converts the public_transport property represented as number from 1 to 6 (or None) + to a German representation: + u'' <=> None + u'Sehr gut' <=> 1 + u'Gut' <=> 2 + u'Mittelmäßig' <=> 3 + u'Schlecht' <=> 4 + u'Nein' <=> 5 + u'Ja' <=> 6""" + dc = formencode.validators.DictConverter({u'Sehr gut': 1, u'Gut': 2, u'Mittelmäßig': 3, u'Schlecht': 4, u'Nein': 5, u'Ja': 6}) + + def _to_python(self, value, state): + """value has to be one of u'', u'Sehr gut', u'Gut', u'Mittelmäßig', u'Schlecht', u'Nein', u'Ja': + u'' => None + u'Sehr gut' => 1 + u'Gut' => 2 + u'Mittelmäßig' => 3 + u'Schlecht' => 4 + u'Nein' => 5 + u'Ja' => 6""" + self.assert_string(value, state) + return self.dc.to_python(value) + + def from_python(self, value): + """value has to be one of None, 1, 2, 3, 4, 5, 6: + None => u'' + 1 => u'Sehr gut' + 2 => u'Gut' + 3 => u'Mittelmäßig' + 4 => u'Schlecht' + 5 => u'Nein' + 6 => u'Ja'""" + if value is None: return u'' + return self.dc.from_python(value) + + +class GermanTristateFloat(formencode.FancyValidator): + """Converts the a property with the possible values 0.0, 0.5, 1.0 or None + to a German text: + u'' <=> None + u'Ja' <=> 1.0 + u'Teilweise' <=> 0.5 + u'Nein' <=> 0.0""" + dc = formencode.validators.DictConverter({u'Ja': 1.0, u'Teilweise': 0.5, u'Nein': 0.0}) + + def _to_python(self, value, state): + """value has to be one of u'', u'Ja', u'Teilweise', u'Nein': + u'' => None + u'Ja' => 1.0 + u'Teilweise' => 0.5 + u'Nein' => 0.0""" + self.assert_string(value, state) + return self.dc.to_python(value) + + def from_python(self, value): + """value has to be one of None, 0.0, 0.5, 1.0: + None => u'' + 0.0 => u'Nein' + 0.5 => u'Teilweise' + 1.0 => u'Ja'""" + if value is None: return u'' + return self.dc.from_python(value) + + +class GermanTristateFloatComment(formencode.FancyValidator): + """Converts the a property with the possible values 0.0, 0.5, 1.0 or None and an optional comment + in parenthesis to a German text: + u'' <=> (None, None + u'Ja' <=> (1.0, None + u'Teilweise' <=> (0.5, None + u'Nein' <=> (0.0, None + u'Ja (aber schmal)' <=> (1.0, u'aber schmal') + u'Teilweise (oben)' <=> (0.5, u'oben') + u'Nein (aber breit)' <=> (0.0, u'aber breit') + """ + tf = GermanTristateFloat() + + def _to_python(self, value, state): + self.assert_string(value, state) + return self.dc.to_python(value) + + def from_python(self, value): + """value has to be one of None, 0.0, 0.5, 1.0: + None => u'' + 0.0 => u'Nein' + 0.5 => u'Teilweise' + 1.0 => u'Ja'""" + if value is None: return u'' + return self.dc.from_python(value) + diff --git a/wradmin/wradmin/templates/rodelbahn_list.html b/wradmin/wradmin/templates/rodelbahn_list.html index b9ffe04..eb77fe8 100644 --- a/wradmin/wradmin/templates/rodelbahn_list.html +++ b/wradmin/wradmin/templates/rodelbahn_list.html @@ -50,7 +50,7 @@ ${h.bool(s.walkup_separate)} ${h.bool(s.lift)} ${h.bool(s.night_light)} - ${h.bool(s.sledge_rental)} + ${h.bool(s.sled_rental)} ${h.bool(s.public_transport)} ${s.image} ${s.position_latitude} diff --git a/wradmin/wradmin/templates/rodelbahn_view.html b/wradmin/wradmin/templates/rodelbahn_view.html index 10fa685..52d7da4 100644 --- a/wradmin/wradmin/templates/rodelbahn_view.html +++ b/wradmin/wradmin/templates/rodelbahn_view.html @@ -53,7 +53,7 @@ Rodelverleih - ${h.bool(c.sledding.sledge_rental)} + ${h.bool(c.sledding.sled_rental)} Öffentliche Anreise diff --git a/wradmin/wradmin/templates/wrgpxtool.html b/wradmin/wradmin/templates/wrgpxtool.html index dc1992f..05147b0 100644 --- a/wradmin/wradmin/templates/wrgpxtool.html +++ b/wradmin/wradmin/templates/wrgpxtool.html @@ -14,7 +14,7 @@

WRGPX-Werkzeug

-

Achtung: Da das WRGPX Format noch in Arbeit ist, ist diese Seite natürlich auch noch nicht fertig!

+

Achtung: Da das WRGPX Format noch in Arbeit ist, ist diese Seite natürlich auch noch nicht fertig!

WRGPX steht für "Winterrodeln GPX". Hier können Sie eine .gpx Datei auf ihre Gültigkeit untersuchen.

diff --git a/wradmin/wradmin/tests/test_lib.py b/wradmin/wradmin/tests/test_lib.py index c764688..df55e02 100644 --- a/wradmin/wradmin/tests/test_lib.py +++ b/wradmin/wradmin/tests/test_lib.py @@ -1,4 +1,117 @@ +#!/usr/bin/python2.5 +# -*- coding: iso-8859-15 -*- +# $Id$ import wradmin.lib +import wradmin.model + + +def test_wikipage_to_wrsleddingcache1_2(): + wiki_page = wradmin.model.Page() + wiki_page.page_id = 7 + wiki_page.page_title = u"Kemater Alm" + wiki_page.old_text = u""" +Text above +{{Rodelbahnbox +| Bild = Rodelbahn_Mitterer_Alm_04.jpg +| Position = 47.203959 N 11.308052 E +| Länge = 3500 +| Gehzeit = 90 +| Höhe oben = 2000 +| Höhe unten = 1200 +| Aufstieg getrennt = Ja +| Lift = Nein +| Beleuchtung = Nein +| Rodelverleih = Ja +| Öffentliche Anreise = Nein +| Lawinengefahr = kaum +| Auskunft = 0664/5487520 (Mitterer Alm) +| In Übersichtskarte = Ja +}} +Text below""" + sledding_cache = wradmin.lib.mediawiki.wikipage_to_wrsleddingcache1_2(wiki_page) + assert sledding_cache.page_id == 7 + assert sledding_cache.page_title == u"Kemater Alm" + assert sledding_cache.length == 3500 + assert sledding_cache.walktime == 90 + assert sledding_cache.height_top == 2000 + assert sledding_cache.height_bottom == 1200 + assert sledding_cache.walkup_separate == True + assert sledding_cache.lift == False + assert sledding_cache.night_light == False + assert sledding_cache.sledge_rental == True + assert sledding_cache.public_transport == False + assert sledding_cache.image == u"Rodelbahn_Mitterer_Alm_04.jpg" + assert sledding_cache.position_latitude == 47.203959 + assert sledding_cache.position_longitude == 11.308052 + assert sledding_cache.information == u"+43/664/5487520 (Mitterer Alm)" + # assert sledding_cache.forum_id + # assert sledding_cache.under_construction + assert sledding_cache.show_in_overview == True + + +def test_wikipage_to_wrsleddingcache(): + wiki_page = wradmin.model.Page() + wiki_page.page_id = 7 + wiki_page.page_title = u"Kemater Alm" + wiki_page.old_text = u""" +Text above +{{Rodelbahnbox +| Position = 47.203959 N 11.308052 E +| Position oben = +| Höhe oben = 1700 +| Position unten = +| Höhe unten = 1200 +| Länge = 3500 +| Schwierigkeit = mittel +| Lawinen = kaum +| Betreiber = Max Mustermann +| Öffentliche Anreise = Mittelmäßig +| Gehzeit = 90 +| Aufstieg getrennt = Ja +| Aufstiegshilfe = Gondel (unterer Teil) +| Beleuchtungsanlage = Ja +| Beleuchtungstage = 3 (Montag, Mittwoch, Freitag) +| Rodelverleih = Ja (Talstation Serlesbahnan) +| Gütesiegel = Tiroler Naturrodelbahn-Gütesiegel 2009 mittel +| Webauskunft = http://www.nösslachhütte.at/page9.php +| Telefonauskunft = +43-664-5487520 (Mitterer Alm) +| Bild = Rodelbahn_Mitterer_Alm_04.jpg +| In Übersichtskarte = Ja +| Forumid = 33 +}} +Text below""" + sledding_cache = wradmin.lib.mediawiki.wikipage_to_wrsleddingcache(wiki_page) + assert sledding_cache.page_id == 7 + assert sledding_cache.page_title == u"Kemater Alm" + + assert sledding_cache.position_latitude == 47.203959 + assert sledding_cache.position_longitude == 11.308052 + assert sledding_cache.top_latitude == 47.203959 + assert sledding_cache.top_longitude == 11.308052 + assert sledding_cache.top_elevation == 2000 + assert sledding_cache.bottom_latitude == 47.203959 + assert sledding_cache.bottom_longitude == 11.308052 + assert sledding_cache.bottom_elevation == 1200 + + assert sledding_cache.length == 3500 + assert sledding_cache.walktime == 90 + assert sledding_cache.walkup_separate == 1.0 + sa.Column("walkup_separate_comment", types.Unicode(255)), + assert sledding_cache.lift == False + sa.Column("lift_details", types.Unicode(255)), + assert sledding_cache.night_light == 1.0 + sa.Column("night_light_days", types.Integer), + sa.Column("night_light_days_comment", types.Unicode(255)), + assert sledding_cache.sled_rental == True + assert sledding_cache.public_transport == 3 + assert sledding_cache.avalanche = 1 + assert sledding_cache.image == u"Rodelbahn_Mitterer_Alm_04.jpg" + assert sledding_cache.information == u"+43/664/5487520 (Mitterer Alm)" + assert sledding_cache.forum_threadid = 33 + assert sledding_cache.show_in_overview == True + + # assert sledding_cache.under_construction + def test_mediawiki_users(): users = wradmin.lib.mediawiki.MediaWikiUsers(True) diff --git a/wradmin/wradmin/tests/test_models.py b/wradmin/wradmin/tests/test_models.py index 01ca6cf..96ca739 100644 --- a/wradmin/wradmin/tests/test_models.py +++ b/wradmin/wradmin/tests/test_models.py @@ -72,4 +72,13 @@ def test_PhoneInfo(): v.to_python(n) # has to throw an exception assert False, u"The telephone info '%s' should throw an exception." % n except formencode.Invalid: pass - \ No newline at end of file + +def test_ValueCommentList(): + v = wradmin.model.validators.ValueCommentList() + assert v.to_python('abc') == [('abc', None)] + assert v.to_python(u'abc def') == [(u'abc def', None)] + assert v.to_python('value (comment)') == [('value', 'comment')] + assert v.to_python(u'value (comment)') == [(u'value', u'comment')] + assert v.to_python('value1 (comment); value2') == [('value1', 'comment'), ('value2', None)] + assert v.to_python('value1 (comment1); value2; value3 (comment3)') == [('value1', 'comment1'), ('value2', None), ('value3', 'comment3')] + assert v.to_python('value1 (comment1); value2 (test (not easy))') == [('value1', 'comment1'), ('value2', 'test (not easy)')] \ No newline at end of file