Skip to content

Commit b74b8eb

Browse files
authored
Merge branch '3.13' into tkinter
2 parents 63d20de + 707a327 commit b74b8eb

34 files changed

+1257
-637
lines changed

.github/workflows/ci.yml

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
name: build
22

3+
concurrency: preview-${{ github.ref }}
4+
5+
permissions:
6+
contents: write
7+
pull-requests: write
8+
39
on:
410
pull_request:
511

@@ -19,5 +25,20 @@ jobs:
1925
- name: Install uv
2026
uses: astral-sh/setup-uv@v6
2127

22-
- name: Validate
28+
- name: Build HTML Docs
2329
run: VERSION=${{ github.event.repository.default_branch }} JOBS=4 MODE=html make all
30+
31+
- uses: actions/create-github-app-token@v2
32+
id: app-token
33+
with:
34+
app-id: ${{ secrets.APP_ID }}
35+
private-key: ${{ secrets.APP_PRIVATE_KEY }}
36+
37+
- name: Deploy PR Doc Preview
38+
uses: rossjrw/pr-preview-action@v1
39+
with:
40+
source-dir: ../cpython/Doc/build/html
41+
token: ${{ steps.app-token.outputs.token }}
42+
preview-branch: gh-pages
43+
umbrella-dir: pr-preview
44+
action: auto

.github/workflows/deploy-gh-page.yml

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ jobs:
2323
- name: Deploy to gh page
2424
uses: JamesIves/[email protected]
2525
with:
26-
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
27-
BRANCH: gh-pages
28-
FOLDER: ../cpython/Doc/build/html
29-
CLEAN: true
26+
token: ${{ secrets.GITHUB_TOKEN }}
27+
branch: gh-pages
28+
folder: ../cpython/Doc/build/html
29+
clean: true
30+
clean-exclude: pr-preview/

.github/workflows/py313-sync-cpython.yml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,17 +36,17 @@ jobs:
3636
- name: Sync with CPython
3737
run: make clone merge rm_cpython wrap
3838

39-
- uses: tibdex/github-app-token@v2
40-
id: generate-token
39+
- uses: actions/create-github-app-token@v2
40+
id: app-token
4141
with:
42-
app_id: ${{ secrets.APP_ID }}
43-
private_key: ${{ secrets.APP_PRIVATE_KEY }}
42+
app-id: ${{ secrets.APP_ID }}
43+
private-key: ${{ secrets.APP_PRIVATE_KEY }}
4444

4545
- name: Create Pull Request
4646
id: cpr
4747
uses: peter-evans/create-pull-request@v6
4848
with:
49-
token: ${{ steps.generate-token.outputs.token }}
49+
token: ${{ steps.app-token.outputs.token }}
5050
commit-message: sync with cpython ${{ env.LATEST_COMMIT_ID }}
5151
committer: GitHub <[email protected]>
5252
author: github-actions[bot] <github-actions[bot]@users.noreply.github.com>

.scripts/README.md

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,11 @@
22

33
Useful scripts for the translation.
44

5-
## Translation Dictionary
6-
7-
The repository includes terminology dictionaries (`terminology_dictionary.csv` and `focused_terminology_dictionary.csv`) that provide standard translations for important Python terms to maintain consistency across documents. These dictionaries are maintained using LLM knowledge and can be referenced by translators.
8-
9-
See `TERMINOLOGY_DICTIONARY.md` for detailed usage and integration with translation workflow.
10-
115
## From Google Translation
126

137
Translate all untranslated entries of the given .po file with Google Translate.
148

9+
1510
```sh
1611
.scripts/google_translate.sh library/csv.po
1712
```

.scripts/summarize_progress/main.py

Lines changed: 55 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -6,27 +6,6 @@
66
from pathlib import Path
77

88

9-
def entry_check(pofile: polib.POFile) -> str:
10-
'''
11-
Check the po file with how many entries are translated or not.
12-
'''
13-
14-
lines_tranlated = len(pofile.translated_entries())
15-
lines_untranlated = len(pofile.untranslated_entries())
16-
17-
if lines_tranlated == 0:
18-
result = "❌"
19-
elif lines_untranlated == 0:
20-
result = "✅"
21-
else:
22-
lines_all = lines_tranlated + lines_untranlated
23-
progress = lines_tranlated / lines_all
24-
progress_percentage = round(progress * 100, 2)
25-
result = f"{progress_percentage} %"
26-
27-
return result
28-
29-
309
def get_open_issues_count() -> int:
3110
'''
3211
Fetch GitHub API to get the number of OPEN ISSUES.
@@ -89,21 +68,23 @@ def get_github_issues() -> list:
8968

9069

9170
def format_line_table_header() -> list:
92-
return [f"|Filename|Progress|Issue|Assignee|\r\n",
71+
return [f"|Filename|Progress (#string)|Issue|Assignee|\r\n",
9372
f"|-------:|:-------|:----|:-------|\r\n"]
9473

9574

96-
def format_issue_link(url: str) -> str:
97-
return f"[{url.split('/')[-1]}]({url})" if len(url) > 0 else ''
98-
99-
100-
def format_line_file(dirname: str, filename: str, data: dict) -> str:
101-
return f"|[`{filename}`](https://github.com/python/python-docs-zh-tw/tree/3.13/{dirname}/{filename})" + \
102-
f"|{data['progress']}|{format_issue_link(data['issue'])}|{data['assignee']}|\r\n"
75+
def format_line_po_issue_display(issue_link: str, issue_number: str, progress: float, create_issue_link: str) -> str:
76+
if issue_link:
77+
return f"[{issue_number}]({issue_link})"
78+
if progress != 100.:
79+
return f"[create issue]({create_issue_link})"
80+
return ""
10381

10482

105-
def format_line_directory(dirname: str) -> str:
106-
return f"## {dirname}\r\n"
83+
def format_line_po(filename: str, po_link: str, progress: str, num_entries: str, issue_display: str, assignee: str) -> str:
84+
progress_display = f"{progress} %"
85+
if progress == 100:
86+
progress_display = "✅"
87+
return f"|[`{filename}`]({po_link})|{progress_display} ({num_entries:,})|{issue_display}|{assignee}|\r\n"
10788

10889

10990
if __name__ == "__main__":
@@ -118,11 +99,17 @@ def format_line_directory(dirname: str) -> str:
11899
for filepath in glob.glob(str(BASE_DIR / "**/*.po"), recursive=True):
119100
path = Path(filepath)
120101
filename = path.name
121-
dirname = path.parent.name if path.parent.name != BASE_DIR.name else '/'
102+
dirname = path.parent.name if path.parent.name != BASE_DIR.name else 'root'
122103
po = polib.pofile(filepath)
123104

105+
num_entries = len(list(filter(lambda e: not e.obsolete, po)))
106+
num_translated = len(po.translated_entries())
124107
summary.setdefault(dirname, {})[filename] = {
125-
'progress': entry_check(po),
108+
'po_info': {
109+
'num_entries': num_entries,
110+
'num_translated': num_translated,
111+
'progress': round(num_translated / num_entries * 100, 2),
112+
},
126113
'issue': '',
127114
'assignee': '',
128115
}
@@ -138,25 +125,47 @@ def format_line_directory(dirname: str) -> str:
138125
pass
139126

140127
'''
141-
Adding Space for Formatting Markdown Link
142-
'''
143-
144-
'''
145-
Format the lines that will write into the markdown file,
128+
Format the lines that will be written into the markdown file,
146129
also sort the directory name and file name.
147130
'''
148131
writeliner = []
149132
summary_sorted = dict(sorted(summary.items()))
133+
total_entries, total_translated = 0, 0
150134
for dirname, filedict in summary_sorted.items():
151-
writeliner.append(format_line_directory(dirname))
152-
writeliner.extend(format_line_table_header())
153-
135+
dir_total_entries, dir_total_translated = 0, 0
136+
lines = []
154137
filedict_sorted = dict(sorted(filedict.items()))
155138
for filename, filedata in filedict_sorted.items():
156-
writeliner.append(format_line_file(dirname, filename, filedata))
139+
file_path = f"{dirname}/{filename}" if dirname else filename
140+
po_link = f"https://github.com/python/python-docs-zh-tw/tree/3.13/{file_path}"
141+
issue_link = filedata['issue']
142+
issue_number = f"#{issue_link.split('/')[-1]}"
143+
create_issue_link = f"https://github.com/python/python-docs-zh-tw/issues/new?title=Translate%20`{file_path}`"
144+
issue_display = format_line_po_issue_display(issue_link, issue_number, filedata['po_info']['progress'], create_issue_link)
145+
line_po = format_line_po(
146+
filename,
147+
po_link,
148+
filedata['po_info']['progress'],
149+
filedata['po_info']['num_entries'],
150+
issue_display,
151+
filedata['assignee'],
152+
)
153+
lines.append(line_po)
154+
155+
dir_total_entries += filedata['po_info']['num_entries']
156+
dir_total_translated += filedata['po_info']['num_translated']
157+
158+
dir_progress = round(dir_total_translated / dir_total_entries * 100, 2)
159+
writeliner.append(f"## {dirname} ({dir_progress}%)\r\n")
160+
writeliner.extend(format_line_table_header())
161+
writeliner.extend(lines)
162+
163+
total_entries += dir_total_entries
164+
total_translated += dir_total_translated
165+
166+
overall_progress = round(total_translated / total_entries * 100, 2)
167+
title = f"## Overall Progress: {overall_progress}% ({total_translated:,} / {total_entries:,})\r\n"
168+
writeliner = [title] + writeliner
157169

158-
with open(
159-
f"summarize_progress/result.md",
160-
"w",
161-
) as file:
170+
with open(f"summarize_progress/result.md", "w") as file:
162171
file.writelines(writeliner)

c-api/allocation.po

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright (C) 2001-2024, Python Software Foundation
1+
# Copyright (C) 2001-2025, Python Software Foundation
22
# This file is distributed under the same license as the Python package.
33
#
44
# Translators:
@@ -62,6 +62,8 @@ msgid ""
6262
"`Py_TPFLAGS_HAVE_GC` set. For such objects, use :c:func:`PyObject_GC_New` "
6363
"instead."
6464
msgstr ""
65+
"注意,如果 *typeobj* 有 :c:macro:`Py_TPFLAGS_HAVE_GC` 設定,則此函式不適用。"
66+
"對於這種物件,請改用 :c:func:`PyObject_GC_New`。"
6567

6668
#: ../../c-api/allocation.rst:45
6769
msgid ""
@@ -88,6 +90,8 @@ msgid ""
8890
"`Py_TPFLAGS_HAVE_GC` set. For such objects, use :c:func:`PyObject_GC_NewVar` "
8991
"instead."
9092
msgstr ""
93+
"注意,如果 *typeobj* 有 :c:macro:`Py_TPFLAGS_HAVE_GC` 設定,則此函式不適用。"
94+
"對於這種物件,請改用 :c:func:`PyObject_GC_NewVar`。"
9195

9296
#: ../../c-api/allocation.rst:63
9397
msgid ""

c-api/bool.po

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
# SOME DESCRIPTIVE TITLE.
2-
# Copyright (C) 2001-2022, Python Software Foundation
1+
# Copyright (C) 2001-2025, Python Software Foundation
32
# This file is distributed under the same license as the Python package.
43
#
54
# Translators:
@@ -42,6 +41,8 @@ msgid ""
4241
"This instance of :c:type:`PyTypeObject` represents the Python boolean type; "
4342
"it is the same object as :class:`bool` in the Python layer."
4443
msgstr ""
44+
"此 :c:type:`PyTypeObject` 實例代表 Python 的布林型別;它與 Python 層級中的 "
45+
":class:`bool` 是同一個物件。"
4546

4647
#: ../../c-api/bool.rst:22
4748
msgid ""

c-api/call.po

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright (C) 2001-2023, Python Software Foundation
1+
# Copyright (C) 2001-2025, Python Software Foundation
22
# This file is distributed under the same license as the Python package.
33
#
44
# Translators:
@@ -122,6 +122,11 @@ msgid ""
122122
"versions, vectorcall should only be used with :c:macro:`immutable "
123123
"<Py_TPFLAGS_IMMUTABLETYPE>` or static types."
124124
msgstr ""
125+
"當一個類別的 :py:meth:`~object.__call__` 方法被重新賦值時,:c:macro:"
126+
"`Py_TPFLAGS_HAVE_VECTORCALL` 旗標現在會被移除。(這會在內部設定 :c:member:"
127+
"`~PyTypeObject.tp_call`,因此可能會使它與 vectorcall 函式有不同的行為。)"
128+
"在較早的 Python 版本中,vectorcall 應該只與 :c:macro:"
129+
"`immutable <Py_TPFLAGS_IMMUTABLETYPE>` 或靜態型別一起使用。"
125130

126131
#: ../../c-api/call.rst:69
127132
msgid ""

c-api/hash.po

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright (C) 2001-2024, Python Software Foundation
1+
# Copyright (C) 2001-2025, Python Software Foundation
22
# This file is distributed under the same license as the Python package.
33
#
44
# Translators:
@@ -39,22 +39,24 @@ msgid ""
3939
"The `Mersenne prime <https://en.wikipedia.org/wiki/Mersenne_prime>`_ ``P = "
4040
"2**n -1``, used for numeric hash scheme."
4141
msgstr ""
42+
"用於數值雜湊方案的\\ `梅森質數 (Mersenne prime) <https://en.wikipedia.org/"
43+
"wiki/Mersenne_prime>`_ ``P = 2**n -1``。"
4244

4345
#: ../../c-api/hash.rst:28
4446
msgid "The exponent ``n`` of ``P`` in :c:macro:`PyHASH_MODULUS`."
45-
msgstr ""
47+
msgstr ":c:macro:`PyHASH_MODULUS` 中 ``P`` 的指數 ``n``。"
4648

4749
#: ../../c-api/hash.rst:34
4850
msgid "Prime multiplier used in string and various other hashes."
49-
msgstr ""
51+
msgstr "用於字串和其他各種雜湊的質數乘數 (prime multiplier)。"
5052

5153
#: ../../c-api/hash.rst:40
5254
msgid "The hash value returned for a positive infinity."
53-
msgstr ""
55+
msgstr "正無窮大回傳的雜湊值。"
5456

5557
#: ../../c-api/hash.rst:46
5658
msgid "The multiplier used for the imaginary part of a complex number."
57-
msgstr ""
59+
msgstr "用於複數虛數部分的乘數。"
5860

5961
#: ../../c-api/hash.rst:52
6062
msgid "Hash function definition used by :c:func:`PyHash_GetFuncDef`."
@@ -87,17 +89,21 @@ msgid ""
8789
"Hash a pointer value: process the pointer value as an integer (cast it to "
8890
"``uintptr_t`` internally). The pointer is not dereferenced."
8991
msgstr ""
92+
"雜湊指標值:將指標值作為整數處理(在內部轉型為 ``uintptr_t``)。指標不會被取"
93+
"值 (dereference)。"
9094

9195
#: ../../c-api/hash.rst:88
9296
msgid "The function cannot fail: it cannot return ``-1``."
93-
msgstr ""
97+
msgstr "此函式不會失敗:它不會回傳 ``-1``。"
9498

9599
#: ../../c-api/hash.rst:94
96100
msgid ""
97101
"Generic hashing function that is meant to be put into a type object's "
98102
"``tp_hash`` slot. Its result only depends on the object's identity."
99103
msgstr ""
104+
"泛用雜湊函式,旨在放入型別物件的 ``tp_hash`` 插槽中。其結果僅取決於物件的識別"
105+
"性。"
100106

101107
#: ../../c-api/hash.rst:99
102108
msgid "In CPython, it is equivalent to :c:func:`Py_HashPointer`."
103-
msgstr ""
109+
msgstr "在 CPython 中,它等價於 :c:func:`Py_HashPointer`。"

c-api/iter.po

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright (C) 2001-2023, Python Software Foundation
1+
# Copyright (C) 2001-2025, Python Software Foundation
22
# This file is distributed under the same license as the Python package.
33
#
44
# Translators:
@@ -87,6 +87,28 @@ msgid ""
8787
" /* continue doing useful work */\n"
8888
"}"
8989
msgstr ""
90+
"PyObject *iterator = PyObject_GetIter(obj);\n"
91+
"PyObject *item;\n"
92+
"\n"
93+
"if (iterator == NULL) {\n"
94+
" /* 傳播錯誤 */\n"
95+
"}\n"
96+
"\n"
97+
"while ((item = PyIter_Next(iterator))) {\n"
98+
" /* 對 item 做些事情 */\n"
99+
" ...\n"
100+
" /* 完成後釋放參照 */\n"
101+
" Py_DECREF(item);\n"
102+
"}\n"
103+
"\n"
104+
"Py_DECREF(iterator);\n"
105+
"\n"
106+
"if (PyErr_Occurred()) {\n"
107+
" /* 傳播錯誤 */\n"
108+
"}\n"
109+
"else {\n"
110+
" /* 繼續做一些有用的任務 */\n"
111+
"}"
90112

91113
#: ../../c-api/iter.rst:59
92114
msgid ""

0 commit comments

Comments
 (0)