Source code for livemaker.lsb.translate

# -*- coding: utf-8 -*-
#
# Copyright (C) 2020 Peter Rowlands <peter@pmrowla.com>
# Copyright (C) 2014 tinfoil <https://bitbucket.org/tinfoil/>
#
# This file is a part of pylivemaker.
#
# This program is free software: you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation, either version 3 of the License, or (at your option) any later
# version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along with
# this program. If not, see <http://www.gnu.org/licenses/>.
"""pylivemaker translatable text module."""

from abc import ABC
from hashlib import blake2b

from funcy import cached_property

from ..exceptions import BadTextIdentifierError, InvalidCharError


[docs]class BaseTranslatable(ABC): """Base class for translatable text objects.""" def __init__(self, text): self._orig_text = "\n".join(text.splitlines()) self.text = self._orig_text @property def orig_text(self): return self._orig_text @property def text(self): return "\n".join(self._text) @text.setter def text(self, text): for ch in text: try: ch.encode("cp932") except UnicodeEncodeError: raise InvalidCharError(ch) self._text = text.splitlines() @cached_property def digest(self): return self.text_digest(self.orig_text) def __str__(self): return str(self.text) def __hash__(self): return hash(self.digest) def __eq__(self, other): return hash(self) == hash(other)
[docs] @staticmethod def text_digest(text): hash_ = blake2b(digest_size=8) hash_.update(text.encode("utf-8")) return hash_.hexdigest()
[docs]class BaseTextIdentifier: """Base identifier for translatable text inside an LSB.""" type = "base" def __init__(self, filename, line_no, name=""): self.filename = filename self.line_no = int(line_no) self.name = name def __hash__(self): return hash(self.parts) def __eq__(self, other): return hash(self) == hash(other) def __str__(self): return ":".join([str(x) for x in self.parts]) @property def _parts(self): return [] @property def parts(self): return ("pylm", self.type, self.filename, self.line_no, *self._parts)
[docs] @classmethod def from_string(cls, string, **kwargs): parts = string.split(":") if len(parts) < 2 or parts[0] != "pylm": raise BadTextIdentifierError(f"{string} is not a valid pylm identifier") if parts[1] != cls.type: raise BadTextIdentifierError(f"{string} is not a valid pylm:{cls.type} identifier") try: return cls(*parts[2:], **kwargs) except ValueError as e: raise BadTextIdentifierError(f"{string} is not a valid pylm:{cls.type} identifier: {e}")
[docs]class TextBlockIdentifier(BaseTextIdentifier): """Identifier for scenario text block.""" type = "text" def __init__(self, filename, line_no, block_index, **kwargs): super().__init__(filename, line_no, **kwargs) self.block_index = int(block_index) @property def _parts(self): return (self.block_index,)
[docs]class BaseMenuIdentifier(BaseTextIdentifier): """Base identifier for selection menus.""" type = "menu" def __init__(self, filename, line_no, choice_index, **kwargs): super().__init__(filename, line_no, **kwargs) self.choice_index = int(choice_index) @property def _parts(self): return (self.choice_index,)
[docs]class TextMenuIdentifier(BaseMenuIdentifier): """Identifier for text selection menu.""" type = "menu-text"
[docs]class LPMMenuIdentifier(BaseMenuIdentifier): """Identifier for text selection menu.""" type = "menu-lpm"
supported_identifiers = [ TextBlockIdentifier, TextMenuIdentifier, LPMMenuIdentifier, ]
[docs]def make_identifier(string): for cls in supported_identifiers: try: return cls.from_string(string) except BadTextIdentifierError: pass raise BadTextIdentifierError(f"{string} is not a valid pylm identifier")