from dataclasses import dataclass
from datetime import datetime
from operator import attrgetter
from os import path
from pathlib import Path
import re
from typing import Iterator, Optional
def guess_language(filename):
parent = str(Path(filename).parent)
if parent == '.':
return 'fr'
return parent
def relative_path(*, to, ref):
# pathlib.Path(x).relative_to(y) cannot handle y not being under x,
# os.path.dirname('x') yields '' rather than '.'.
# 😮💨
return path.relpath(to, Path(ref).parent)
_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