#!/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 # TODO: change some jargon: # - event => concert # - 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'{self.tag}' @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