Skip to content

Commit 63e96ce

Browse files
mudongliangJonathan Corbet
authored andcommitted
scripts: fix all issues reported by pylint
This patch 1) fixes all the issues (not most) reported by pylint, 2) add the functionability to tackle documents that need translation, 3) add logging to adjust the logging level and log file Signed-off-by: Dongliang Mu <dzm91@hust.edu.cn> Reviewed-by: Yanteng Si <siyanteng@loongson.cn> Signed-off-by: Jonathan Corbet <corbet@lwn.net> Link: https://lore.kernel.org/r/20240719041400.3909775-2-dzm91@hust.edu.cn
1 parent 565a304 commit 63e96ce

1 file changed

Lines changed: 141 additions & 73 deletions

File tree

scripts/checktransupdate.py

Lines changed: 141 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -10,31 +10,28 @@
1010
1111
The usage is as follows:
1212
- ./scripts/checktransupdate.py -l zh_CN
13-
This will print all the files that need to be updated in the zh_CN locale.
13+
This will print all the files that need to be updated or translated in the zh_CN locale.
1414
- ./scripts/checktransupdate.py Documentation/translations/zh_CN/dev-tools/testing-overview.rst
1515
This will only print the status of the specified file.
1616
1717
The output is something like:
18-
Documentation/translations/zh_CN/dev-tools/testing-overview.rst (1 commits)
18+
Documentation/dev-tools/kfence.rst
19+
No translation in the locale of zh_CN
20+
21+
Documentation/translations/zh_CN/dev-tools/testing-overview.rst
1922
commit 42fb9cfd5b18 ("Documentation: dev-tools: Add link to RV docs")
23+
1 commits needs resolving in total
2024
"""
2125

2226
import os
23-
from argparse import ArgumentParser, BooleanOptionalAction
27+
import time
28+
import logging
29+
from argparse import ArgumentParser, ArgumentTypeError, BooleanOptionalAction
2430
from datetime import datetime
2531

26-
flag_p_c = False
27-
flag_p_uf = False
28-
flag_debug = False
29-
30-
31-
def dprint(*args, **kwargs):
32-
if flag_debug:
33-
print("[DEBUG] ", end="")
34-
print(*args, **kwargs)
35-
3632

3733
def get_origin_path(file_path):
34+
"""Get the origin path from the translation path"""
3835
paths = file_path.split("/")
3936
tidx = paths.index("translations")
4037
opaths = paths[:tidx]
@@ -43,17 +40,16 @@ def get_origin_path(file_path):
4340

4441

4542
def get_latest_commit_from(file_path, commit):
46-
command = "git log --pretty=format:%H%n%aD%n%cD%n%n%B {} -1 -- {}".format(
47-
commit, file_path
48-
)
49-
dprint(command)
43+
"""Get the latest commit from the specified commit for the specified file"""
44+
command = f"git log --pretty=format:%H%n%aD%n%cD%n%n%B {commit} -1 -- {file_path}"
45+
logging.debug(command)
5046
pipe = os.popen(command)
5147
result = pipe.read()
5248
result = result.split("\n")
5349
if len(result) <= 1:
5450
return None
5551

56-
dprint("Result: {}".format(result[0]))
52+
logging.debug("Result: %s", result[0])
5753

5854
return {
5955
"hash": result[0],
@@ -64,17 +60,19 @@ def get_latest_commit_from(file_path, commit):
6460

6561

6662
def get_origin_from_trans(origin_path, t_from_head):
63+
"""Get the latest origin commit from the translation commit"""
6764
o_from_t = get_latest_commit_from(origin_path, t_from_head["hash"])
6865
while o_from_t is not None and o_from_t["author_date"] > t_from_head["author_date"]:
6966
o_from_t = get_latest_commit_from(origin_path, o_from_t["hash"] + "^")
7067
if o_from_t is not None:
71-
dprint("tracked origin commit id: {}".format(o_from_t["hash"]))
68+
logging.debug("tracked origin commit id: %s", o_from_t["hash"])
7269
return o_from_t
7370

7471

7572
def get_commits_count_between(opath, commit1, commit2):
76-
command = "git log --pretty=format:%H {}...{} -- {}".format(commit1, commit2, opath)
77-
dprint(command)
73+
"""Get the commits count between two commits for the specified file"""
74+
command = f"git log --pretty=format:%H {commit1}...{commit2} -- {opath}"
75+
logging.debug(command)
7876
pipe = os.popen(command)
7977
result = pipe.read().split("\n")
8078
# filter out empty lines
@@ -83,113 +81,183 @@ def get_commits_count_between(opath, commit1, commit2):
8381

8482

8583
def pretty_output(commit):
86-
command = "git log --pretty='format:%h (\"%s\")' -1 {}".format(commit)
87-
dprint(command)
84+
"""Pretty print the commit message"""
85+
command = f"git log --pretty='format:%h (\"%s\")' -1 {commit}"
86+
logging.debug(command)
8887
pipe = os.popen(command)
8988
return pipe.read()
9089

9190

91+
def valid_commit(commit):
92+
"""Check if the commit is valid or not"""
93+
msg = pretty_output(commit)
94+
return "Merge tag" not in msg
95+
9296
def check_per_file(file_path):
97+
"""Check the translation status for the specified file"""
9398
opath = get_origin_path(file_path)
9499

95100
if not os.path.isfile(opath):
96-
dprint("Error: Cannot find the origin path for {}".format(file_path))
101+
logging.error("Cannot find the origin path for {file_path}")
97102
return
98103

99104
o_from_head = get_latest_commit_from(opath, "HEAD")
100105
t_from_head = get_latest_commit_from(file_path, "HEAD")
101106

102107
if o_from_head is None or t_from_head is None:
103-
print("Error: Cannot find the latest commit for {}".format(file_path))
108+
logging.error("Cannot find the latest commit for %s", file_path)
104109
return
105110

106111
o_from_t = get_origin_from_trans(opath, t_from_head)
107112

108113
if o_from_t is None:
109-
print("Error: Cannot find the latest origin commit for {}".format(file_path))
114+
logging.error("Error: Cannot find the latest origin commit for %s", file_path)
110115
return
111116

112117
if o_from_head["hash"] == o_from_t["hash"]:
113-
if flag_p_uf:
114-
print("No update needed for {}".format(file_path))
115-
return
118+
logging.debug("No update needed for %s", file_path)
116119
else:
117-
print("{}".format(file_path), end="\t")
120+
logging.info(file_path)
118121
commits = get_commits_count_between(
119122
opath, o_from_t["hash"], o_from_head["hash"]
120123
)
121-
print("({} commits)".format(len(commits)))
122-
if flag_p_c:
123-
for commit in commits:
124-
msg = pretty_output(commit)
125-
if "Merge tag" not in msg:
126-
print("commit", msg)
124+
count = 0
125+
for commit in commits:
126+
if valid_commit(commit):
127+
logging.info("commit %s", pretty_output(commit))
128+
count += 1
129+
logging.info("%d commits needs resolving in total\n", count)
130+
131+
132+
def valid_locales(locale):
133+
"""Check if the locale is valid or not"""
134+
script_path = os.path.dirname(os.path.abspath(__file__))
135+
linux_path = os.path.join(script_path, "..")
136+
if not os.path.isdir(f"{linux_path}/Documentation/translations/{locale}"):
137+
raise ArgumentTypeError("Invalid locale: {locale}")
138+
return locale
139+
140+
141+
def list_files_with_excluding_folders(folder, exclude_folders, include_suffix):
142+
"""List all files with the specified suffix in the folder and its subfolders"""
143+
files = []
144+
stack = [folder]
145+
146+
while stack:
147+
pwd = stack.pop()
148+
# filter out the exclude folders
149+
if os.path.basename(pwd) in exclude_folders:
150+
continue
151+
# list all files and folders
152+
for item in os.listdir(pwd):
153+
ab_item = os.path.join(pwd, item)
154+
if os.path.isdir(ab_item):
155+
stack.append(ab_item)
156+
else:
157+
if ab_item.endswith(include_suffix):
158+
files.append(ab_item)
159+
160+
return files
161+
162+
163+
class DmesgFormatter(logging.Formatter):
164+
"""Custom dmesg logging formatter"""
165+
def format(self, record):
166+
timestamp = time.time()
167+
formatted_time = f"[{timestamp:>10.6f}]"
168+
log_message = f"{formatted_time} {record.getMessage()}"
169+
return log_message
170+
171+
172+
def config_logging(log_level, log_file="checktransupdate.log"):
173+
"""configure logging based on the log level"""
174+
# set up the root logger
175+
logger = logging.getLogger()
176+
logger.setLevel(log_level)
177+
178+
# Create console handler
179+
console_handler = logging.StreamHandler()
180+
console_handler.setLevel(log_level)
181+
182+
# Create file handler
183+
file_handler = logging.FileHandler(log_file)
184+
file_handler.setLevel(log_level)
185+
186+
# Create formatter and add it to the handlers
187+
formatter = DmesgFormatter()
188+
console_handler.setFormatter(formatter)
189+
file_handler.setFormatter(formatter)
190+
191+
# Add the handler to the logger
192+
logger.addHandler(console_handler)
193+
logger.addHandler(file_handler)
127194

128195

129196
def main():
197+
"""Main function of the script"""
130198
script_path = os.path.dirname(os.path.abspath(__file__))
131199
linux_path = os.path.join(script_path, "..")
132200

133201
parser = ArgumentParser(description="Check the translation update")
134202
parser.add_argument(
135203
"-l",
136204
"--locale",
205+
default="zh_CN",
206+
type=valid_locales,
137207
help="Locale to check when files are not specified",
138208
)
209+
139210
parser.add_argument(
140-
"--print-commits",
211+
"--print-missing-translations",
141212
action=BooleanOptionalAction,
142213
default=True,
143-
help="Print commits between the origin and the translation",
214+
help="Print files that do not have translations",
144215
)
145216

146217
parser.add_argument(
147-
"--print-updated-files",
148-
action=BooleanOptionalAction,
149-
default=False,
150-
help="Print files that do no need to be updated",
151-
)
218+
'--log',
219+
default='INFO',
220+
choices=['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'],
221+
help='Set the logging level')
152222

153223
parser.add_argument(
154-
"--debug",
155-
action=BooleanOptionalAction,
156-
help="Print debug information",
157-
default=False,
158-
)
224+
'--logfile',
225+
default='checktransupdate.log',
226+
help='Set the logging file (default: checktransupdate.log)')
159227

160228
parser.add_argument(
161229
"files", nargs="*", help="Files to check, if not specified, check all files"
162230
)
163231
args = parser.parse_args()
164232

165-
global flag_p_c, flag_p_uf, flag_debug
166-
flag_p_c = args.print_commits
167-
flag_p_uf = args.print_updated_files
168-
flag_debug = args.debug
233+
# Configure logging based on the --log argument
234+
log_level = getattr(logging, args.log.upper(), logging.INFO)
235+
config_logging(log_level)
169236

170-
# get files related to linux path
237+
# Get files related to linux path
171238
files = args.files
172239
if len(files) == 0:
173-
if args.locale is not None:
174-
files = (
175-
os.popen(
176-
"find {}/Documentation/translations/{} -type f".format(
177-
linux_path, args.locale
178-
)
179-
)
180-
.read()
181-
.split("\n")
182-
)
183-
else:
184-
files = (
185-
os.popen(
186-
"find {}/Documentation/translations -type f".format(linux_path)
187-
)
188-
.read()
189-
.split("\n")
190-
)
191-
192-
files = list(filter(lambda x: x != "", files))
240+
offical_files = list_files_with_excluding_folders(
241+
os.path.join(linux_path, "Documentation"), ["translations", "output"], "rst"
242+
)
243+
244+
for file in offical_files:
245+
# split the path into parts
246+
path_parts = file.split(os.sep)
247+
# find the index of the "Documentation" directory
248+
kindex = path_parts.index("Documentation")
249+
# insert the translations and locale after the Documentation directory
250+
new_path_parts = path_parts[:kindex + 1] + ["translations", args.locale] \
251+
+ path_parts[kindex + 1 :]
252+
# join the path parts back together
253+
new_file = os.sep.join(new_path_parts)
254+
if os.path.isfile(new_file):
255+
files.append(new_file)
256+
else:
257+
if args.print_missing_translations:
258+
logging.info(os.path.relpath(os.path.abspath(file), linux_path))
259+
logging.info("No translation in the locale of %s\n", args.locale)
260+
193261
files = list(map(lambda x: os.path.relpath(os.path.abspath(x), linux_path), files))
194262

195263
# cd to linux root directory

0 commit comments

Comments
 (0)