diff options
Diffstat (limited to 'build-concerts.py')
| -rwxr-xr-x | build-concerts.py | 174 |
1 files changed, 16 insertions, 158 deletions
diff --git a/build-concerts.py b/build-concerts.py index 43dce57..6e99673 100755 --- a/build-concerts.py +++ b/build-concerts.py @@ -1,16 +1,17 @@ #!/usr/bin/env python3 -from contextlib import contextmanager -from dataclasses import dataclass from datetime import datetime -import locale -from operator import attrgetter from pathlib import Path -import re from sys import argv -from typing import Iterator, Optional -from helpers import relative_path +from helpers import ( + DATE_FORMATTERS, + guess_language, + read_concerts, + relative_path, + tmplocale, + touchup_plaintext, +) # TODO: change some jargon: @@ -18,115 +19,6 @@ from helpers import relative_path # - canceled => warning -LICENSE_URLS = { - 'CC0': 'https://creativecommons.org/publicdomain/zero', - 'CC BY': 'https://creativecommons.org/licenses/by', - 'CC BY-SA': 'https://creativecommons.org/licenses/by-sa', -} - -LICENSE_RE = re.compile( - '('+'|'.join(LICENSE_URLS.keys())+')' + ' ([0-9.]+)' -) - - -@dataclass -class LicenseInfo: - tag: str - version: str - - @classmethod - def deserialize(cls, info): - if info is None: - return None - return cls(*LICENSE_RE.fullmatch(info).groups()) - - def format(self): - url = f'{LICENSE_URLS[self.tag]}/{self.version}/' - - return f'<a href="{url}" target="_blank">{self.tag}</a>' - - -@dataclass -class Illustration: - file: str - alt_text: str - source_name: str - source_link: Optional[str] - license_info: Optional[LicenseInfo] - - @classmethod - def deserialize(cls, d): - return cls(d['pic_file'], - d['pic_alt'], - d['pic_src'], - d['pic_link'], - LicenseInfo.deserialize(d['pic_license'])) - - -@dataclass -class Concert: - time: datetime - place: str - address: str - pieces: Iterator[str] - instructions: str - illustration: Illustration - warning: Optional[str] - - @classmethod - def deserialize(cls, d): - return cls( - time=datetime.strptime(d['time'], '%d/%m/%Y %Hh%M'), - place=d['place'], - address=d['address'], - pieces=d['pieces'], - instructions=d['instructions'], - illustration=Illustration.deserialize(d), - warning=d['warning'] - ) - - -def optional(line): - return f'(?:{line})?' - - -CONCERT_LINES = ( - r'QUAND : (?P<time>[^\n]+)\n', - r'O[UÙ] : (?P<place>[^\n]+)\n', - 'ADRESSE :\n', - '(?P<address>.+?)\n', - 'PROGRAMME :\n', - '(?P<pieces>.+?)\n', - 'INSTRUCTIONS :\n', - '(?P<instructions>.+?)\n', - 'ILLUSTRATION :\n', - r'fichier : (?P<pic_file>[^\n]+)\n', - r'légende : (?P<pic_alt>[^\n]+)\n', - r'source : (?P<pic_src>[^\n]+)\n', - optional(r'lien : (?P<pic_link>[^\n]+)\n'), - optional(r'licence : (?P<pic_license>[^\n]+)\n'), - optional(r'AVERTISSEMENT : (?P<warning>[^\n]+)\n'), -) - -CONCERT_RE = re.compile(''.join(CONCERT_LINES), flags=re.DOTALL) - - -def guess_language(filename): - parent = str(Path(filename).parent) - if parent == '.': - return 'fr' - return parent - - -def read_concerts(filename): - with open(filename) as f: - concerts = ( - Concert.deserialize(match) - for match in re.finditer(CONCERT_RE, f.read()) - ) - return tuple(sorted(concerts, key=attrgetter('time'))) - - def split_concerts(concerts, threshold): cutoff = len(concerts) @@ -177,28 +69,20 @@ THUMBNAIL_TEMPLATE = '''\ ''' -@contextmanager -def tmplocale(lang): - old_lang, encoding = locale.getlocale() - try: - locale.setlocale(locale.LC_TIME, (lang, encoding)) - yield - finally: - locale.setlocale(locale.LC_TIME, (old_lang, encoding)) - - def format_credits(illustration): - credits = illustration.source_name + attribution = illustration.source_name if illustration.source_link is not None: - credits = (f'<a href="{illustration.source_link}" target="_blank">' - f'{illustration.source_name}' - '</a>') + attribution = ( + f'<a href="{illustration.source_link}" target="_blank">' + f'{illustration.source_name}' + '</a>' + ) if illustration.license_info is not None: - credits += ' / ' + illustration.license_info.format() + attribution += ' / ' + illustration.license_info.format() - return credits + return attribution def format_thumbnail(concert, imgdir, lang): @@ -256,18 +140,6 @@ DETAILS_TEMPLATE = '''\ ''' -DATE_FORMATTERS = { - 'en': { - 'date': lambda d: d.strftime('%A %B %-d, %Y'), - 'time': lambda d: d.strftime('%I:%M %P'), - }, - 'fr': { - 'date': lambda d: d.strftime('%A %-d %B %Y').capitalize(), - 'time': lambda d: d.strftime('%Hh%M'), - }, -} - - def detail_block(tag, classes, content): opener = f'<{tag} class="{" ".join(classes)}">' closer = f'</{tag}>' @@ -286,20 +158,6 @@ def break_lines(lines): return tuple(line+'<br>' for line in lines[:-1]) + (lines[-1],) -TOUCHUPS = ( - (re.compile('([0-9])(st|nd|rd|th|er|ère|nde|ème)'), r'\1<sup>\2</sup>'), - (re.compile('(https://[^ ]+)'), r'<a href="\1" target="_blank">\1</a>'), - (re.compile('([^ ]+@[^ ]+)'), r'<a href="mailto:\1">\1</a>'), -) - - -def touchup_plaintext(plaintext): - text = plaintext - for regexp, repl in TOUCHUPS: - text = regexp.sub(repl, text) - return text - - def print_concert_details(concert, lang): concert_id = f'concert-{concert.time.strftime("%F")}' classes = ('details',) |
