Source code for rics.translation.offline._format_applier

from abc import ABC, abstractmethod
from typing import Any, Dict, Generic, List

from rics.translation.offline._format import Format
from rics.translation.offline._magic_dict import MagicDict
from rics.translation.offline.types import PlaceholdersTuple, PlaceholderTranslations, TranslatedIds
from rics.translation.types import ID, IdType, NameType, SourceType
from rics.utility.misc import tname


[docs]class FormatApplier(ABC, Generic[IdType, NameType, SourceType]): """Base class for application of ``Format`` specifications. Args: translations: Matrix of ID translation components returned by fetchers. Raises: ValueError: If `default` is given and any placeholder names are missing. """ def __init__(self, translations: PlaceholderTranslations) -> None: self._source = translations.source self._placeholder_names = translations.placeholders self._n_ids = len(translations.records) def __call__( self, fmt: Format, placeholders: PlaceholdersTuple = None, default_fmt: Format = None, default_fmt_placeholders: Dict[str, Any] = None, ) -> MagicDict: """Translate IDs. Args: fmt: Translation format to use. placeholders: Placeholders to include in the formatted output. Use as many as possible if ``None``. default_fmt: Alternative format for default translation. default_fmt_placeholders: Default placeholders Returns: A dict ``{idx: translated_id}``. """ if placeholders is None: # Use as many placeholders as possible. placeholders = tuple(filter(self._placeholder_names.__contains__, fmt.placeholders)) fstring = fmt.fstring(placeholders, self.positional) real_translations = self._apply(fstring, placeholders) if default_fmt or default_fmt_placeholders: fmap = {ID: "{}", **(default_fmt_placeholders or {})} default_fstring = (default_fmt or fmt).fstring(fmap, positional=False).format(**fmap) else: default_fstring = None return MagicDict( real_translations, default_fstring, ) @abstractmethod def _apply(self, fstring: str, placeholders: PlaceholdersTuple) -> TranslatedIds: """Apply fstring to all IDs. The abstract class delegates ``__apply__``-invocations to this method after some input validation. Args: fstring: A format string. placeholders: Keys needed for the fstring, in the order in which they appear. Returns: A dict ``{idx: translated_id}``. """ @property def positional(self) -> bool: """If ``True``, names are stripped from fstring placeholders.""" return True @property def source(self) -> SourceType: """Return translation source.""" return self._source # pragma: no cover @property def placeholders(self) -> List[str]: """Return placeholder names in sorted order.""" return list(self._placeholder_names) # pragma: no cover def __len__(self) -> int: return self._n_ids # pragma: no cover def __repr__(self) -> str: placeholders = tuple(self._placeholder_names) source = self._source return f"{tname(self)}({len(self)} IDs, {placeholders=}, {source=})"
[docs]class DefaultFormatApplier(FormatApplier): """Default format applier implementation.""" def __init__( self, translations: PlaceholderTranslations, ) -> None: super().__init__(translations) self._pht = translations def _apply(self, fstring: str, placeholders: PlaceholdersTuple) -> TranslatedIds: if self._placeholder_names == placeholders: return {record[self._pht.id_pos]: fstring.format(*record) for record in self._pht.records} else: pos = tuple(map(self._placeholder_names.index, placeholders)) return {record[self._pht.id_pos]: fstring.format(*(record[i] for i in pos)) for record in self._pht.records}