summaryrefslogtreecommitdiff
path: root/src/hydrilla_dev_helper.py
diff options
context:
space:
mode:
authorWojtek Kosior <koszko@koszko.org>2022-02-12 11:31:36 +0100
committerWojtek Kosior <koszko@koszko.org>2022-02-12 16:10:26 +0100
commit40c24168fcaf9251f56e8570538e9a7dd48795e9 (patch)
tree42e68ea29d5c809c4b5e37e2a7237917433d7303 /src/hydrilla_dev_helper.py
parentded47952fc7f3e4484c6ae4a559e514cb660f2bc (diff)
downloadhaketilo-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.py308
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
- }