Select Git revision
test-browser
-
Martin Mareš authoredMartin Mareš authored
arg_attrs.py 5.10 KiB
# Automatický generátor command-line argumentů pro atributy databázových objektů
import argparse
from dataclasses import dataclass
from datetime import datetime
from typing import Callable, Any, Optional, Type, List
import mo.db as db
class HelpFormatter(argparse.HelpFormatter):
def __init__(self, *args, **kwargs):
super().__init__(*args, max_help_position=50, **kwargs)
@dataclass
class Attr:
name: str
parser: Callable[[str], Any]
help: str
long: Optional[str] = None
short: Optional[str] = None
nullable: bool = False
def add_to_arg_parser(self, parser: argparse.ArgumentParser) -> None:
arg_names = []
if self.short is not None:
arg_names.append('-' + self.short)
if self.long is not None:
arg_names.append('--' + self.long)
else:
arg_names.append('--' + self.name.replace('_', '-'))
other = {
'metavar': 'X',
}
typ = self.parser
if typ is parse_bool:
other['nargs'] = '?'
other['const'] = 'true'
other['metavar'] = 'BOOL'
if self.nullable:
typ = make_nullable_parser(typ)
parser.add_argument(*arg_names, type=typ, default=Ellipsis, help=self.help, **other)
def args_to_obj(self, args: argparse.Namespace, obj: Any) -> None:
key = self.long.replace('-', '_') if self.long else self.name
val = getattr(args, key)
assert hasattr(obj, self.name)
if val is not Ellipsis:
setattr(obj, self.name, val)
@dataclass
class AttrList:
attrs: List[Attr]
def add_to_arg_parser(self, parser: argparse.ArgumentParser) -> None:
for a in self.attrs:
a.add_to_arg_parser(parser)
def args_to_obj(self, args: argparse.Namespace, obj: Any) -> None:
for a in self.attrs:
a.args_to_obj(args, obj)
def parse_enum(e: Type[db.MOEnum], s: str) -> Any:
try:
return e.coerce(s)
except ValueError:
choices = ", ".join([x.name for x in e])
raise argparse.ArgumentTypeError(f'Invalid value {s} (must be one of {choices})')
def parse_type(s: str) -> db.RoundType:
return parse_enum(db.RoundType, s)
def parse_time(s: str) -> Optional[datetime]:
return datetime.fromisoformat(s).astimezone()
def parse_bool(s: str) -> bool:
if s in ('true', '1', 'yes', 't', 'y'):
return True
if s in ('false', '0', 'no', 'f', 'n'):
return False
raise ValueError(f'Cannot parse {s} as Boolean value')
def parse_score_mode(s: str) -> db.RoundScoreMode:
return parse_enum(db.RoundScoreMode, s)
def parse_enroll_mode(s: str) -> db.RoundEnrollMode:
return parse_enum(db.RoundEnrollMode, s)
def make_nullable_parser(typ: Callable[[str], Any]) -> Any:
def parse(s: str) -> Any:
if s == '-' or s == "":
return None
else:
return typ(s)
return parse
ROUND_ATTRS = AttrList([
Attr('level', int, 'úroveň v hierarchii oblastí', short='l'),
Attr('name', str, 'název kola', short='n'),
Attr('round_type', parse_type, 'typ kola', long='type', short='t'),
# FIXME: state, last_state
# tasks_file nenastavujeme
Attr('ct_tasks_start', parse_time, 'začátek pro účastníky', nullable=True),
Attr('ct_submit_end', parse_time, 'konec odevzdávání pro účastníky'),
Attr('pr_tasks_start', parse_time, 'začátek pro dozor'),
Attr('pr_submit_end', parse_time, 'konec odevzdávání pro dozor'),
Attr('online_submit', parse_bool, 'povoleno elektronické odevzdávání'),
Attr('score_mode', parse_score_mode, 'režim výsledkové listiny'),
Attr('score_winner_limit', float, 'hranice bodů pro vítěze', nullable=True),
Attr('score_successful_limit', float, 'hranice bodů pro úspěšného řešitele', nullable=True),
Attr('score_advance_limit', float, 'hranice bodů pro postup', nullable=True),
Attr('points_step', float, 'bodovací krok', short='S'),
Attr('has_messages', parse_bool, 'povoleny zprávičky'),
Attr('enroll_mode', parse_enroll_mode, 'režim registrace'),
Attr('enroll_advert', str, 'popis v přihlášce'),
Attr('enroll_deadline', parse_time, 'deadline přihlašování', nullable=True),
Attr('min_rec_grade', int, 'minimální doporučený ročník (1-12)', nullable=True),
Attr('max_rec_grade', int, 'maximální doporučený ročník (1-12)', nullable=True),
Attr('export_score_to_mo_web', parse_bool, 'exportovat výsledkovky na web', long='publish-score'),
])
CONTEST_ATTRS = AttrList([
Attr('online_submit', parse_bool, 'povoleno elektronické odevzdávání'),
Attr('tex_hacks', str, 'hacky pro sazbu výsledkových listin'),
])