diff options
Diffstat (limited to 'utils')
-rw-r--r-- | utils/CHANGES_template.rst (renamed from utils/CHANGES_template) | 0 | ||||
-rw-r--r-- | utils/babel_runner.py | 96 | ||||
-rwxr-xr-x[-rw-r--r--] | utils/bump_docker.py | 32 | ||||
-rwxr-xr-x | utils/bump_version.py | 57 | ||||
-rw-r--r-- | utils/release-checklist.rst (renamed from utils/release-checklist) | 0 |
5 files changed, 112 insertions, 73 deletions
diff --git a/utils/CHANGES_template b/utils/CHANGES_template.rst index a655c46..a655c46 100644 --- a/utils/CHANGES_template +++ b/utils/CHANGES_template.rst diff --git a/utils/babel_runner.py b/utils/babel_runner.py index dfb58db..b66425f 100644 --- a/utils/babel_runner.py +++ b/utils/babel_runner.py @@ -31,7 +31,7 @@ from babel.messages.pofile import read_po, write_po from babel.util import pathmatch from jinja2.ext import babel_extract as extract_jinja2 -ROOT = os.path.realpath(os.path.join(os.path.abspath(__file__), "..", "..")) +ROOT = os.path.realpath(os.path.join(os.path.abspath(__file__), '..', '..')) TEX_DELIMITERS = { 'variable_start_string': '<%=', 'variable_end_string': '%>', @@ -70,7 +70,7 @@ OPTIONS_MAP = { KEYWORDS = {**DEFAULT_KEYWORDS, '_': None, '__': None} -def run_extract(): +def run_extract() -> None: """Message extraction function.""" log = _get_logger() @@ -100,12 +100,15 @@ def run_extract(): options = opt_dict with open(os.path.join(root, filename), 'rb') as fileobj: for lineno, message, comments, context in extract( - method, fileobj, KEYWORDS, options=options, + method, fileobj, KEYWORDS, options=options ): filepath = os.path.join(input_path, relative_name) catalogue.add( - message, None, [(filepath, lineno)], - auto_comments=comments, context=context, + message, + None, + [(filepath, lineno)], + auto_comments=comments, + context=context, ) break @@ -115,9 +118,8 @@ def run_extract(): write_po(outfile, catalogue) -def run_update(): +def run_update() -> None: """Catalog merging command.""" - log = _get_logger() domain = 'sphinx' @@ -138,7 +140,8 @@ def run_update(): catalog.update(template) tmp_name = os.path.join( - os.path.dirname(filename), tempfile.gettempprefix() + os.path.basename(filename), + os.path.dirname(filename), + tempfile.gettempprefix() + os.path.basename(filename), ) try: with open(tmp_name, 'wb') as tmpfile: @@ -150,7 +153,7 @@ def run_update(): os.replace(tmp_name, filename) -def run_compile(): +def run_compile() -> None: """ Catalog compilation command. @@ -160,11 +163,10 @@ def run_compile(): Unfortunately, babel's setup command isn't built very extensible, so most of the run() code is duplicated here. """ - log = _get_logger() directory = os.path.join('sphinx', 'locale') - total_errors = 0 + total_errors = {} for locale in os.listdir(directory): po_file = os.path.join(directory, locale, 'LC_MESSAGES', 'sphinx.po') @@ -179,10 +181,17 @@ def run_compile(): continue for message, errors in catalog.check(): + if locale not in total_errors: + total_errors[locale] = 0 for error in errors: - total_errors += 1 - log.error('error: %s:%d: %s\nerror: in message string: %s', - po_file, message.lineno, error, message.string) + total_errors[locale] += 1 + log.error( + 'error: %s:%d: %s\nerror: in message string: %r', + po_file, + message.lineno, + error, + message.string, + ) mo_file = os.path.join(directory, locale, 'LC_MESSAGES', 'sphinx.mo') log.info('compiling catalog %s to %s', po_file, mo_file) @@ -194,26 +203,37 @@ def run_compile(): js_catalogue = {} for message in catalog: if any( - x[0].endswith(('.js', '.js.jinja', '.js_t', '.html')) - for x in message.locations + x[0].endswith(('.js', '.js.jinja', '.js_t', '.html')) + for x in message.locations ): msgid = message.id if isinstance(msgid, (list, tuple)): msgid = msgid[0] js_catalogue[msgid] = message.string - obj = json.dumps({ - 'messages': js_catalogue, - 'plural_expr': catalog.plural_expr, - 'locale': str(catalog.locale), - }, sort_keys=True, indent=4) + obj = json.dumps( + { + 'messages': js_catalogue, + 'plural_expr': catalog.plural_expr, + 'locale': str(catalog.locale), + }, + sort_keys=True, + indent=4, + ) with open(js_file, 'wb') as outfile: # to ensure lines end with ``\n`` rather than ``\r\n``: outfile.write(f'Documentation.addTranslations({obj});'.encode()) - if total_errors > 0: - log.error('%d errors encountered.', total_errors) - print("Compiling failed.", file=sys.stderr) + if 'ta' in total_errors: + # Tamil is a known failure. + err_count = total_errors.pop('ta') + log.error('%d errors encountered in %r locale.', err_count, 'ta') + + if len(total_errors) > 0: + for locale, err_count in total_errors.items(): + log.error('%d errors encountered in %r locale.', err_count, locale) + log.error('%d errors encountered.', sum(total_errors.values())) + print('Compiling failed.', file=sys.stderr) raise SystemExit(2) @@ -234,17 +254,17 @@ if __name__ == '__main__': raise SystemExit(2) from None os.chdir(ROOT) - if action == "extract": - raise SystemExit(run_extract()) - if action == "update": - raise SystemExit(run_update()) - if action == "compile": - raise SystemExit(run_compile()) - if action == "all": - exit_code = run_extract() - if exit_code: - raise SystemExit(exit_code) - exit_code = run_update() - if exit_code: - raise SystemExit(exit_code) - raise SystemExit(run_compile()) + if action == 'extract': + run_extract() + elif action == 'update': + run_update() + elif action == 'compile': + run_compile() + elif action == 'all': + run_extract() + run_update() + run_compile() + else: + msg = f"invalid action: '{action}'" + raise ValueError(msg) + raise SystemExit diff --git a/utils/bump_docker.py b/utils/bump_docker.py index ec4a1c7..8f385ae 100644..100755 --- a/utils/bump_docker.py +++ b/utils/bump_docker.py @@ -25,22 +25,28 @@ SPHINX_VERSION_PREFIX = 'Sphinx==' for file in DOCKERFILE_BASE, DOCKERFILE_LATEXPDF: content = file.read_text(encoding='utf-8') - content = re.sub(rf'{re.escape(OPENCONTAINERS_VERSION_PREFIX)} = "{VERSION_PATTERN}"', - rf'{OPENCONTAINERS_VERSION_PREFIX} = "{VERSION}"', - content) - content = re.sub(rf'{re.escape(SPHINX_VERSION_PREFIX)}{VERSION_PATTERN}', - rf'{SPHINX_VERSION_PREFIX}{VERSION}', - content) + content = re.sub( + rf'{re.escape(OPENCONTAINERS_VERSION_PREFIX)} = "{VERSION_PATTERN}"', + rf'{OPENCONTAINERS_VERSION_PREFIX} = "{VERSION}"', + content, + ) + content = re.sub( + rf'{re.escape(SPHINX_VERSION_PREFIX)}{VERSION_PATTERN}', + rf'{SPHINX_VERSION_PREFIX}{VERSION}', + content, + ) file.write_text(content, encoding='utf-8') -def git(*args): - ret = subprocess.run(('git', *args), - capture_output=True, - cwd=DOCKER_ROOT, - check=True, - text=True, - encoding='utf-8') +def git(*args: str) -> None: + ret = subprocess.run( + ('git', *args), + capture_output=True, + cwd=DOCKER_ROOT, + check=True, + text=True, + encoding='utf-8', + ) print(ret.stdout) print(ret.stderr, file=sys.stderr) diff --git a/utils/bump_version.py b/utils/bump_version.py index 6e50755..7275cca 100755 --- a/utils/bump_version.py +++ b/utils/bump_version.py @@ -1,19 +1,29 @@ #!/usr/bin/env python3 +from __future__ import annotations + import argparse -import os import re import sys import time from contextlib import contextmanager +from pathlib import Path +from typing import TYPE_CHECKING + +from typing_extensions import TypeAlias -script_dir = os.path.dirname(__file__) -package_dir = os.path.abspath(os.path.join(script_dir, '..')) +if TYPE_CHECKING: + from collections.abc import Iterator, Sequence + +script_dir = Path(__file__).parent +package_dir = script_dir.parent RELEASE_TYPE = {'a': 'alpha', 'b': 'beta'} +VersionInfo: TypeAlias = tuple[int, int, int, str, int] + -def stringify_version(version_info, in_develop=True): +def stringify_version(version_info: VersionInfo, in_develop: bool = True) -> str: version = '.'.join(str(v) for v in version_info[:3]) if not in_develop and version_info[3] != 'final': version += version_info[3][0] + str(version_info[4]) @@ -21,7 +31,7 @@ def stringify_version(version_info, in_develop=True): return version -def bump_version(path, version_info, in_develop=True): +def bump_version(path: Path, version_info: VersionInfo, in_develop: bool = True) -> None: version = stringify_version(version_info, in_develop) with open(path, encoding='utf-8') as f: @@ -42,7 +52,7 @@ def bump_version(path, version_info, in_develop=True): f.write('\n'.join(lines) + '\n') -def parse_version(version): +def parse_version(version: str) -> VersionInfo: matched = re.search(r'^(\d+)\.(\d+)$', version) if matched: major, minor = matched.groups() @@ -73,7 +83,7 @@ class Skip(Exception): @contextmanager -def processing(message): +def processing(message: str) -> Iterator[None]: try: print(message + ' ... ', end='') yield @@ -87,11 +97,11 @@ def processing(message): class Changes: - def __init__(self, path): + def __init__(self, path: Path) -> None: self.path = path self.fetch_version() - def fetch_version(self): + def fetch_version(self) -> None: with open(self.path, encoding='utf-8') as f: version = f.readline().strip() matched = re.search(r'^Release (.*) \((.*)\)$', version) @@ -105,7 +115,7 @@ class Changes: else: self.in_development = False - def finalize_release_date(self): + def finalize_release_date(self) -> None: release_date = time.strftime('%b %d, %Y') heading = f'Release {self.version} (released {release_date})' @@ -120,16 +130,18 @@ class Changes: f.write('=' * len(heading) + '\n') f.write(self.filter_empty_sections(body)) - def add_release(self, version_info): + def add_release(self, version_info: VersionInfo) -> None: if version_info[-2:] in (('beta', 0), ('final', 0)): version = stringify_version(version_info) else: reltype = version_info[3] - version = (f'{stringify_version(version_info)} ' - f'{RELEASE_TYPE.get(reltype, reltype)}{version_info[4] or ""}') + version = ( + f'{stringify_version(version_info)} ' + f'{RELEASE_TYPE.get(reltype, reltype)}{version_info[4] or ""}' + ) heading = 'Release %s (in development)' % version - with open(os.path.join(script_dir, 'CHANGES_template'), encoding='utf-8') as f: + with open(script_dir / 'CHANGES_template.rst', encoding='utf-8') as f: f.readline() # skip first two lines f.readline() tmpl = f.read() @@ -145,11 +157,11 @@ class Changes: f.write('\n') f.write(body) - def filter_empty_sections(self, body): - return re.sub('^\n.+\n-{3,}\n+(?=\n.+\n[-=]{3,}\n)', '', body, flags=re.M) + def filter_empty_sections(self, body: str) -> str: + return re.sub('^\n.+\n-{3,}\n+(?=\n.+\n[-=]{3,}\n)', '', body, flags=re.MULTILINE) -def parse_options(argv): +def parse_options(argv: Sequence[str]) -> argparse.Namespace: parser = argparse.ArgumentParser() parser.add_argument('version', help='A version number (cf. 1.6b0)') parser.add_argument('--in-develop', action='store_true') @@ -158,15 +170,16 @@ def parse_options(argv): return options -def main(): +def main() -> None: options = parse_options(sys.argv[1:]) - with processing("Rewriting sphinx/__init__.py"): - bump_version(os.path.join(package_dir, 'sphinx/__init__.py'), - options.version, options.in_develop) + with processing('Rewriting sphinx/__init__.py'): + bump_version( + package_dir / 'sphinx' / '__init__.py', options.version, options.in_develop + ) with processing('Rewriting CHANGES'): - changes = Changes(os.path.join(package_dir, 'CHANGES')) + changes = Changes(package_dir / 'CHANGES.rst') if changes.version_info == options.version: if changes.in_development: changes.finalize_release_date() diff --git a/utils/release-checklist b/utils/release-checklist.rst index 5aabbce..5aabbce 100644 --- a/utils/release-checklist +++ b/utils/release-checklist.rst |