-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathupdate_translations.py
More file actions
153 lines (132 loc) · 4.7 KB
/
Copy pathupdate_translations.py
File metadata and controls
153 lines (132 loc) · 4.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
from dataclasses import dataclass
from pathlib import Path
from subprocess import DEVNULL, PIPE, CalledProcessError
from subprocess import run as run_subprocess
from typing import assert_never
from git import Repo
from .config import PoFilePair, RepositoryConfig, UpdateTranslationsConfig
from .git import commit_and_push_files, repository_in_clean_state
from .html_tags import forbidden_tags
from .logger import LOGGER
from .portable_object import (
format_forbidden_tags_error,
remove_header,
remove_last_translator,
remove_source_string_locations,
)
@dataclass(frozen=True)
class _Success:
path: Path
@dataclass(frozen=True)
class _Failure:
error_message: str
path: Path
def run(config: UpdateTranslationsConfig) -> int:
checkmk_repo = repository_in_clean_state(config.checkmk_repository)
repository_in_clean_state(config.locale_repository)
failures: list[_Failure] = []
successes: list[_Success] = []
for file_pair in config.po_file_pairs:
LOGGER.info("Processing %s, %s", file_pair.locale, file_pair.checkmk)
match result := _process_po_file_pair(
file_pair=file_pair,
checkmk_repo=config.checkmk_repository,
locale_repo=config.locale_repository,
):
case _Success():
successes.append(result)
case _Failure():
LOGGER.error(
"Encountered an error while processing the .po file pair. "
"See the logging output at the end for more information.",
)
failures.append(result)
case _:
assert_never(result)
LOGGER.info("Checking if any .po files changed in the checkmk repository")
if _is_repo_dirty(checkmk_repo):
LOGGER.info("Committing and pushing .po files to checkmk repository")
commit_and_push_files(
repo=checkmk_repo,
files=[success.path for success in successes],
commit_message=config.commit_message,
)
else:
LOGGER.info("No changes in checkmk repository.")
if not failures:
return 0
for failure in failures:
LOGGER.error(
"Encountered the following error while processing %s:\n%s",
failure.path,
failure.error_message,
)
return 1
def _process_po_file_pair(
file_pair: PoFilePair,
checkmk_repo: RepositoryConfig,
locale_repo: RepositoryConfig,
) -> _Success | _Failure:
checkmk_po_file = checkmk_repo.path / file_pair.checkmk
locale_po_file = locale_repo.path / file_pair.locale
LOGGER.info("Checking for formatting errors in %s", locale_po_file)
try:
run_subprocess( # noqa: S603
[
"/usr/bin/msgfmt",
"--check-format",
"-o",
"-",
locale_po_file,
],
check=True,
stdout=DEVNULL,
stderr=PIPE,
encoding="UTF-8",
)
except CalledProcessError as e:
return _Failure(
error_message=f"Found formatting errors: {e.stderr}",
path=locale_po_file,
)
except OSError as e:
return _Failure(error_message=str(e), path=locale_po_file)
LOGGER.info("Reading %s", locale_po_file)
try:
po_file_content = locale_po_file.read_text()
except OSError as e:
return _Failure(
error_message=f"Encountered error while reading file: {e}",
path=locale_po_file,
)
LOGGER.info("Checking HTML tags")
body, header_line_count = remove_header(po_file_content)
if forbidden_html_tags := forbidden_tags(body):
return _Failure(
error_message=format_forbidden_tags_error(
po_file_content,
header_line_count,
forbidden_html_tags,
),
path=locale_po_file,
)
LOGGER.info("Stripping source string locations and Last-Translator")
po_file_content = remove_source_string_locations(po_file_content)
po_file_content = remove_last_translator(po_file_content)
LOGGER.info("Writing stripped .po file to checkmk repository: %s", checkmk_po_file)
try:
checkmk_po_file.write_text(po_file_content)
except OSError as e:
return _Failure(
error_message=f"Encountered error while writing po file to checkmk repository: {e}",
path=checkmk_po_file,
)
return _Success(checkmk_po_file)
def _is_repo_dirty(repo: Repo) -> bool:
try:
return repo.is_dirty(untracked_files=True)
except Exception:
LOGGER.error(
"Checking if any .po files changed in the checkmk repository failed",
)
raise