Skip to content

Commit 941e891

Browse files
authored
Merge branch 'python:3.12' into io
2 parents 6acde35 + c30bc8d commit 941e891

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

90 files changed

+8573
-7587
lines changed

.github/workflows/ci.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,4 @@ jobs:
1313
run: sudo apt-get install gettext
1414

1515
- name: Validate
16-
run: VERSION=${{ github.event.pull_request.base.ref }} MODE=dummy make all
16+
run: VERSION=${{ github.event.repository.default_branch }} MODE=dummy make all
+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
name: summarize_progress
2+
3+
on:
4+
schedule:
5+
- cron: '30 23 * * 5'
6+
7+
jobs:
8+
ci:
9+
runs-on: ubuntu-latest
10+
permissions:
11+
# Give the default GITHUB_TOKEN write permission to commit and push the
12+
# added or changed files to the repository.
13+
contents: write
14+
steps:
15+
- uses: actions/checkout@v2
16+
17+
- name: Install poetry
18+
uses: abatilo/actions-poetry@v2
19+
20+
- name: Execute Check Process
21+
run: |
22+
chmod +x .scripts/summarize_progress.sh
23+
.scripts/summarize_progress.sh
24+
shell: bash
25+
26+
- uses: stefanzweifel/git-auto-commit-action@v5
27+
with:
28+
commit_message: Weekly Update -- Summarize Progress

.scripts/poetry.lock

+140-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.scripts/pyproject.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ python = "^3.10"
1010
polib = "1.1.1"
1111
googletrans = "3.1.0a0"
1212
translate-toolkit = "3.8.1"
13-
13+
requests = "2.31.0"
1414

1515
[build-system]
1616
requires = ["poetry-core"]

.scripts/summarize_progress.sh

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#!/bin/sh
2+
3+
WORK_DIR=.scripts
4+
cd $WORK_DIR
5+
6+
source utils/install_poetry.sh
7+
8+
poetry lock
9+
poetry install
10+
poetry run bash -c "
11+
python summarize_progress/main.py
12+
"

.scripts/summarize_progress/dist/summarize_progress.md

+498
Large diffs are not rendered by default.

.scripts/summarize_progress/main.py

+138
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
import re
2+
import polib
3+
import glob
4+
import datetime
5+
import requests
6+
7+
from pathlib import Path
8+
9+
10+
def entry_check(pofile: polib.POFile) -> str:
11+
'''
12+
Check the po file with how many entries are translated or not.
13+
'''
14+
15+
lines_tranlated = len(pofile.translated_entries())
16+
lines_untranlated = len(pofile.untranslated_entries())
17+
18+
if lines_tranlated == 0:
19+
result = "❌"
20+
elif lines_untranlated == 0:
21+
result = "✅"
22+
else:
23+
lines_all = lines_tranlated + lines_untranlated
24+
progress = lines_tranlated / lines_all
25+
progress_percentage = round(progress * 100, 2)
26+
result = f"Ongoing, {progress_percentage} %"
27+
28+
return result
29+
30+
31+
def get_open_issues_count() -> int:
32+
'''
33+
Fetch GitHub API to get the number of OPEN ISSUES.
34+
'''
35+
36+
url = f"https://api.github.com/search/issues?q=repo:python/python-docs-zh-tw+type:issue+state:open"
37+
headers = {
38+
"Accept": "application/vnd.github+json",
39+
"X-GitHub-Api-Version": "2022-11-28",
40+
}
41+
r = requests.get(url=url, headers=headers)
42+
result = r.json()
43+
44+
return result["total_count"]
45+
46+
47+
def get_github_issues() -> list:
48+
'''
49+
Fetch GitHub API to collect the infomation of OPEN ISSUES,
50+
including issue title and assignee.
51+
52+
Steps:
53+
1. Fetch GitHub API and get open issue list
54+
2. Filter the issue if it have no assignee
55+
3. Filter the issue if it have no "Translate" in the title
56+
4. Filter the issue if it have no correct filepath in the title
57+
'''
58+
NUMBER_OF_ISSUES = get_open_issues_count()
59+
60+
url = f"https://api.github.com/search/issues?q=repo:python/python-docs-zh-tw+type:issue+state:open&per_page={NUMBER_OF_ISSUES}"
61+
headers = {
62+
"Accept": "application/vnd.github+json",
63+
"X-GitHub-Api-Version": "2022-11-28",
64+
}
65+
r = requests.get(url=url, headers=headers)
66+
result = r.json()
67+
68+
result_list = []
69+
for issue in result["items"]:
70+
if issue["assignee"] is None:
71+
continue
72+
73+
title = issue["title"]
74+
if "翻譯" not in title and "translate" not in title.lower():
75+
continue
76+
77+
match = re.search("(?P<dirname>[^\s`][a-zA-z-]+)/(?P<filename>[a-zA-Z0-9._-]+(.po)?)", title)
78+
if not match:
79+
continue
80+
81+
dirname, filename = match.group('dirname', 'filename')
82+
if not filename.endswith('.po'):
83+
filename += '.po'
84+
85+
result_list.append(((dirname, filename), issue["assignee"]["login"]))
86+
87+
return result_list
88+
89+
def format_line_file(filename: str, result: str) -> str:
90+
return f" - {filename.ljust(37, '-')}{result}\r\n"
91+
92+
93+
def format_line_directory(dirname: str) -> str:
94+
return f"- {dirname}/\r\n"
95+
96+
97+
if __name__ == "__main__":
98+
issue_list = get_github_issues()
99+
100+
'''
101+
Search all the po file in the directory,
102+
and record the translation progress of each files.
103+
'''
104+
BASE_DIR = Path("../")
105+
summary = {}
106+
for filepath in glob.glob(str(BASE_DIR / "**/*.po"), recursive=True):
107+
path = Path(filepath)
108+
filename = path.name
109+
dirname = path.parent.name if path.parent.name != BASE_DIR.name else '/'
110+
po = polib.pofile(filepath)
111+
summary.setdefault(dirname, {})[filename] = entry_check(po)
112+
113+
'''
114+
Unpack the open issue list, and add assignee after the progress
115+
'''
116+
for (category, filename), assignee in issue_list:
117+
try:
118+
summary[category][filename] += f", 💻 {assignee}"
119+
except KeyError:
120+
pass
121+
122+
'''
123+
Format the lines that will write into the markdown file,
124+
also sort the directory name and file name.
125+
'''
126+
writeliner = []
127+
summary_sorted = dict(sorted(summary.items()))
128+
for dirname, filedict in summary_sorted.items():
129+
writeliner.append(format_line_directory(dirname))
130+
filedict_sorted = dict(sorted(filedict.items()))
131+
for filename, result in filedict_sorted.items():
132+
writeliner.append(format_line_file(filename, result))
133+
134+
with open(
135+
f"summarize_progress/dist/summarize_progress.md",
136+
"w",
137+
) as file:
138+
file.writelines(writeliner)

c-api/bytearray.po

+8-7
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,8 @@ msgid ""
3333
"This instance of :c:type:`PyTypeObject` represents the Python bytearray "
3434
"type; it is the same object as :class:`bytearray` in the Python layer."
3535
msgstr ""
36-
"這個 :c:type:`PyTypeObject` 的實例代表了 Python 的位元組陣列型別;在 Python "
37-
"中的 :class:`bytearray` 為同一個物件。"
36+
"這個 :c:type:`PyTypeObject` 的實例代表了 Python 的位元組陣列型別;在 Python "
37+
"層中的 :class:`bytearray` 為同一個物件。"
3838

3939
#: ../../c-api/bytearray.rst:23
4040
msgid "Type check macros"
@@ -45,16 +45,16 @@ msgid ""
4545
"Return true if the object *o* is a bytearray object or an instance of a "
4646
"subtype of the bytearray type. This function always succeeds."
4747
msgstr ""
48-
"如果物件 *o* 是一個位元組陣列物件,或者是位元組陣列型別的子型別的實例,則回傳真"
49-
"。此函式總是會成功執行。"
48+
"如果物件 *o* 是一個位元組陣列物件,或者是位元組陣列型別的子型別的實例,則回傳"
49+
"真值。此函式總是會成功執行。"
5050

5151
#: ../../c-api/bytearray.rst:33
5252
msgid ""
5353
"Return true if the object *o* is a bytearray object, but not an instance of "
5454
"a subtype of the bytearray type. This function always succeeds."
5555
msgstr ""
56-
"如果物件 *o* 是一個位元組陣列物件,但不是位元組陣列型別的子型別的實例,則回傳真"
57-
"。此函式總是會成功執行。"
56+
"如果物件 *o* 是一個位元組陣列物件,但不是位元組陣列型別的子型別的實例,則回傳"
57+
"真值。此函式總是會成功執行。"
5858

5959
#: ../../c-api/bytearray.rst:38
6060
msgid "Direct API functions"
@@ -73,7 +73,8 @@ msgid ""
7373
"Create a new bytearray object from *string* and its length, *len*. On "
7474
"failure, ``NULL`` is returned."
7575
msgstr ""
76-
"從 *string* 及其長度 *len* 建立一個新的位元組陣列物件。若失敗則回傳 ``NULL``。"
76+
"從 *string* 及其長度 *len* 建立一個新的位元組陣列物件。若失敗則回傳 "
77+
"``NULL``。"
7778

7879
#: ../../c-api/bytearray.rst:54
7980
msgid ""

c-api/complex.po

+5-4
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,9 @@ msgid ""
4343
"return them as results do so *by value* rather than dereferencing them "
4444
"through pointers. This is consistent throughout the API."
4545
msgstr ""
46-
"請注意,接受這些結構作為參數並將它們作為結果回傳的函式是\\ *按值 (by "
47-
"value)* 執行的,而不是透過指標取消參照 (dereference) 它們。這在整個 API "
48-
"都是一致的。"
46+
"請注意,接受這些結構作為參數並將它們作為結果回傳的函式是\\ *按值 (by value)* "
47+
"執行的,而不是透過指標取消參照 (dereference) 它們。這在整個 API 中都是一致"
48+
"。"
4949

5050
#: ../../c-api/complex.rst:26
5151
msgid ""
@@ -73,7 +73,8 @@ msgstr "以 C 的 :c:type:`Py_complex` 表示形式來回傳兩個複數間的
7373
msgid ""
7474
"Return the negation of the complex number *num*, using the C :c:type:"
7575
"`Py_complex` representation."
76-
msgstr "以 C 的 :c:type:`Py_complex` 表示形式來回傳複數 *num* 的相反數 (negation)。"
76+
msgstr ""
77+
"以 C 的 :c:type:`Py_complex` 表示形式來回傳複數 *num* 的相反數 (negation)。"
7778

7879
#: ../../c-api/complex.rst:57
7980
msgid ""

c-api/datetime.po

+14-14
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,8 @@ msgstr ""
3939
":mod:`datetime` 模組提供各種日期和時間物件。在使用任何這些函式之前,必須將標"
4040
"頭檔 :file:`datetime.h` 引入於原始碼中(請注意,:file:`Python.h` 並無引入該標"
4141
"頭檔),且巨集 :c:macro:`!PyDateTime_IMPORT` 必須被調用,而這通常作為模組初始"
42-
"化函式的一部分。該巨集將指向 C 結構的指標放入靜態變數 :c:data:"
43-
"`!PyDateTimeAPI` 中,該變數會被以下巨集使用。"
42+
"化函式的一部分。該巨集將指向 C 結構的指標放入靜態變數 :c:data:`!"
43+
"PyDateTimeAPI` 中,該變數會被以下巨集使用。"
4444

4545
#: ../../c-api/datetime.rst:18
4646
msgid "This subtype of :c:type:`PyObject` represents a Python date object."
@@ -112,9 +112,9 @@ msgid ""
112112
"of :c:data:`!PyDateTime_DateType`. *ob* must not be ``NULL``. This "
113113
"function always succeeds."
114114
msgstr ""
115-
"如果 *ob* 的型別為 :c:data:`PyDateTime_DateType` 或 :c:data:"
116-
"`!PyDateTime_DateType` 的子型別,則回傳 true。 *ob* 不得為 ``NULL``。這個函式"
117-
"一定會執行成功。"
115+
"如果 *ob* 的型別為 :c:data:`PyDateTime_DateType` 或 :c:data:`!"
116+
"PyDateTime_DateType` 的子型別,則回傳 true。 *ob* 不得為 ``NULL``。這個函式一"
117+
"定會執行成功。"
118118

119119
#: ../../c-api/datetime.rst:80
120120
msgid ""
@@ -130,8 +130,8 @@ msgid ""
130130
"subtype of :c:data:`!PyDateTime_DateTimeType`. *ob* must not be ``NULL``. "
131131
"This function always succeeds."
132132
msgstr ""
133-
"如果 *ob* 的型別為 :c:data:`PyDateTime_DateTimeType` 或 :c:data:"
134-
"`!PyDateTime_DateTimeType` 的子型別,則回傳 true。*ob* 不得為 ``NULL``。這個函"
133+
"如果 *ob* 的型別為 :c:data:`PyDateTime_DateTimeType` 或 :c:data:`!"
134+
"PyDateTime_DateTimeType` 的子型別,則回傳 true。*ob* 不得為 ``NULL``。這個函"
135135
"式一定會執行成功。"
136136

137137
#: ../../c-api/datetime.rst:93
@@ -148,8 +148,8 @@ msgid ""
148148
"of :c:data:`!PyDateTime_TimeType`. *ob* must not be ``NULL``. This "
149149
"function always succeeds."
150150
msgstr ""
151-
"如果 *ob* 的型別為 :c:data:`PyDateTime_TimeType` 或 :c:data:"
152-
"`!PyDateTime_TimeType` 的子型別,則回傳 true。*ob* 不得為 ``NULL``。這個函式一"
151+
"如果 *ob* 的型別為 :c:data:`PyDateTime_TimeType` 或 :c:data:`!"
152+
"PyDateTime_TimeType` 的子型別,則回傳 true。*ob* 不得為 ``NULL``。這個函式一"
153153
"定會執行成功。"
154154

155155
#: ../../c-api/datetime.rst:106
@@ -166,9 +166,9 @@ msgid ""
166166
"of :c:data:`!PyDateTime_DeltaType`. *ob* must not be ``NULL``. This "
167167
"function always succeeds."
168168
msgstr ""
169-
"如果 *ob* 的型別為 :c:data:`PyDateTime_DeltaType` 或 :c:data:"
170-
"`!PyDateTime_DeltaType` 的子型別,則回傳 true。*ob* 不得為 ``NULL``。這個函式"
171-
"一定會執行成功。"
169+
"如果 *ob* 的型別為 :c:data:`PyDateTime_DeltaType` 或 :c:data:`!"
170+
"PyDateTime_DeltaType` 的子型別,則回傳 true。*ob* 不得為 ``NULL``。這個函式一"
171+
"定會執行成功。"
172172

173173
#: ../../c-api/datetime.rst:119
174174
msgid ""
@@ -184,8 +184,8 @@ msgid ""
184184
"of :c:data:`!PyDateTime_TZInfoType`. *ob* must not be ``NULL``. This "
185185
"function always succeeds."
186186
msgstr ""
187-
"如果 *ob* 的型別為 :c:data:`PyDateTime_TZInfoType` 或 :c:data:"
188-
"`!PyDateTime_TZInfoType` 的子型別,則回傳 true。*ob* 不得為 ``NULL``。這個函式"
187+
"如果 *ob* 的型別為 :c:data:`PyDateTime_TZInfoType` 或 :c:data:`!"
188+
"PyDateTime_TZInfoType` 的子型別,則回傳 true。*ob* 不得為 ``NULL``。這個函式"
189189
"一定會執行成功。"
190190

191191
#: ../../c-api/datetime.rst:132

0 commit comments

Comments
 (0)