-#!/usr/bin/python3.4
-# -*- coding: iso-8859-15 -*-
-# $Id$
-# $HeadURL$
"""
This module contains functions that convert winterrodeln specific strings (like geographic coordinates) from string
to appropriate python types and the other way round.
import urllib.parse
import re
from collections import OrderedDict, namedtuple
+from email.errors import HeaderParseError
-import mwparserfromhell
+import mwparserfromhell # https://github.com/earwig/mwparserfromhell
-from wrpylib.mwmarkup import template_to_table
+from wrpylib.mwmarkup import format_template_table
# FromToConverter type
def value_comment_from_str(value, value_from_str, comment_from_str, comment_optional=False):
"""Makes it possible to have a mandatory comment in parenthesis at the end of the string."""
- open_brackets = 0
comment = ''
- comment_end_pos = None
- for i, char in enumerate(value[::-1]):
- if char == ')':
- open_brackets += 1
- if open_brackets == 1:
- comment_end_pos = i
- if len(value[-1-comment_end_pos:].rstrip()) > 1:
- raise ValueError('invalid characters after comment')
- elif char == '(':
- open_brackets -= 1
- if open_brackets == 0:
- comment = value[-i:-1-comment_end_pos]
- value = value[:-i-1].rstrip()
- break
+ if value.endswith(')'):
+ open_brackets = 0
+ for i, char in enumerate(value[::-1]):
+ if char == ')':
+ open_brackets += 1
+ elif char == '(':
+ open_brackets -= 1
+ if open_brackets == 0:
+ comment = value[-i:-1]
+ value = value[:-i-1]
+ if len(value) > 1 and value[-1] != ' ':
+ raise ValueError('there has to be a space before the opening bracket of the comment')
+ value = value[:-1]
+ break
+ else:
+ if open_brackets > 0:
+ raise ValueError('bracket mismatch')
+ if not comment_optional:
+ raise ValueError('mandatory comment not found')
else:
- if open_brackets > 0:
- raise ValueError('bracket mismatch')
if not comment_optional:
- raise ValueError('mandatory comment not found')
+ raise ValueError('mandatory comment not found in "{}"'.format(value))
return value_from_str(value), comment_from_str(comment)
# -------------------------------
def opt_tristate_german_comment_from_str(value):
- """Ja, Nein or Vielleicht, optionally with comment in parenthesis."""
+ """Ja, Nein or Teilweise, optionally with comment in parenthesis."""
return value_comment_from_str(value, opt_tristate_german_from_str, opt_str_from_str, True)
# ---------------------
def webauskunft_from_str(value):
+ """Converts a URL or 'Nein' to a tuple
+ 'http://www.example.com/' -> (True, 'http://www.example.com/')
+ 'Nein' -> (False, None)
+ '' -> (None, None)
+
+ :param value: URL or 'Nein'
+ :return: tuple
+ """
return opt_no_german_from_str(value, url_from_str)
def wikipage_from_str(value):
"""Validates wiki page name like '[[Birgitzer Alm]]'.
- The page is not checked for existance.
+ The page is not checked for existence.
An empty string is an error.
'[[Birgitzer Alm]]' => '[[Birgitzer Alm]]'
"""
- if not value.startswith('[[') or not value.endswith(']]'):
+ if re.match(r'\[\[[^\[\]]+]]$', value) is None:
raise ValueError('No valid wiki page name "{}"'.format(value))
return value
"""Takes an email address like 'office@example.com', checks it for correctness and returns it again as string."""
try:
email.headerregistry.Address(addr_spec=value)
- except email.errors.HeaderParseError as e:
+ except HeaderParseError as e:
raise ValueError('Invalid email address: {}'.format(value), e)
return value
lonlat_none = LonLat(None, None)
-def lonlat_from_str(value):
- """Converts a winterrodeln geo string like '47.076207 N 11.453553 E' (being '<latitude> N <longitude> E'
- to the LonLat(lon, lat) named tupel."""
- r = re.match('(\d+\.\d+) N (\d+\.\d+) E', value)
+def lonlat_from_str(value: str) -> LonLat:
+ """Converts a Winterrodeln geo string like '47.076207 N 11.453553 E' (being '<latitude> N <longitude> E'
+ to the LonLat(lon, lat) named tuple."""
+ r = re.match(r'(\d+\.\d+) N (\d+\.\d+) E', value)
if r is None: raise ValueError("Coordinates '{}' have not a format like '47.076207 N 11.453553 E'".format(value))
return LonLat(float(r.groups()[1]), float(r.groups()[0]))
-def lonlat_to_str(value):
+def lonlat_to_str(value: LonLat) -> str:
return '{:.6f} N {:.6f} E'.format(value.lat, value.lon)
# avalanches converter
# --------------------
-AVALANCHES_GERMAN = OrderedDict([(1, 'kaum'), (2, 'selten'), (3, 'gelegentlich'), (4, 'häufig')])
+AVALANCHES_GERMAN = OrderedDict([(1, 'kaum'), (2, 'selten'), (3, 'gelegentlich'), (4, 'häufig')])
def avalanches_german_from_str(value):
'' <=> None
'Nein' <=> []
'Sessellift <=> [('Sessellift', None)]
- 'Gondel (nur bis zur Hälfte)' <=> [('Gondel', 'nur bis zur Hälfte')]
+ 'Gondel (nur bis zur Hälfte)' <=> [('Gondel', 'nur bis zur Hälfte')]
'Sessellift; Taxi' <=> [('Sessellift', None), ('Taxi', None)]
'Sessellift (Wochenende); Taxi (6 Euro)' <=> [('Sessellift', 'Wochenende'), ('Taxi', '6 Euro')]
"""
# public transport converter
# --------------------------
-PUBLIC_TRANSPORT_GERMAN = OrderedDict([(1, 'Sehr gut'), (2, 'Gut'), (3, 'Mittelmäßig'), (4, 'Schlecht'), (5, 'Nein'), (6, 'Ja')])
+PUBLIC_TRANSPORT_GERMAN = OrderedDict([(1, 'Sehr gut'), (2, 'Gut'), (3, 'Mittelmäßig'), (4, 'Schlecht'), (5, 'Nein'), (6, 'Ja')])
def public_transport_german_from_str(value):
# cachet converter
# ----------------
-CACHET_REGEXP = [r'(Tiroler Naturrodelbahn-Gütesiegel) ([12]\d{3}) (leicht|mittel|schwer)$']
+CACHET_REGEXP = [r'(Tiroler Naturrodelbahn-Gütesiegel) ([12]\d{3}) (leicht|mittel|schwer)$']
def single_cachet_german_from_str(value):
def cachet_german_from_str(value):
- """Converts a "Gütesiegel":
+ """Converts a "Gütesiegel":
'' => None
'Nein' => []
- 'Tiroler Naturrodelbahn-Gütesiegel 2009 mittel' => [('Tiroler Naturrodelbahn-Gütesiegel', '2009', 'mittel')]"""
+ 'Tiroler Naturrodelbahn-Gütesiegel 2009 mittel' => [('Tiroler Naturrodelbahn-Gütesiegel', '2009', 'mittel')]"""
return opt_no_german_from_str(value, lambda val: enum_from_str(val, single_cachet_german_from_str), False, [], None)
pass
-def wikibox_from_template(template, name, converter_dict):
- if template.name.strip() != name:
- raise ValueError('Box name has to be "{}"'.format(name))
+def wikibox_from_template(template, converter_dict):
+ """Returns an ordered dict."""
result = OrderedDict()
exceptions_dict = OrderedDict()
# check values
def template_from_str(value, name):
wikicode = mwparserfromhell.parse(value)
- template_list = wikicode.filter_templates(name)
- if len(name) == 0:
+ template_list = wikicode.filter_templates(recursive=False, matches=lambda t: t.name.strip() == name)
+ if len(template_list) == 0:
raise ValueError('No "{}" template was found'.format(name))
if len(template_list) > 1:
raise ValueError('{} "{}" templates were found'.format(len(template_list), name))
def wikibox_from_str(value, name, converter_dict):
template = template_from_str(value, name)
- return wikibox_from_template(template, name, converter_dict)
+ return wikibox_from_template(template, converter_dict)
def wikibox_to_str(value, name, converter_dict):
RODELBAHNBOX_DICT = OrderedDict([
('Position', opt_lonlat_converter), # '47.583333 N 15.75 E'
('Position oben', opt_lonlat_converter), # '47.583333 N 15.75 E'
- ('Höhe oben', opt_uint_converter), # '2000'
+ ('Höhe oben', opt_uint_converter), # '2000'
('Position unten', opt_lonlat_converter), # '47.583333 N 15.75 E'
- ('Höhe unten', opt_uint_converter), # '1200'
- ('Länge', opt_uint_converter), # 3500
+ ('Höhe unten', opt_uint_converter), # '1200'
+ ('Länge', opt_uint_converter), # 3500
('Schwierigkeit', opt_difficulty_german_converter), # 'mittel'
('Lawinen', opt_avalanches_german_converter), # 'kaum'
('Betreiber', opt_str_converter), # 'Max Mustermann'
- ('Öffentliche Anreise', opt_public_transport_german_converter), # 'Mittelmäßig'
- ('Aufstieg möglich', opt_bool_german_converter), # 'Ja'
+ ('Öffentliche Anreise', opt_public_transport_german_converter), # 'Mittelmäßig'
+ ('Aufstieg möglich', opt_bool_german_converter), # 'Ja'
('Aufstieg getrennt', opt_tristate_german_comment_converter), # 'Ja'
('Gehzeit', opt_uint_converter), # 90
('Aufstiegshilfe', lift_german_converter), # 'Gondel (unterer Teil)'
('Beleuchtungsanlage', opt_tristate_german_comment_converter),
('Beleuchtungstage', nightlightdays_converter), # '3 (Montag, Mittwoch, Freitag)'
('Rodelverleih', opt_str_opt_comment_enum_converter), # 'Talstation Serlesbahnan'
- ('Gütesiegel', cachet_german_converter), # 'Tiroler Naturrodelbahn-Gütesiegel 2009 mittel'
- ('Webauskunft', webauskunft_converter), # 'http://www.nösslachhütte.at/page9.php'
+ ('Gütesiegel', cachet_german_converter), # 'Tiroler Naturrodelbahn-Gütesiegel 2009 mittel'
+ ('Webauskunft', webauskunft_converter), # 'http://www.nösslachhütte.at/page9.php'
('Telefonauskunft', opt_phone_comment_enum_converter), # '+43-664-5487520 (Mitterer Alm)'
('Bild', opt_str_converter),
- ('In Übersichtskarte', opt_bool_german_converter),
+ ('In Übersichtskarte', opt_bool_german_converter),
('Forumid', opt_uint_converter)
])
def rodelbahnbox_from_template(template):
- return wikibox_from_template(template, RODELBAHNBOX_TEMPLATE_NAME, RODELBAHNBOX_DICT)
+ """Returns an ordered dict."""
+ return wikibox_from_template(template, RODELBAHNBOX_DICT)
def rodelbahnbox_to_template(value):
def rodelbahnbox_from_str(value):
+ """Returns an ordered dict."""
return wikibox_from_str(value, RODELBAHNBOX_TEMPLATE_NAME, RODELBAHNBOX_DICT)
def rodelbahnbox_to_str(value):
template = rodelbahnbox_to_template(value)
- template_to_table(template, 20)
+ format_template_table(template, 20)
return str(template)
GASTHAUSBOX_DICT = OrderedDict([
('Position', opt_lonlat_converter), # '47.583333 N 15.75 E'
- ('Höhe', opt_uint_converter),
+ ('Höhe', opt_uint_converter),
('Betreiber', opt_str_converter),
- ('Sitzplätze', opt_uint_converter),
- ('Übernachtung', opt_no_or_str_converter),
+ ('Sitzplätze', opt_uint_converter),
+ ('Übernachtung', opt_no_or_str_converter),
('Rauchfrei', opt_tristate_german_converter),
('Rodelverleih', opt_no_or_str_converter),
('Handyempfang', opt_str_opt_comment_enum_converter),
def gasthausbox_from_template(template):
+ """Returns an ordered dict."""
return wikibox_from_template(template, GASTHAUSBOX_TEMPLATE_NAME, GASTHAUSBOX_DICT)
def gasthausbox_from_str(value):
+ """Returns an ordered dict."""
return wikibox_from_str(value, GASTHAUSBOX_TEMPLATE_NAME, GASTHAUSBOX_DICT)
def gasthausbox_to_str(value):
template = gasthausbox_to_template(value)
- template_to_table(template, 17)
+ format_template_table(template, 17)
return str(template)