Skip to content

Commit 29a9a3d

Browse files
zwarezoobajjhelmus
authored
[3.14] gh-124111: Update Windows build to use Tcl/Tk 9.0.4 (GH-150102) (GH-149477) (GH-151562) (GH-153901) (#150197)
Co-authored-by: Steve Dower <steve.dower@python.org> Co-authored-by: Jonathan J. Helmus <jjhelmus@gmail.com>
1 parent 90be969 commit 29a9a3d

12 files changed

Lines changed: 97 additions & 27 deletions

Lib/test/test_tcl.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,11 @@ def test_eval_null_in_result(self):
5454

5555
def test_eval_surrogates_in_result(self):
5656
tcl = self.interp
57-
self.assertEqual(tcl.eval(r'set a "<\ud83d\udcbb>"'), '<\U0001f4bb>')
57+
result = tcl.eval(r'set a "<\ud83d\udcbb>"')
58+
if sys.platform == 'win32' and tcl_version >= (9, 0):
59+
self.assertEqual('<\ud83d\udcbb>', result)
60+
else:
61+
self.assertEqual('<\U0001f4bb>', result)
5862

5963
def testEvalException(self):
6064
tcl = self.interp
@@ -289,7 +293,11 @@ def test_evalfile_surrogates_in_result(self):
289293
set b "<\\ud83d\\udcbb>"
290294
""")
291295
tcl.evalfile(filename)
292-
self.assertEqual(tcl.eval('set b'), '<\U0001f4bb>')
296+
result = tcl.eval('set b')
297+
if sys.platform == 'win32' and tcl_version >= (9, 0):
298+
self.assertEqual('<\ud83d\udcbb>', result)
299+
else:
300+
self.assertEqual('<\U0001f4bb>', result)
293301

294302
def testEvalFileException(self):
295303
tcl = self.interp
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Make installed tkinter work with Tcl/Tk 9 builds that embed the Tk script library in the Tk DLL on Windows.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Updated Windows builds to use Tcl/Tk 9.0.4.

Misc/externals.spdx.json

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -108,46 +108,46 @@
108108
"versionInfo": "3.50.4.0"
109109
},
110110
{
111-
"SPDXID": "SPDXRef-PACKAGE-tcl-core",
111+
"SPDXID": "SPDXRef-PACKAGE-tcl",
112112
"checksums": [
113113
{
114114
"algorithm": "SHA256",
115-
"checksumValue": "4c23f0dd3efcbe6f3a22c503a68d147617bb30c4f5290f1eb3eaacf0b460440b"
115+
"checksumValue": "3ac2acd65ddaaac0b2b8df321b558419d21da20bf67ab39149b8248c85f0d214"
116116
}
117117
],
118-
"downloadLocation": "https://github.com/python/cpython-source-deps/archive/refs/tags/tcl-core-8.6.15.0.tar.gz",
118+
"downloadLocation": "https://github.com/python/cpython-source-deps/archive/refs/tags/tcl-9.0.4.0.tar.gz",
119119
"externalRefs": [
120120
{
121121
"referenceCategory": "SECURITY",
122-
"referenceLocator": "cpe:2.3:a:tcl_tk:tcl_tk:8.6.15.0:*:*:*:*:*:*:*",
122+
"referenceLocator": "cpe:2.3:a:tcl_tk:tcl_tk:9.0.4.0:*:*:*:*:*:*:*",
123123
"referenceType": "cpe23Type"
124124
}
125125
],
126126
"licenseConcluded": "NOASSERTION",
127-
"name": "tcl-core",
127+
"name": "tcl",
128128
"primaryPackagePurpose": "SOURCE",
129-
"versionInfo": "8.6.15.0"
129+
"versionInfo": "9.0.4.0"
130130
},
131131
{
132132
"SPDXID": "SPDXRef-PACKAGE-tk",
133133
"checksums": [
134134
{
135135
"algorithm": "SHA256",
136-
"checksumValue": "0ae56d39bca92865f338529557a1e56d110594184b6dc5a91339c5675751e264"
136+
"checksumValue": "66048966cfa88989333ff1632f454e10e9248516bb45efda7b4d2ae5a61642cb"
137137
}
138138
],
139-
"downloadLocation": "https://github.com/python/cpython-source-deps/archive/refs/tags/tk-8.6.15.0.tar.gz",
139+
"downloadLocation": "https://github.com/python/cpython-source-deps/archive/refs/tags/tk-9.0.4.1.tar.gz",
140140
"externalRefs": [
141141
{
142142
"referenceCategory": "SECURITY",
143-
"referenceLocator": "cpe:2.3:a:tcl_tk:tcl_tk:8.6.15.0:*:*:*:*:*:*:*",
143+
"referenceLocator": "cpe:2.3:a:tcl_tk:tcl_tk:9.0.4.1:*:*:*:*:*:*:*",
144144
"referenceType": "cpe23Type"
145145
}
146146
],
147147
"licenseConcluded": "NOASSERTION",
148148
"name": "tk",
149149
"primaryPackagePurpose": "SOURCE",
150-
"versionInfo": "8.6.15.0"
150+
"versionInfo": "9.0.4.1"
151151
},
152152
{
153153
"SPDXID": "SPDXRef-PACKAGE-xz",

Modules/_tkinter.c

Lines changed: 57 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,10 @@ Copyright (C) 1994 Steen Lumholt.
5454
# include <tk.h>
5555
#endif
5656

57+
#if defined(MS_WINDOWS) && TK_MAJOR_VERSION >= 9
58+
# include <tkPlatDecls.h>
59+
#endif
60+
5761
#include "tkinter.h"
5862

5963
#if TK_HEX_VERSION < 0x0805020c
@@ -199,6 +203,57 @@ _get_tcl_lib_path(void)
199203
}
200204
#endif /* MS_WINDOWS */
201205

206+
#if defined(MS_WINDOWS) && TK_MAJOR_VERSION >= 9
207+
static void
208+
mount_tk_dll_zip(void)
209+
{
210+
HINSTANCE tk_module = Tk_GetHINSTANCE();
211+
wchar_t *tk_path = NULL;
212+
DWORD path_len = 0;
213+
for (DWORD buffer_len = 256;
214+
tk_path == NULL && buffer_len < (1024 * 1024);
215+
buffer_len *= 2)
216+
{
217+
tk_path = (wchar_t *)PyMem_RawMalloc(
218+
buffer_len * sizeof(*tk_path));
219+
if (tk_path != NULL) {
220+
path_len = GetModuleFileNameW(tk_module, tk_path, buffer_len);
221+
if (path_len == buffer_len) {
222+
PyMem_RawFree(tk_path);
223+
tk_path = NULL;
224+
}
225+
}
226+
}
227+
228+
if (tk_path == NULL || path_len == 0) {
229+
PyMem_RawFree(tk_path);
230+
return;
231+
}
232+
233+
Tcl_DString utf8_path;
234+
235+
Tcl_DStringInit(&utf8_path);
236+
Tcl_WCharToUtfDString(tk_path, path_len, &utf8_path);
237+
/* Failure is harmless if the DLL has no embedded ZIP or if another
238+
interpreter has already mounted it. */
239+
(void) TclZipfs_Mount(NULL, Tcl_DStringValue(&utf8_path),
240+
"//zipfs:/lib/tk", NULL);
241+
Tcl_DStringFree(&utf8_path);
242+
PyMem_RawFree(tk_path);
243+
}
244+
#endif
245+
246+
int
247+
Tkinter_TkInit(Tcl_Interp *interp)
248+
{
249+
#if defined(MS_WINDOWS) && TK_MAJOR_VERSION >= 9
250+
/* Tcl/Tk 9 may embed the tk_library in the Tk DLL which tcl_findLibrary
251+
does not search. Mount the DLL using Zipfs if possible. */
252+
mount_tk_dll_zip();
253+
#endif
254+
return Tk_Init(interp);
255+
}
256+
202257
/* The threading situation is complicated. Tcl is not thread-safe, except
203258
when configured with --enable-threads.
204259
@@ -569,7 +624,7 @@ Tcl_AppInit(Tcl_Interp *interp)
569624
return TCL_OK;
570625
}
571626

572-
if (Tk_Init(interp) == TCL_ERROR) {
627+
if (Tkinter_TkInit(interp) == TCL_ERROR) {
573628
PySys_WriteStderr("Tk_Init error: %s\n", Tcl_GetStringResult(interp));
574629
return TCL_ERROR;
575630
}
@@ -3013,7 +3068,7 @@ _tkinter_tkapp_loadtk_impl(TkappObject *self)
30133068
return NULL;
30143069
}
30153070
if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
3016-
if (Tk_Init(interp) == TCL_ERROR) {
3071+
if (Tkinter_TkInit(interp) == TCL_ERROR) {
30173072
Tkinter_Error(self);
30183073
return NULL;
30193074
}

Modules/tkappinit.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ Tcl_AppInit(Tcl_Interp *interp)
3737
return TCL_OK;
3838
}
3939

40-
if (Tk_Init(interp) == TCL_ERROR) {
40+
if (Tkinter_TkInit(interp) == TCL_ERROR) {
4141
return TCL_ERROR;
4242
}
4343

Modules/tkinter.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,6 @@
1616
(TK_RELEASE_LEVEL << 8) | \
1717
(TK_RELEASE_SERIAL << 0))
1818

19+
int Tkinter_TkInit(Tcl_Interp *interp);
20+
1921
#endif /* !TKINTER_H */

PCbuild/get_externals.bat

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,8 @@ if NOT "%IncludeLibffiSrc%"=="false" set libraries=%libraries% libffi-3.4.4
5757
if NOT "%IncludeSSLSrc%"=="false" set libraries=%libraries% openssl-3.5.7
5858
set libraries=%libraries% mpdecimal-4.0.0
5959
set libraries=%libraries% sqlite-3.50.4.0
60-
if NOT "%IncludeTkinterSrc%"=="false" set libraries=%libraries% tcl-core-8.6.15.0
61-
if NOT "%IncludeTkinterSrc%"=="false" set libraries=%libraries% tk-8.6.15.0
60+
if NOT "%IncludeTkinterSrc%"=="false" set libraries=%libraries% tcl-9.0.4.0
61+
if NOT "%IncludeTkinterSrc%"=="false" set libraries=%libraries% tk-9.0.4.1
6262
set libraries=%libraries% xz-5.2.5
6363
set libraries=%libraries% zlib-ng-2.2.4
6464
set libraries=%libraries% zstd-1.5.7
@@ -80,7 +80,7 @@ echo.Fetching external binaries...
8080
set binaries=
8181
if NOT "%IncludeLibffi%"=="false" set binaries=%binaries% libffi-3.4.4
8282
if NOT "%IncludeSSL%"=="false" set binaries=%binaries% openssl-bin-3.5.7
83-
if NOT "%IncludeTkinter%"=="false" set binaries=%binaries% tcltk-8.6.15.0
83+
if NOT "%IncludeTkinter%"=="false" set binaries=%binaries% tcltk-9.0.4.0
8484
if NOT "%IncludeSSLSrc%"=="false" set binaries=%binaries% nasm-2.11.06
8585
if NOT "%IncludeLLVM%"=="false" set binaries=%binaries% llvm-19.1.7.0
8686

PCbuild/readme.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,7 @@ _sqlite3
234234
Homepage:
235235
https://www.sqlite.org/
236236
_tkinter
237-
Wraps version 8.6.15 of the Tk windowing system, which is downloaded
237+
Wraps version 9.0.4 of the Tk windowing system, which is downloaded
238238
from our binaries repository at
239239
https://github.com/python/cpython-bin-deps.
240240

PCbuild/tcltk.props

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
33
<Import Project="pyproject.props" Condition="$(__PyProject_Props_Imported) != 'true'" />
44
<PropertyGroup>
5-
<TclVersion Condition="$(TclVersion) == ''">8.6.15.0</TclVersion>
5+
<TclVersion Condition="$(TclVersion) == ''">9.0.4.0</TclVersion>
66
<TkVersion Condition="$(TkVersion) == ''">$(TclVersion)</TkVersion>
77
<TclMajorVersion>$([System.Version]::Parse($(TclVersion)).Major)</TclMajorVersion>
88
<TclMinorVersion>$([System.Version]::Parse($(TclVersion)).Minor)</TclMinorVersion>
@@ -12,7 +12,9 @@
1212
<TkMinorVersion>$([System.Version]::Parse($(TkVersion)).Minor)</TkMinorVersion>
1313
<TkPatchLevel>$([System.Version]::Parse($(TkVersion)).Build)</TkPatchLevel>
1414
<TkRevision>$([System.Version]::Parse($(TkVersion)).Revision)</TkRevision>
15-
<tclDir Condition="$(tclDir) == ''">$(ExternalsDir)tcl-core-$(TclVersion)\</tclDir>
15+
<!-- Back compat hack. If you're here wondering about -core vs not, do us both a favor and just override the whole tclDir variable -->
16+
<tclDir Condition="$(tclDir) == '' and $(TclMajorVersion) == '8'">$(ExternalsDir)tcl-core-$(TclVersion)\</tclDir>
17+
<tclDir Condition="$(tclDir) == ''">$(ExternalsDir)tcl-$(TclVersion)\</tclDir>
1618
<tkDir Condition="$(tkDir) == ''">$(ExternalsDir)tk-$(TkVersion)\</tkDir>
1719
<tcltkDir Condition="$(tcltkDir) == ''">$(ExternalsDir)tcltk-$(TclVersion)\$(ArchName)\</tcltkDir>
1820
<tclWin32Exe Condition="$(Platform) == 'Win32'">$(tcltkDir)\bin\tclsh$(TclMajorVersion)$(TclMinorVersion)t.exe</tclWin32Exe>

0 commit comments

Comments
 (0)