Project

General

Profile

« Previous | Next » 

Revision 9e71d383

Added by koszko over 1 year ago

internationalize using Babel

this commit also makes the sdist tarball generated by setuptools REUSE-compliant

View differences:

.gitignore
10 10
*.pyc
11 11
setuptools
12 12
src/hydrilla/builder/_version.py
13
src/hydrilla/locales/hydrilla_builder.pot
14
hydrilla_builder.mo
.reuse/dep5
3 3
Upstream-Contact: Wojtek Kosior <koszko@koszko.org>
4 4
Source: https://git.koszko.org/hydrilla-builder
5 5

  
6
# Sample paragraph, commented out:
7
#
8
# Files: src/*
9
# Copyright: $YEAR $NAME <$CONTACT>
10
# License: ...
6
Files: PKG-INFO setup.cfg src/hydrilla/builder/_version.py
7
       src/hydrilla.builder.egg-info/*
8
Copyright: 2022 Wojtek Kosior <koszko@koszko.org>
9
License: CC0-1.0
10
Comment: Those are files that setuptools generate in sdist.
11
 `setup.cfg` gets stripped of comments during generation of
12
 sdist, so we include it here as well.
MANIFEST.in
5 5
# Available under the terms of Creative Commons Zero v1.0 Universal.
6 6

  
7 7
include src/hydrilla/schemas/*.schema.json*
8
include src/hydrilla/locales/*/LC_MESSAGES/hydrilla_builder.po
8 9
include src/test/source-package-example/*
9 10
global-exclude .git .gitignore .gitmodules
pyproject.toml
6 6

  
7 7
[build-system]
8 8
build-backend = "setuptools.build_meta"
9
requires = ["setuptools>=45", "wheel", "setuptools_scm>=5.0"]
9
requires = ["setuptools>=45", "wheel", "setuptools_scm>=5.0", "babel"]
10 10

  
11 11
[tool.setuptools_scm]
12 12
write_to = "src/hydrilla/builder/_version.py"
setup.cfg
35 35
install_requires =
36 36
    click
37 37
    jsonschema
38
    importlib; python_version == "2.6"
39 38
 # reuse is optional:
40 39
 #    reuse
41 40

  
41
[options.package_data]
42
* = *.mo
43

  
42 44
[options.extras_require]
43 45
test = pytest
44 46
setup = setuptools_scm
......
50 52

  
51 53
[options.entry_points]
52 54
console_scripts =
53
    hydrilla-builder = hydrilla.builder.__main__:perform_build
55
    hydrilla-builder = hydrilla.builder.build:perform
56

  
57
[extract_messages]
58
keywords = _
59
width = 80
60
input_dirs = src/hydrilla
61
output_file = src/hydrilla/locales/hydrilla_builder.pot
62
msgid_bugs_address = koszko@koszko.org
63
sort_by_file = True
64
copyright_holder = Wojtek Kosior <koszko@koszko.org>
65

  
66
[init_catalog]
67
input_file = src/hydrilla/locales/hydrilla_builder.pot
68
output_dir = src/hydrilla/locales/
69
domain = hydrilla_builder
70

  
71
[update_catalog]
72
input_file = src/hydrilla/locales/hydrilla_builder.pot
73
output_dir = src/hydrilla/locales/
74
domain = hydrilla_builder
75

  
76
[compile_catalog]
77
directory = src/hydrilla/locales
78
use_fuzzy = True
79
domain = hydrilla_builder
setup.py
7 7

  
8 8
import setuptools
9 9

  
10
setuptools.setup()
10
from setuptools.command.build_py import build_py
11

  
12
class CustomBuildCommand(build_py):
13
    '''
14
    The build command but runs babel before build.
15
    '''
16
    def run(self, *args, **kwargs):
17
        self.run_command('compile_catalog')
18
        super().run(*args, **kwargs)
19

  
20
setuptools.setup(cmdclass={'build_py': CustomBuildCommand})
src/hydrilla/builder/__main__.py
1
# SPDX-License-Identifier: AGPL-3.0-or-later
1
# SPDX-License-Identifier: CC0-1.0
2 2

  
3
# Command line interface of Hydrilla package builder.
3
# Copyright (C) 2022 Wojtek Kosior <koszko@koszko.org>
4 4
#
5
# This file is part of Hydrilla
6
#
7
# Copyright (C) 2022 Wojtek Kosior
8
#
9
# This program is free software: you can redistribute it and/or modify
10
# it under the terms of the GNU Affero General Public License as
11
# published by the Free Software Foundation, either version 3 of the
12
# License, or (at your option) any later version.
13
#
14
# This program is distributed in the hope that it will be useful,
15
# but WITHOUT ANY WARRANTY; without even the implied warranty of
16
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
# GNU Affero General Public License for more details.
18
#
19
# You should have received a copy of the GNU Affero General Public License
20
# along with this program.  If not, see <https://www.gnu.org/licenses/>.
21
#
22
#
23
# I, Wojtek Kosior, thereby promise not to sue for violation of this
24
# file's license. Although I request that you do not make use this code
25
# in a proprietary program, I am not going to enforce this in court.
26

  
27
from pathlib import Path
28

  
29
import click
30

  
31
from .build import Build
32

  
33
dir_type = click.Path(exists=True, file_okay=False, resolve_path=True)
5
# Available under the terms of Creative Commons Zero v1.0 Universal.
34 6

  
35
@click.command()
36
@click.option('-s', '--srcdir', default='./', type=dir_type, show_default=True,
37
              help='Source directory to build from.')
38
@click.option('-i', '--index-json', default='index.json', type=click.Path(),
39
              help='Path to file to be processed instead of index.json (if not absolute, resolved relative to srcdir).')
40
@click.option('-d', '--dstdir', type=dir_type, required=True,
41
              help='Destination directory to write built package files to.')
42
def preform_build(srcdir, index_json, dstdir):
43
    """
44
    Build Hydrilla package from scrdir and write the resulting files under
45
    dstdir.
46
    """
47
    build = Build(Path(srcdir), Path(index_json))
48
    build.write_package_files(Path(dstdir))
7
from . import build
49 8

  
50
preform_build()
9
build.perform()
src/hydrilla/builder/build.py
32 32
from sys import stderr
33 33

  
34 34
import jsonschema
35
import click
35 36

  
36 37
from .. import util
37 38

  
39
_ = util.get_gettext('hydrilla_builder')
40

  
38 41
index_validator = util.validator_for('package_source-1.schema.json')
39 42

  
40 43
class FileReferenceError(Exception):
......
99 102
    try:
100 103
        from reuse._main import main as reuse_main
101 104
    except ModuleNotFoundError:
102
        ReuseError("Could not import 'reuse'. Is the tool installed and visible to this Python instance?")
105
        ReuseError(_('couldnt_import_reuse_is_it_installed'))
103 106

  
104 107
    mocked_output = FileBuffer()
105 108
    if reuse_main(args=['--root', str(root), 'lint'], out=mocked_output) != 0:
106 109
        stderr.write(mocked_output.get_bytes().decode())
107
        raise ReuseError('Attempt to generate an SPDX report for a REUSE-incompliant package.')
110
        raise ReuseError(_('spdx_report_from_reuse_incompliant'))
108 111

  
109 112
    mocked_output = FileBuffer()
110 113
    if reuse_main(args=['--root', str(root), 'spdx'], out=mocked_output) != 0:
......
188 191

  
189 192
        path = path.resolve()
190 193
        if not path.is_relative_to(self.srcdir):
191
            raise FileReferenceError(f"Attempt to load '{filename}' which lies outside package source directory.")
194
            raise FileReferenceError(_('loading_{}_outside_package_dir')
195
                                     .format(filename))
192 196

  
193 197
        if str(path.relative_to(self.srcdir)) == 'index.json':
194
            raise FileReferenceError("Attempt to load 'index.json' which is a reserved filename.")
198
            raise FileReferenceError(_('loading_reserved_index_json'))
195 199

  
196 200
        file_ref = self.files_by_path.get(path)
197 201
        if file_ref is None:
......
305 309
            [self._process_file(f['file']) for f in index_obj['copyright']]
306 310

  
307 311
        if generate_spdx and not spdx_ref.include_in_distribution:
308
            raise FileReferenceError("Told to generate 'report.spdx' but 'report.spdx' is not listed among copyright files. Refusing to proceed.")
312
            raise FileReferenceError(_('report_spdx_not_in_copyright_list'))
309 313

  
310 314
        item_refs = [self._process_item(d) for d in index_obj['definitions']]
311 315

  
......
373 377
                version = '.'.join([str(n) for n in item_def['version']])
374 378
                with open(item_dir_path / version, 'wt') as output:
375 379
                    json.dump(item_def, output)
380

  
381
dir_type = click.Path(exists=True, file_okay=False, resolve_path=True)
382

  
383
@click.option('-s', '--srcdir', default='./', type=dir_type, show_default=True,
384
              help=_('source_directory_to_build_from'))
385
@click.option('-i', '--index-json', default='index.json', type=click.Path(),
386
              help=_('path_instead_of_index_json'))
387
@click.option('-d', '--dstdir', type=dir_type, required=True,
388
              help=_('built_package_files_destination'))
389
def perform(srcdir, index_json, dstdir):
390
    """<this will be replaced by a localized docstring for Click to pick up>"""
391
    build = Build(Path(srcdir), Path(index_json))
392
    build.write_package_files(Path(dstdir))
393

  
394
perform.__doc__ = _('build_package_from_srcdir_to_dstdir')
395

  
396
perform = click.command()(perform)
src/hydrilla/locales/en_US/LC_MESSAGES/hydrilla_builder.po
1
# SPDX-License-Identifier: CC0-1.0
2
#
3
# English (United States) translations for hydrilla.builder.
4
# Copyright (C) 2022 Wojtek Kosior <koszko@koszko.org>
5
# Available under the terms of Creative Commons Zero v1.0 Universal.
6
msgid ""
7
msgstr ""
8
"Project-Id-Version: hydrilla.builder 0.1.dev16+g4e46d7f.d20220211\n"
9
"Report-Msgid-Bugs-To: koszko@koszko.org\n"
10
"POT-Creation-Date: 2022-02-12 10:49+0100\n"
11
"PO-Revision-Date: 2022-02-12\n"
12
"Last-Translator: Wojtek Kosior <koszko@koszko.org>\n"
13
"Language: en_US\n"
14
"Language-Team: en_US <koszko@koszko.org>\n"
15
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
16
"MIME-Version: 1.0\n"
17
"Content-Type: text/plain; charset=utf-8\n"
18
"Content-Transfer-Encoding: 8bit\n"
19
"Generated-By: Babel 2.8.0\n"
20

  
21
#: src/hydrilla/builder/build.py:105
22
msgid "couldnt_import_reuse_is_it_installed"
23
msgstr ""
24
"Could not import 'reuse'. Is the tool installed and visible to this "
25
"Python instance?"
26

  
27
#: src/hydrilla/builder/build.py:110
28
msgid "spdx_report_from_reuse_incompliant"
29
msgstr "Attempt to generate an SPDX report for a REUSE-incompliant package."
30

  
31
#: src/hydrilla/builder/build.py:194
32
msgid "loading_{}_outside_package_dir"
33
msgstr "Attempt to load '{}' which lies outside package source directory."
34

  
35
#: src/hydrilla/builder/build.py:198
36
msgid "loading_reserved_index_json"
37
msgstr "Attempt to load 'index.json' which is a reserved filename."
38

  
39
#: src/hydrilla/builder/build.py:312
40
msgid "report_spdx_not_in_copyright_list"
41
msgstr ""
42
"Told to generate 'report.spdx' but 'report.spdx' is not listed among "
43
"copyright files. Refusing to proceed."
44

  
45
#: src/hydrilla/builder/build.py:384
46
msgid "source_directory_to_build_from"
47
msgstr "Source directory to build from."
48

  
49
#: src/hydrilla/builder/build.py:386
50
msgid "path_instead_of_index_json"
51
msgstr ""
52
"Path to file to be processed instead of index.json (if not absolute, "
53
"resolved relative to srcdir)."
54

  
55
#: src/hydrilla/builder/build.py:388
56
msgid "built_package_files_destination"
57
msgstr "Destination directory to write built package files to."
58

  
59
#: src/hydrilla/builder/build.py:394
60
msgid "build_package_from_srcdir_to_dstdir"
61
msgstr ""
62
"Build Hydrilla package from `scrdir` and write the resulting files "
63
"under `dstdir`."
64

  
65
#: src/hydrilla/util/_util.py:76
66
msgid "bad_comment"
67
msgstr "bad comment"
src/hydrilla/util/__init__.py
5 5
# Available under the terms of Creative Commons Zero v1.0 Universal.
6 6

  
7 7
from ._util import strip_json_comments, normalize_version, parse_version, \
8
    version_string, validator_for
8
    version_string, validator_for, get_gettext
src/hydrilla/util/_util.py
26 26

  
27 27
import re
28 28
import json
29
import locale
30
import gettext
29 31

  
30 32
from pathlib import Path
31 33
from typing import Optional
......
71 73
            # ignore this error, let json module report it
72 74
            stripped = line
73 75
        elif len(match[2]) == 1:
74
            raise json.JSONDecodeError('bad comment', text,
76
            raise json.JSONDecodeError(_('bad_comment'), text,
75 77
                                       processed + len(match[1]))
76 78
        else:
77 79
            stripped = match[1]
......
127 129
    """
128 130
    return Draft7Validator(resolver.resolve(schema_filename)[1],
129 131
                           resolver=resolver)
132

  
133
def get_gettext(domain: str, lang: Optional[str]=None):
134
    """
135
    Configure translation and return its gettext() function.
136

  
137
    If `lang` is set, look for translations for `lang`. Otherwise, try to
138
    determine system's default language and use that.
139
    """
140
    # https://stackoverflow.com/questions/3425294/how-to-detect-the-os-default-language-in-python
141
    # But I am not going to surrender to Microbugs' nonfree, crappy OS to test
142
    # it, to the lines inside try: may fail.
143
    try:
144
        from ctypes.windll import kernel32 as windll
145
        lang = locale.windows_locale[windll.GetUserDefaultUILanguage()]
146
    except:
147
        lang = locale.getdefaultlocale()[0] or 'C'
148

  
149
    translation = gettext.translation(
150
        domain,
151
        localedir=(here.parent / 'locales'),
152
        languages=[lang, 'en_US']
153
    )
154

  
155
    return translation.gettext
156

  
157
_ = get_gettext('hydrilla_builder')

Also available in: Unified diff