2 # -*- coding: utf-8 -*-
6 This module contains functions that convert winterrodeln specific strings (like geographic coordinates) from string
7 to appropriate python types and the other way round.
8 Functions that take strings to convert it to python types are called *_from_str(value, [...]) and are supposed to
9 validate the string. In case of errors, a ValueError (or a subclass thereof) is returned.
10 Functions that take python types and convert it to Winterrodeln strings are called *_to_str(value, [...]) and can
11 assume that the value they get is valid. If it is not, the behavior is undefined.
12 The namedtuple FromToConverter groups corresponding *_from_str and *_to_str converters.
14 import email.headerregistry
17 from collections import OrderedDict, namedtuple
19 import mwparserfromhell
21 from wrpylib.mwmarkup import format_template_table
24 # FromToConverter type
25 # --------------------
27 # namedtuple that groups corresponding *_from_str and *_to_str functions.
28 FromToConverter = namedtuple('FromToConverter', ['from_str', 'to_str'])
34 def opt_from_str(value, from_str, empty=None):
35 """Makes the converter `from_str` "optional"
36 by replacing the empty string with a predefined value (default: None)."""
37 return empty if value == '' else from_str(value)
40 def opt_to_str(value, to_str, empty=None):
41 return '' if value == empty else to_str(value)
47 def no_german_from_str(value, from_str, use_tuple=True, no_value=None):
48 """Makes it possible to have "Nein" as special value. If use_tuple is True, a tuple is returned. The first
49 entry of the tuple is False in case the value is "Nein", otherwiese the first value is True. The second value is
50 no_value in case of the value being "Nein", otherwise it is the result of from_str(value).
51 If use_tuple is False, no_value is returned in case the value is "Nein", otherwise the result of from_str(value)."""
53 return (False, no_value) if use_tuple else no_value
54 return (True, from_str(value)) if use_tuple else from_str(value)
57 def no_german_to_str(value, to_str, use_tuple=True, no_value=None):
61 return to_str(value[1])
68 # "optional"/"no" converter
69 # -------------------------
71 def opt_no_german_from_str(value, from_str, use_tuple=True, no_value=None, empty=(None, None)):
72 return opt_from_str(value, lambda v: no_german_from_str(v, from_str, use_tuple, no_value), empty)
75 def opt_no_german_to_str(value, to_str, use_tuple=True, no_value=None, empty=(None, None)):
76 return opt_to_str(value, lambda v: no_german_to_str(v, to_str, use_tuple, no_value), empty)
82 def choice_from_str(value, choices):
83 """Returns the value if it is a member of the choices iterable."""
84 if value not in choices:
85 raise ValueError('{} is an invalid value')
92 def dictkey_from_str(value, key_str_dict):
93 """Returns the key of an entry in the key_str_dict if the value of the entry corresponds to the given value."""
95 return dict(list(zip(key_str_dict.values(), key_str_dict.keys())))[value]
97 raise ValueError("Invalid value '{}'".format(value))
100 def dictkey_to_str(value, key_str_dict):
102 return key_str_dict[value]
104 raise ValueError("Invalid value '{}'".format(value))
107 # enum/"list" converter
108 # ---------------------
110 def enum_from_str(value, from_str, separator=';', min_len=0):
111 """Semicolon separated list of entries with the same "type"."""
112 values = value.split(separator)
113 if len(values) == 1 and values[0] == '':
115 if len(values) < min_len:
116 raise ValueError('at least {} entry/entries have to be in the enumeration'.format(min_len))
117 return list(map(from_str, map(str.strip, values)))
120 def enum_to_str(value, to_str, separator='; '):
121 return separator.join(map(to_str, value))
124 # value/comment converter
125 # -----------------------
127 def value_comment_from_str(value, value_from_str, comment_from_str, comment_optional=False):
128 """Makes it possible to have a mandatory comment in parenthesis at the end of the string."""
130 if value.endswith(')'):
132 for i, char in enumerate(value[::-1]):
137 if open_brackets == 0:
138 comment = value[-i:-1]
140 if len(value) > 1 and value[-1] != ' ':
141 raise ValueError('there has to be a space before the opening bracket of the comment')
145 if open_brackets > 0:
146 raise ValueError('bracket mismatch')
147 if not comment_optional:
148 raise ValueError('mandatory comment not found')
150 if not comment_optional:
151 raise ValueError('mandatory comment not found in "{}"'.format(value))
152 return value_from_str(value), comment_from_str(comment)
155 def value_comment_to_str(value, value_to_str, comment_to_str, comment_optional=False):
156 left = value_to_str(value[0])
157 comment = comment_to_str(value[1])
158 if len(comment) > 0 or not comment_optional:
159 comment = '({})'.format(comment)
162 if len(comment) == 0:
164 return '{} {}'.format(left, comment)
170 def str_from_str(value):
171 """Converter that takes any string and returns it as string without validation.
172 In other words, this function does nothing and just returns its argument."""
176 def str_to_str(value):
180 def req_str_from_str(value):
182 raise ValueError('missing required value')
183 return str_from_str(value)
186 def opt_str_from_str(value):
187 return opt_from_str(value, str_from_str)
190 def opt_str_to_str(value):
191 return opt_to_str(value, str_to_str)
194 opt_str_converter = FromToConverter(opt_str_from_str, opt_str_to_str)
197 # optional no or string converter
198 # -------------------------------
200 def opt_no_or_str_from_str(value):
202 'Nein' => (False, None); 'Nur Wochenende' => (True, 'Nur Wochenende'); 'Ja' => (True, 'Ja'); '' => (None, None)"""
203 return opt_no_german_from_str(value, req_str_from_str)
206 def opt_no_or_str_to_str(value):
207 return opt_no_german_to_str(value, str_to_str)
210 opt_no_or_str_converter = FromToConverter(opt_no_or_str_from_str, opt_no_or_str_to_str)
216 def int_from_str(value, min=None, max=None):
217 """Converter that takes a string representation of an integer and returns the integer.
218 :param value: string representation of an integer
219 :param min: If not None, the integer has to be at least min
220 :param max: If not None, the integer has to be no more than max
223 if min is not None and value < min:
224 raise ValueError('{} must be >= than {}'.format(value, min))
225 if max is not None and value > max:
226 raise ValueError('{} must be <= than {}'.format(value, max))
230 def int_to_str(value):
234 def opt_int_from_str(value, min=None, max=None):
235 return opt_from_str(value, lambda val: int_from_str(val, min, max))
238 def opt_int_to_str(value):
239 return opt_to_str(value, int_to_str)
242 def opt_uint_from_str(value, min=0, max=None):
243 """Optional positive integer."""
244 return opt_int_from_str(value, min, max)
247 def opt_uint_to_str(value):
248 return opt_int_to_str(value)
251 opt_uint_converter = FromToConverter(opt_uint_from_str, opt_uint_to_str)
257 BOOL_GERMAN = OrderedDict([(False, 'Nein'), (True, 'Ja')])
260 def bool_german_from_str(value):
261 return dictkey_from_str(value, BOOL_GERMAN)
264 def bool_german_to_str(value):
265 return dictkey_to_str(value, BOOL_GERMAN)
268 def opt_bool_german_from_str(value):
269 return opt_from_str(value, bool_german_from_str)
272 def opt_bool_german_to_str(value):
273 return opt_to_str(value, bool_german_to_str)
276 opt_bool_german_converter = FromToConverter(opt_bool_german_from_str, opt_bool_german_to_str)
282 TRISTATE_GERMAN = OrderedDict([(0.0, 'Nein'), (0.5, 'Teilweise'), (1.0, 'Ja')])
285 def tristate_german_from_str(value):
286 return dictkey_from_str(value, TRISTATE_GERMAN)
289 def tristate_german_to_str(value):
290 return dictkey_to_str(value, TRISTATE_GERMAN)
293 def opt_tristate_german_from_str(value):
294 return opt_from_str(value, tristate_german_from_str)
297 def opt_tristate_german_to_str(value):
298 return opt_to_str(value, tristate_german_to_str)
301 opt_tristate_german_converter = FromToConverter(opt_tristate_german_from_str, opt_tristate_german_to_str)
304 # tristate with comment converter
305 # -------------------------------
307 def opt_tristate_german_comment_from_str(value):
308 """Ja, Nein or Vielleicht, optionally with comment in parenthesis."""
309 return value_comment_from_str(value, opt_tristate_german_from_str, opt_str_from_str, True)
312 def opt_tristate_german_comment_to_str(value):
313 return value_comment_to_str(value, opt_tristate_german_to_str, opt_str_to_str, True)
316 opt_tristate_german_comment_converter = FromToConverter(opt_tristate_german_comment_from_str, opt_tristate_german_comment_to_str)
322 def url_from_str(value):
323 result = urllib.parse.urlparse(value)
324 if result.scheme not in ['http', 'https']:
325 raise ValueError('scheme has to be http or https')
326 if not result.netloc:
327 raise ValueError('url does not contain netloc')
331 def url_to_str(value):
335 # webauskunft converter
336 # ---------------------
338 def webauskunft_from_str(value):
339 return opt_no_german_from_str(value, url_from_str)
342 def webauskunft_to_str(value):
343 return opt_no_german_to_str(value, url_to_str)
346 webauskunft_converter = FromToConverter(webauskunft_from_str, webauskunft_to_str)
352 def wikipage_from_str(value):
353 """Validates wiki page name like '[[Birgitzer Alm]]'.
354 The page is not checked for existance.
355 An empty string is an error.
356 '[[Birgitzer Alm]]' => '[[Birgitzer Alm]]'
358 if not value.startswith('[[') or not value.endswith(']]'):
359 raise ValueError('No valid wiki page name "{}"'.format(value))
363 def wikipage_to_str(value):
367 def opt_wikipage_enum_from_str(value):
368 """Validates a list of wiki pages like '[[Birgitzer Alm]]; [[Kemater Alm]]'.
369 '[[Birgitzer Alm]]; [[Kemater Alm]]' => ['[[Birgitzer Alm]]', '[[Kemater Alm]]']
370 '[[Birgitzer Alm]]' => ['[[Birgitzer Alm]]']
374 return opt_no_german_from_str(value, lambda val: enum_from_str(val, wikipage_from_str), False, [], None)
377 def opt_wikipage_enum_to_str(value):
378 return opt_no_german_to_str(value, lambda val: enum_to_str(val, wikipage_to_str), False, [], None)
381 opt_wikipage_enum_converter = FromToConverter(opt_wikipage_enum_from_str, opt_wikipage_enum_to_str)
387 def email_from_str(value):
388 """Takes an email address like 'office@example.com', checks it for correctness and returns it again as string."""
390 email.headerregistry.Address(addr_spec=value)
391 except email.errors.HeaderParseError as e:
392 raise ValueError('Invalid email address: {}'.format(value), e)
396 def email_to_str(value):
400 def masked_email_from_str(value, mask='(at)', masked_only=False):
401 """Converts an email address that is possibly masked. Returns a tuple. The first parameter is the un-masked
402 email address as string, the second is a boolean telling whether the address was masked."""
403 unmasked = value.replace(mask, '@')
404 was_masked = unmasked != value
405 if masked_only and not was_masked:
406 raise ValueError('E-Mail address not masked')
407 return email_from_str(unmasked), was_masked
410 def masked_email_to_str(value, mask='(at)'):
411 """Value is a tuple. The first entry is the email address, the second one is a boolean telling whether the
412 email address should be masked."""
413 email, do_masking = value
414 email = email_to_str(email)
416 email = email.replace('@', mask)
420 def emails_from_str(value):
421 return opt_no_german_from_str(value, lambda val: enum_from_str(val, lambda v: value_comment_from_str(v, masked_email_from_str, opt_str_from_str, True)), False, [], None)
424 def emails_to_str(value):
425 return opt_no_german_to_str(value, lambda val: enum_to_str(val, lambda v: value_comment_to_str(v, masked_email_to_str, opt_str_to_str, True)), False, [], None)
428 emails_converter = FromToConverter(emails_from_str, emails_to_str)
434 def phone_number_from_str(value):
435 match = re.match(r'\+\d+(-\d+)*$', value)
437 raise ValueError('invalid format of phone number - use something like +43-699-1234567')
441 def phone_number_to_str(value):
445 def opt_phone_comment_enum_from_str(value, comment_optional=False):
446 return opt_no_german_from_str(value, lambda val: enum_from_str(val, lambda v: value_comment_from_str(v, phone_number_from_str, opt_str_from_str if comment_optional else req_str_from_str, comment_optional)), False, [], None)
449 def opt_phone_comment_enum_to_str(value, comment_optional=False):
450 return opt_no_german_to_str(value, lambda val: enum_to_str(val, lambda v: value_comment_to_str(v, phone_number_to_str, opt_str_to_str if comment_optional else str_to_str, comment_optional)), False, [], None)
453 opt_phone_comment_enum_converter = FromToConverter(opt_phone_comment_enum_from_str, opt_phone_comment_enum_to_str)
456 opt_phone_comment_opt_enum_converter = FromToConverter(lambda value: opt_phone_comment_enum_from_str(value, True), lambda value: opt_phone_comment_enum_to_str(value, True))
459 # longitude/latitude converter
460 # ----------------------------
462 LonLat = namedtuple('LonLat', ['lon', 'lat'])
465 lonlat_none = LonLat(None, None)
468 def lonlat_from_str(value):
469 """Converts a winterrodeln geo string like '47.076207 N 11.453553 E' (being '<latitude> N <longitude> E'
470 to the LonLat(lon, lat) named tupel."""
471 r = re.match('(\d+\.\d+) N (\d+\.\d+) E', value)
472 if r is None: raise ValueError("Coordinates '{}' have not a format like '47.076207 N 11.453553 E'".format(value))
473 return LonLat(float(r.groups()[1]), float(r.groups()[0]))
476 def lonlat_to_str(value):
477 return '{:.6f} N {:.6f} E'.format(value.lat, value.lon)
480 def opt_lonlat_from_str(value):
481 return opt_from_str(value, lonlat_from_str, lonlat_none)
484 def opt_lonlat_to_str(value):
485 return opt_to_str(value, lonlat_to_str, lonlat_none)
488 opt_lonlat_converter = FromToConverter(opt_lonlat_from_str, opt_lonlat_to_str)
491 # difficulty converter
492 # --------------------
494 DIFFICULTY_GERMAN = OrderedDict([(1, 'leicht'), (2, 'mittel'), (3, 'schwer')])
497 def difficulty_german_from_str(value):
498 return dictkey_from_str(value, DIFFICULTY_GERMAN)
501 def difficulty_german_to_str(value):
502 return dictkey_to_str(value, DIFFICULTY_GERMAN)
505 def opt_difficulty_german_from_str(value):
506 return opt_from_str(value, difficulty_german_from_str)
509 def opt_difficulty_german_to_str(value):
510 return opt_to_str(value, difficulty_german_to_str)
513 opt_difficulty_german_converter = FromToConverter(opt_difficulty_german_from_str, opt_difficulty_german_to_str)
516 # avalanches converter
517 # --------------------
519 AVALANCHES_GERMAN = OrderedDict([(1, 'kaum'), (2, 'selten'), (3, 'gelegentlich'), (4, 'häufig')])
522 def avalanches_german_from_str(value):
523 return dictkey_from_str(value, AVALANCHES_GERMAN)
526 def avalanches_german_to_str(value):
527 return dictkey_to_str(value, AVALANCHES_GERMAN)
530 def opt_avalanches_german_from_str(value):
531 return opt_from_str(value, avalanches_german_from_str)
534 def opt_avalanches_german_to_str(value):
535 return opt_to_str(value, avalanches_german_to_str)
538 opt_avalanches_german_converter = FromToConverter(opt_avalanches_german_from_str, opt_avalanches_german_to_str)
544 LIFT_GERMAN = ['Sessellift', 'Gondel', 'Linienbus', 'Taxi', 'Sonstige']
547 def lift_german_from_str(value):
548 """Checks a lift_details property. It is a value comment property with the following
555 Alternatively, the value u'Nein' is allowed.
556 An empty string maps to (None, None).
561 'Sessellift <=> [('Sessellift', None)]
562 'Gondel (nur bis zur Hälfte)' <=> [('Gondel', 'nur bis zur Hälfte')]
563 'Sessellift; Taxi' <=> [('Sessellift', None), ('Taxi', None)]
564 'Sessellift (Wochenende); Taxi (6 Euro)' <=> [('Sessellift', 'Wochenende'), ('Taxi', '6 Euro')]
566 return opt_no_german_from_str(value, lambda value_enum: enum_from_str(value_enum, lambda value_comment: value_comment_from_str(value_comment, lambda v: choice_from_str(v, LIFT_GERMAN), opt_str_from_str, comment_optional=True)), use_tuple=False, no_value=[], empty=None)
569 def lift_german_to_str(value):
570 return opt_no_german_to_str(value, lambda value_enum: enum_to_str(value_enum, lambda value_comment: value_comment_to_str(value_comment, str_to_str, opt_str_to_str, comment_optional=True)), use_tuple=False, no_value=[], empty=None)
573 lift_german_converter = FromToConverter(lift_german_from_str, lift_german_to_str)
576 # public transport converter
577 # --------------------------
579 PUBLIC_TRANSPORT_GERMAN = OrderedDict([(1, 'Sehr gut'), (2, 'Gut'), (3, 'Mittelmäßig'), (4, 'Schlecht'), (5, 'Nein'), (6, 'Ja')])
582 def public_transport_german_from_str(value):
583 return dictkey_from_str(value, PUBLIC_TRANSPORT_GERMAN)
586 def public_transport_german_to_str(value):
587 return dictkey_to_str(value, PUBLIC_TRANSPORT_GERMAN)
590 def opt_public_transport_german_from_str(value):
591 return opt_from_str(value, public_transport_german_from_str)
594 def opt_public_transport_german_to_str(value):
595 return opt_to_str(value, public_transport_german_to_str)
598 opt_public_transport_german_converter = FromToConverter(opt_public_transport_german_from_str, opt_public_transport_german_to_str)
604 CACHET_REGEXP = [r'(Tiroler Naturrodelbahn-Gütesiegel) ([12]\d{3}) (leicht|mittel|schwer)$']
607 def single_cachet_german_from_str(value):
608 for pattern in CACHET_REGEXP:
609 match = re.match(pattern, value)
611 return match.groups()
612 raise ValueError("'{}' is no valid cachet".format(value))
615 def single_cachet_german_to_str(value):
616 return ' '.join(value)
619 def cachet_german_from_str(value):
620 """Converts a "Gütesiegel":
623 'Tiroler Naturrodelbahn-Gütesiegel 2009 mittel' => [('Tiroler Naturrodelbahn-Gütesiegel', '2009', 'mittel')]"""
624 return opt_no_german_from_str(value, lambda val: enum_from_str(val, single_cachet_german_from_str), False, [], None)
627 def cachet_german_to_str(value):
628 return opt_no_german_to_str(value, lambda val: enum_to_str(val, single_cachet_german_to_str), False, [], None)
631 cachet_german_converter = FromToConverter(cachet_german_from_str, cachet_german_to_str)
634 # night light days converter
635 # --------------------------
637 def nightlightdays_from_str(value):
638 return value_comment_from_str(value, lambda val: opt_from_str(val, lambda v: int_from_str(v, min=0, max=7)), opt_str_from_str, comment_optional=True)
641 def nightlightdays_to_str(value):
642 return value_comment_to_str(value, lambda val: opt_to_str(val, int_to_str), opt_str_to_str, comment_optional=True)
645 nightlightdays_converter = FromToConverter(nightlightdays_from_str, nightlightdays_to_str)
648 # string with optional comment enum/list converter
649 # ------------------------------------------------
651 def opt_str_opt_comment_enum_from_str(value):
652 """The value can be an empty string, 'Nein' or a semicolon-separated list of strings with optional comments.
655 'Talstation (nur mit Ticket); Schneealm' => [('Talstation', 'nur mit Ticket'), ('Schneealm', None)]"""
656 return opt_no_german_from_str(value, lambda val: enum_from_str(val, lambda v: value_comment_from_str(v, req_str_from_str, opt_str_from_str, True)), False, [], None)
659 def opt_str_opt_comment_enum_to_str(value):
660 return opt_no_german_to_str(value, lambda val: enum_to_str(val, lambda v: value_comment_to_str(v, str_to_str, opt_str_to_str, True)), False, [], None)
663 opt_str_opt_comment_enum_converter = FromToConverter(opt_str_opt_comment_enum_from_str, opt_str_opt_comment_enum_to_str)
669 class ValueErrorList(ValueError):
673 def wikibox_from_template(template, name, converter_dict):
674 if template.name.strip() != name:
675 raise ValueError('Box name has to be "{}"'.format(name))
676 result = OrderedDict()
677 exceptions_dict = OrderedDict()
679 for key, converter in converter_dict.items():
681 if not template.has(key):
682 raise ValueError('Missing parameter "{}"'.format(key))
683 result[key] = converter.from_str(str(template.get(key).value.strip()))
684 except ValueError as e:
685 exceptions_dict[key] = e
686 # check if keys are superfluous
687 superfluous_keys = {str(p.name.strip()) for p in template.params} - set(converter_dict.keys())
688 for key in superfluous_keys:
689 exceptions_dict[key] = ValueError('Superfluous parameter: "{}"'.format(key))
690 if len(exceptions_dict) > 0:
691 raise ValueErrorList('{} error(s) occurred when parsing template parameters.'.format(len(exceptions_dict)), exceptions_dict)
695 def wikibox_to_template(value, name, converter_dict):
696 template = mwparserfromhell.nodes.template.Template(name)
697 for key, converter in converter_dict.items():
698 template.add(key, converter.to_str(value[key]))
702 def template_from_str(value, name):
703 wikicode = mwparserfromhell.parse(value)
704 template_list = wikicode.filter_templates(name)
706 raise ValueError('No "{}" template was found'.format(name))
707 if len(template_list) > 1:
708 raise ValueError('{} "{}" templates were found'.format(len(template_list), name))
709 return template_list[0]
712 def wikibox_from_str(value, name, converter_dict):
713 template = template_from_str(value, name)
714 return wikibox_from_template(template, name, converter_dict)
717 def wikibox_to_str(value, name, converter_dict):
718 return str(wikibox_to_template(value, name, converter_dict))
721 # Rodelbahnbox converter
722 # ----------------------
724 RODELBAHNBOX_TEMPLATE_NAME = 'Rodelbahnbox'
727 RODELBAHNBOX_DICT = OrderedDict([
728 ('Position', opt_lonlat_converter), # '47.583333 N 15.75 E'
729 ('Position oben', opt_lonlat_converter), # '47.583333 N 15.75 E'
730 ('Höhe oben', opt_uint_converter), # '2000'
731 ('Position unten', opt_lonlat_converter), # '47.583333 N 15.75 E'
732 ('Höhe unten', opt_uint_converter), # '1200'
733 ('Länge', opt_uint_converter), # 3500
734 ('Schwierigkeit', opt_difficulty_german_converter), # 'mittel'
735 ('Lawinen', opt_avalanches_german_converter), # 'kaum'
736 ('Betreiber', opt_str_converter), # 'Max Mustermann'
737 ('Öffentliche Anreise', opt_public_transport_german_converter), # 'Mittelmäßig'
738 ('Aufstieg möglich', opt_bool_german_converter), # 'Ja'
739 ('Aufstieg getrennt', opt_tristate_german_comment_converter), # 'Ja'
740 ('Gehzeit', opt_uint_converter), # 90
741 ('Aufstiegshilfe', lift_german_converter), # 'Gondel (unterer Teil)'
742 ('Beleuchtungsanlage', opt_tristate_german_comment_converter),
743 ('Beleuchtungstage', nightlightdays_converter), # '3 (Montag, Mittwoch, Freitag)'
744 ('Rodelverleih', opt_str_opt_comment_enum_converter), # 'Talstation Serlesbahnan'
745 ('Gütesiegel', cachet_german_converter), # 'Tiroler Naturrodelbahn-Gütesiegel 2009 mittel'
746 ('Webauskunft', webauskunft_converter), # 'http://www.nösslachhütte.at/page9.php'
747 ('Telefonauskunft', opt_phone_comment_enum_converter), # '+43-664-5487520 (Mitterer Alm)'
748 ('Bild', opt_str_converter),
749 ('In Übersichtskarte', opt_bool_german_converter),
750 ('Forumid', opt_uint_converter)
754 def rodelbahnbox_from_template(template):
755 return wikibox_from_template(template, RODELBAHNBOX_TEMPLATE_NAME, RODELBAHNBOX_DICT)
758 def rodelbahnbox_to_template(value):
759 return wikibox_to_template(value, RODELBAHNBOX_TEMPLATE_NAME, RODELBAHNBOX_DICT)
762 def rodelbahnbox_from_str(value):
763 return wikibox_from_str(value, RODELBAHNBOX_TEMPLATE_NAME, RODELBAHNBOX_DICT)
766 def rodelbahnbox_to_str(value):
767 template = rodelbahnbox_to_template(value)
768 format_template_table(template, 20)
772 # Gasthausbox converter
773 # ---------------------
775 GASTHAUSBOX_TEMPLATE_NAME = 'Gasthausbox'
778 GASTHAUSBOX_DICT = OrderedDict([
779 ('Position', opt_lonlat_converter), # '47.583333 N 15.75 E'
780 ('Höhe', opt_uint_converter),
781 ('Betreiber', opt_str_converter),
782 ('Sitzplätze', opt_uint_converter),
783 ('Übernachtung', opt_no_or_str_converter),
784 ('Rauchfrei', opt_tristate_german_converter),
785 ('Rodelverleih', opt_no_or_str_converter),
786 ('Handyempfang', opt_str_opt_comment_enum_converter),
787 ('Homepage', webauskunft_converter),
788 ('E-Mail', emails_converter),
789 ('Telefon', opt_phone_comment_opt_enum_converter),
790 ('Bild', opt_str_converter),
791 ('Rodelbahnen', opt_wikipage_enum_converter)])
794 def gasthausbox_from_template(template):
795 return wikibox_from_template(template, GASTHAUSBOX_TEMPLATE_NAME, GASTHAUSBOX_DICT)
798 def gasthausbox_to_template(value):
799 return wikibox_to_template(value, GASTHAUSBOX_TEMPLATE_NAME, GASTHAUSBOX_DICT)
802 def gasthausbox_from_str(value):
803 return wikibox_from_str(value, GASTHAUSBOX_TEMPLATE_NAME, GASTHAUSBOX_DICT)
806 def gasthausbox_to_str(value):
807 template = gasthausbox_to_template(value)
808 format_template_table(template, 17)
812 # Helper function to make page title pretty
813 # -----------------------------------------
815 def sledrun_page_title_to_pretty_url(page_title):
816 """Converts a page_title from the page_title column of wrsledruncache to name_url.
817 name_url is not used by MediaWiki but by new applications like wrweb."""
818 return page_title.lower().replace(' ', '-').replace('_', '-').replace('(', '').replace(')', '')