diff options
author | Wojtek Kosior <koszko@koszko.org> | 2022-02-12 11:31:36 +0100 |
---|---|---|
committer | Wojtek Kosior <koszko@koszko.org> | 2022-02-12 16:10:26 +0100 |
commit | 40c24168fcaf9251f56e8570538e9a7dd48795e9 (patch) | |
tree | 42e68ea29d5c809c4b5e37e2a7237917433d7303 /src/hydrilla_dev_helper.py | |
parent | ded47952fc7f3e4484c6ae4a559e514cb660f2bc (diff) | |
download | haketilo-hydrilla-40c24168fcaf9251f56e8570538e9a7dd48795e9.tar.gz haketilo-hydrilla-40c24168fcaf9251f56e8570538e9a7dd48795e9.zip |
remake internationalization, using Babel this time
Diffstat (limited to 'src/hydrilla_dev_helper.py')
-rw-r--r-- | src/hydrilla_dev_helper.py | 308 |
1 files changed, 0 insertions, 308 deletions
diff --git a/src/hydrilla_dev_helper.py b/src/hydrilla_dev_helper.py deleted file mode 100644 index 925f414..0000000 --- a/src/hydrilla_dev_helper.py +++ /dev/null @@ -1,308 +0,0 @@ -# SPDX-License-Identifier: GPL-3.0-or-later - -# Definitions of helper commands to use with setuptools -# -# This file is part of Hydrilla -# -# Copyright (C) 2021 Wojtek Kosior -# -# 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 <https://www.gnu.org/licenses/>. -# -# -# I, Wojtek Kosior, thereby promise not to sue for violation of this file's -# license. Although I request that you do not make use this code in a -# proprietary program, I am not going to enforce this in court. - -from setuptools import Command -from setuptools.command.build_py import build_py -import sys -from pathlib import Path -import subprocess -import re -import os -import json -import importlib - -def mypath(path_or_string): - return Path(path_or_string).resolve() - -class Helper: - def __init__(self, project_root, app_package_name, locales_dir, - locales=['en', 'pl'], default_locale='en', locale_domain=None, - packages_root=None, debian_dir=None, config_path=None): - self.project_root = mypath(project_root) - self.app_package_name = app_package_name - self.locales_dir = mypath(locales_dir) - self.locales = locales - self.default_locale = default_locale - self.locale_domain = locale_domain or app_package_name - self.packages_root = mypath(packages_root or project_root / 'src') - self.app_package_dir = self.packages_root / app_package_name - self.debian_dir = mypath(debian_dir or project_root / 'debian') - self.config_path = config_path and mypath(config_path) - self.locale_files_list = None - - def run_command(self, command, verbose, runner=subprocess.run, **kwargs): - cwd = kwargs.get('cwd') - if cwd: - cwd = mypath(cwd) - where = f'from {cwd} ' - else: - cwd = Path.cwd().resolve() - where = '' - - str_command = [str(command[0])] - - for arg in command[1:]: - if isinstance(arg, Path): - try: - arg = str(arg.relative_to(cwd)) - except ValueError: - arg = str(arg) - - str_command.append(arg) - - if verbose: - print(f'{where}executing {" ".join(str_command)}') - runner(str_command, **kwargs) - - def create_mo_files(self, dry_run=False, verbose=False): - self.locale_files_list = [] - - for locale in self.locales: - messages_dir = self.locales_dir / locale / 'LC_MESSAGES' - - for po_path in messages_dir.glob('*.po'): - mo_path = po_path.with_suffix('.mo') - - if not dry_run: - command = ['msgfmt', po_path, '-o', mo_path] - self.run_command(command, verbose=verbose, check=True) - - self.locale_files_list.extend([po_path, mo_path]) - - def locale_files(self): - if self.locale_files_list is None: - self.create_mo_files(dry_run=True) - - return self.locale_files_list - - def locale_files_relative(self, to=None): - if to is None: - to = self.app_package_dir - - return [file.relative_to(to) for file in self.locale_files()] - - def flask_run(self, locale=None): - for var, val in (('ENV', 'development'), ('DEBUG', 'True')): - os.environ[f'FLASK_{var}'] = os.environ.get(f'FLASK_{var}', val) - - config = {'lang': locale or self.default_locale} - - sys.path.insert(0, str(self.packages_root)) - package = importlib.import_module(self.app_package_name) - - # make relative paths in json config resolve from project's directory - os.chdir(self.project_root) - - kwargs = {'config_path': self.config_path} if self.config_path else {} - package.create_app(flask_config=config, **kwargs).run() - - def update_po_files(self, verbose=False): - pot_path = self.locales_dir / f'{self.locale_domain}.pot' - rglob = self.app_package_dir.rglob - command = ['xgettext', '-d', self.locale_domain, '--language=Python', - '-o', pot_path, *rglob('*.py'), *rglob('*.html')] - - self.run_command(command, verbose=verbose, check=True, - cwd=self.app_package_dir) - - for locale in self.locales: - messages_dir = self.locales_dir / locale / 'LC_MESSAGES' - - for po_path in messages_dir.glob('*.po'): - if po_path.stem != self.app_package_name: - continue; - - if po_path.exists(): - command = ['msgmerge', '--update', po_path, pot_path] - else: - command = ['cp', po_path, pot_path] - - self.run_command(command, verbose=verbose, check=True) - - if (verbose): - print('removing generated .pot file') - pot_path.unlink() - - # we exclude these from the source archive we produce - bad_file_regex = re.compile(r'^\..*|build|debian|dist') - - changelog_line_regex = re.compile(r''' - ^ # match from the beginning of each line - \s* # skip initial whitespace (if any) - (?P<source_name> # capture name - [^\s(]+ - ) - \s* # again skip whitespace (if any) - \( - (?P<version> # capture version which is enclosed in parantheses - [^)]+ - ) - - - (?P<debrel> # capture debrel part of version separately - [0-9]+ - ) - \) - ''', re.VERBOSE) - - def make_tarballs(self, verbose=False): - changelog_path = self.project_root / 'debian' / 'changelog' - with open(changelog_path, 'rt') as file_handle: - for line in file_handle.readlines(): - match = changelog_line_regex.match(line) - if match: - break - - if not match: - raise ValueError("Couldn't extract version from debian/changelog.") - - name, ver, debrel = \ - [match.group(gn) for gn in ('source_name', 'version', 'debrel')] - - source_dirname = f'{name}-{ver}' - source_tarball_name = f'{name}_{ver}.orig.tar.gz' - debian_tarball_name = f'{name}_{ver}-{debrel}.debian.tar.gz' - - source_args = [f'--prefix={source_dirname}/', '-o', - self.project_root.parent / source_tarball_name, 'HEAD'] - - for filepath in self.project_root.iterdir(): - if not self.bad_file_regex.search(filepath.parts[-1]): - source_args.append(filepath) - - debian_args = ['-o', self.project_root.parent / debian_tarball_name, - 'HEAD', self.debian_dir] - - for args in [source_args, debian_args]: - command = ['git', 'archive', '--format=tar.gz', *args] - self.run_command(command, verbose=verbose, check=True) - - def commands(self): - helper = self - - class MsgfmtCommand(Command): - '''A custom command to run msgfmt on all .po files below '{}'.''' - - description = 'use msgfmt to generate .mo files from .po files' - user_options = [] - - def initialize_options(self): - pass - - def finalize_options(self): - pass - - def run(self): - helper.create_mo_files(verbose=self.verbose) - - MsgfmtCommand.__doc__ = MsgfmtCommand.__doc__.format(helper.locales_dir) - - class RunCommand(Command): - ''' - A custom command to run the app using flask. - - This is similar in effect to: - PYTHONPATH='{packages_root}' FLASK_APP={app_package_name} \\ - FLASK_ENV=development flask run - ''' - - description = 'run the Flask app from source directory' - - user_options = [ - ('locale=', 'l', - "app locale (one of: %s; default: '%s')" % - (', '.join([f"'{l}'" for l in helper.locales]), - helper.default_locale)) - ] - - def initialize_options(self): - self.locale = helper.default_locale - - def finalize_options(self): - if self.locale not in helper.locales: - raise ValueError("Locale '%s' not supported" % self.lang) - - def run(self): - helper.flask_run(locale=self.locale) - - RunCommand.__doc__ = RunCommand.__doc__.format( - packages_root=self.packages_root, - app_package_name=self.app_package_name - ) - - class MsgmergeCommand(Command): - ''' - A custom command to run xgettext and msgmerge to update project's - .po files below '{}'. - ''' - - description = 'use xgettext and msgmerge to update (or generate) .po files for this project' - user_options = [] - - def initialize_options(self): - pass - - def finalize_options(self): - pass - - def run(self): - helper.update_po_files(verbose=self.verbose) - - MsgmergeCommand.__doc__ = \ - MsgmergeCommand.__doc__.format(helper.locales_dir) - - class TarballsCommand(Command): - ''' - A custom command to run git archive to create debian tarballs of - this project. - ''' - - description = 'use git archive to create .orig.tar.gz and .debian.tar.gz files for this project' - user_options = [] - - def initialize_options(self): - pass - - def finalize_options(self): - pass - - def run(self): - helper.make_tarballs(verbose=self.verbose) - - class BuildCommand(build_py): - ''' - The build command but runs the custom msgfmt command before build. - ''' - def run(self, *args, **kwargs): - self.run_command('msgfmt') - super().run(*args, **kwargs) - - return { - 'msgfmt': MsgfmtCommand, - 'run': RunCommand, - 'msgmerge': MsgmergeCommand, - 'tarballs': TarballsCommand, - 'build_py': BuildCommand - } |