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,)
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")