summaryrefslogtreecommitdiffstats
path: root/utils
diff options
context:
space:
mode:
Diffstat (limited to 'utils')
-rw-r--r--utils/CHANGES_template.rst (renamed from utils/CHANGES_template)0
-rw-r--r--utils/babel_runner.py96
-rwxr-xr-x[-rw-r--r--]utils/bump_docker.py32
-rwxr-xr-xutils/bump_version.py57
-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