[3.14] gh-124111: Update Windows build to use Tcl/Tk 9.0.4 (GH-150102) (GH-149477) (GH-151562) (GH-153901) (#150197)
hugovk <[email protected]> Mon, 03 Aug 2026 06:10:50 -0400 (EDT)
| Newsgroups | gmane.comp.python.cvs |
|---|---|
| Message-ID | <[email protected]> |
https://github.com/python/cpython/commit/29a9a3d8ce46b74290cb855455d83900b910882f commit: 29a9a3d8ce46b74290cb855455d83900b910882f branch: 3.14 author: Zachary Ware <[email protected]> committer: hugovk <[email protected]> date: 2026-08-03T13:10:34+03:00 summary: [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 <[email protected]> Co-authored-by: Jonathan J. Helmus <[email protected]> files: A Misc/NEWS.d/next/Windows/2026-06-04-18-53-18.gh-issue-150836.Wci7bZ.rst A Misc/NEWS.d/next/Windows/2026-07-18-11-56-53.gh-issue-124111.m4OBX8.rst M Lib/test/test_tcl.py M Misc/externals.spdx.json M Modules/_tkinter.c M Modules/tkappinit.c M Modules/tkinter.h M PCbuild/get_externals.bat M PCbuild/readme.txt M PCbuild/tcltk.props M Tools/msi/tcltk/tcltk_files.wxs M Tools/msi/testrelease.bat diff --git a/Lib/test/test_tcl.py b/Lib/test/test_tcl.py index 47450d3fd5976fa..70731d3222ced94 100644 --- a/Lib/test/test_tcl.py +++ b/Lib/test/test_tcl.py @@ -54,7 +54,11 @@ def test_eval_null_in_result(self): def test_eval_surrogates_in_result(self): tcl = self.interp - self.assertEqual(tcl.eval(r'set a "<\ud83d\udcbb>"'), '<\U0001f4bb>') + result = tcl.eval(r'set a "<\ud83d\udcbb>"') + if sys.platform == 'win32' and tcl_version >= (9, 0): + self.assertEqual('<\ud83d\udcbb>', result) + else: + self.assertEqual('<\U0001f4bb>', result) def testEvalException(self): tcl = self.interp @@ -289,7 +293,11 @@ def test_evalfile_surrogates_in_result(self): set b "<\\ud83d\\udcbb>" """) tcl.evalfile(filename) - self.assertEqual(tcl.eval('set b'), '<\U0001f4bb>') + result = tcl.eval('set b') + if sys.platform == 'win32' and tcl_version >= (9, 0): + self.assertEqual('<\ud83d\udcbb>', result) + else: + self.assertEqual('<\U0001f4bb>', result) def testEvalFileException(self): tcl = self.interp diff --git a/Misc/NEWS.d/next/Windows/2026-06-04-18-53-18.gh-issue-150836.Wci7bZ.rst b/Misc/NEWS.d/next/Windows/2026-06-04-18-53-18.gh-issue-150836.Wci7bZ.rst new file mode 100644 index 000000000000000..6497b7927db7da3 --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2026-06-04-18-53-18.gh-issue-150836.Wci7bZ.rst @@ -0,0 +1 @@ +Make installed tkinter work with Tcl/Tk 9 builds that embed the Tk script library in the Tk DLL on Windows. diff --git a/Misc/NEWS.d/next/Windows/2026-07-18-11-56-53.gh-issue-124111.m4OBX8.rst b/Misc/NEWS.d/next/Windows/2026-07-18-11-56-53.gh-issue-124111.m4OBX8.rst new file mode 100644 index 000000000000000..802afc6f7a6fc48 --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2026-07-18-11-56-53.gh-issue-124111.m4OBX8.rst @@ -0,0 +1 @@ +Updated Windows builds to use Tcl/Tk 9.0.4. diff --git a/Misc/externals.spdx.json b/Misc/externals.spdx.json index cfc57981092c2e7..8751760f57673a5 100644 --- a/Misc/externals.spdx.json +++ b/Misc/externals.spdx.json @@ -108,46 +108,46 @@ "versionInfo": "3.50.4.0" }, { - "SPDXID": "SPDXRef-PACKAGE-tcl-core", + "SPDXID": "SPDXRef-PACKAGE-tcl", "checksums": [ { "algorithm": "SHA256", - "checksumValue": "4c23f0dd3efcbe6f3a22c503a68d147617bb30c4f5290f1eb3eaacf0b460440b" + "checksumValue": "3ac2acd65ddaaac0b2b8df321b558419d21da20bf67ab39149b8248c85f0d214" } ], - "downloadLocation": "https://github.com/python/cpython-source-deps/archive/refs/tags/tcl-core-8.6.15.0.tar.gz", + "downloadLocation": "https://github.com/python/cpython-source-deps/archive/refs/tags/tcl-9.0.4.0.tar.gz", "externalRefs": [ { "referenceCategory": "SECURITY", - "referenceLocator": "cpe:2.3:a:tcl_tk:tcl_tk:8.6.15.0:*:*:*:*:*:*:*", + "referenceLocator": "cpe:2.3:a:tcl_tk:tcl_tk:9.0.4.0:*:*:*:*:*:*:*", "referenceType": "cpe23Type" } ], "licenseConcluded": "NOASSERTION", - "name": "tcl-core", + "name": "tcl", "primaryPackagePurpose": "SOURCE", - "versionInfo": "8.6.15.0" + "versionInfo": "9.0.4.0" }, { "SPDXID": "SPDXRef-PACKAGE-tk", "checksums": [ { "algorithm": "SHA256", - "checksumValue": "0ae56d39bca92865f338529557a1e56d110594184b6dc5a91339c5675751e264" + "checksumValue": "66048966cfa88989333ff1632f454e10e9248516bb45efda7b4d2ae5a61642cb" } ], - "downloadLocation": "https://github.com/python/cpython-source-deps/archive/refs/tags/tk-8.6.15.0.tar.gz", + "downloadLocation": "https://github.com/python/cpython-source-deps/archive/refs/tags/tk-9.0.4.1.tar.gz", "externalRefs": [ { "referenceCategory": "SECURITY", - "referenceLocator": "cpe:2.3:a:tcl_tk:tcl_tk:8.6.15.0:*:*:*:*:*:*:*", + "referenceLocator": "cpe:2.3:a:tcl_tk:tcl_tk:9.0.4.1:*:*:*:*:*:*:*", "referenceType": "cpe23Type" } ], "licenseConcluded": "NOASSERTION", "name": "tk", "primaryPackagePurpose": "SOURCE", - "versionInfo": "8.6.15.0" + "versionInfo": "9.0.4.1" }, { "SPDXID": "SPDXRef-PACKAGE-xz", diff --git a/Modules/_tkinter.c b/Modules/_tkinter.c index 3b373cdc366c170..22126b67d8f4a0b 100644 --- a/Modules/_tkinter.c +++ b/Modules/_tkinter.c @@ -54,6 +54,10 @@ Copyright (C) 1994 Steen Lumholt. # include <tk.h> #endif +#if defined(MS_WINDOWS) && TK_MAJOR_VERSION >= 9 +# include <tkPlatDecls.h> +#endif + #include "tkinter.h" #if TK_HEX_VERSION < 0x0805020c @@ -199,6 +203,57 @@ _get_tcl_lib_path(void) } #endif /* MS_WINDOWS */ +#if defined(MS_WINDOWS) && TK_MAJOR_VERSION >= 9 +static void +mount_tk_dll_zip(void) +{ + HINSTANCE tk_module = Tk_GetHINSTANCE(); + wchar_t *tk_path = NULL; + DWORD path_len = 0; + for (DWORD buffer_len = 256; + tk_path == NULL && buffer_len < (1024 * 1024); + buffer_len *= 2) + { + tk_path = (wchar_t *)PyMem_RawMalloc( + buffer_len * sizeof(*tk_path)); + if (tk_path != NULL) { + path_len = GetModuleFileNameW(tk_module, tk_path, buffer_len); + if (path_len == buffer_len) { + PyMem_RawFree(tk_path); + tk_path = NULL; + } + } + } + + if (tk_path == NULL || path_len == 0) { + PyMem_RawFree(tk_path); + return; + } + + Tcl_DString utf8_path; + + Tcl_DStringInit(&utf8_path); + Tcl_WCharToUtfDString(tk_path, path_len, &utf8_path); + /* Failure is harmless if the DLL has no embedded ZIP or if another + interpreter has already mounted it. */ + (void) TclZipfs_Mount(NULL, Tcl_DStringValue(&utf8_path), + "//zipfs:/lib/tk", NULL); + Tcl_DStringFree(&utf8_path); + PyMem_RawFree(tk_path); +} +#endif + +int +Tkinter_TkInit(Tcl_Interp *interp) +{ +#if defined(MS_WINDOWS) && TK_MAJOR_VERSION >= 9 + /* Tcl/Tk 9 may embed the tk_library in the Tk DLL which tcl_findLibrary + does not search. Mount the DLL using Zipfs if possible. */ + mount_tk_dll_zip(); +#endif + return Tk_Init(interp); +} + /* The threading situation is complicated. Tcl is not thread-safe, except when configured with --enable-threads. @@ -569,7 +624,7 @@ Tcl_AppInit(Tcl_Interp *interp) return TCL_OK; } - if (Tk_Init(interp) == TCL_ERROR) { + if (Tkinter_TkInit(interp) == TCL_ERROR) { PySys_WriteStderr("Tk_Init error: %s\n", Tcl_GetStringResult(interp)); return TCL_ERROR; } @@ -3013,7 +3068,7 @@ _tkinter_tkapp_loadtk_impl(TkappObject *self) return NULL; } if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) { - if (Tk_Init(interp) == TCL_ERROR) { + if (Tkinter_TkInit(interp) == TCL_ERROR) { Tkinter_Error(self); return NULL; } diff --git a/Modules/tkappinit.c b/Modules/tkappinit.c index 4c4081e43a8e3dd..1075ccf24d44877 100644 --- a/Modules/tkappinit.c +++ b/Modules/tkappinit.c @@ -37,7 +37,7 @@ Tcl_AppInit(Tcl_Interp *interp) return TCL_OK; } - if (Tk_Init(interp) == TCL_ERROR) { + if (Tkinter_TkInit(interp) == TCL_ERROR) { return TCL_ERROR; } diff --git a/Modules/tkinter.h b/Modules/tkinter.h index 40281c217603318..b73e99b28a40212 100644 --- a/Modules/tkinter.h +++ b/Modules/tkinter.h @@ -16,4 +16,6 @@ (TK_RELEASE_LEVEL << 8) | \ (TK_RELEASE_SERIAL << 0)) +int Tkinter_TkInit(Tcl_Interp *interp); + #endif /* !TKINTER_H */ diff --git a/PCbuild/get_externals.bat b/PCbuild/get_externals.bat index 4ce04d46ce2207b..3afa12672202327 100644 --- a/PCbuild/get_externals.bat +++ b/PCbuild/get_externals.bat @@ -57,8 +57,8 @@ if NOT "%IncludeLibffiSrc%"=="false" set libraries=%libraries% libffi-3.4.4 if NOT "%IncludeSSLSrc%"=="false" set libraries=%libraries% openssl-3.5.7 set libraries=%libraries% mpdecimal-4.0.0 set libraries=%libraries% sqlite-3.50.4.0 -if NOT "%IncludeTkinterSrc%"=="false" set libraries=%libraries% tcl-core-8.6.15.0 -if NOT "%IncludeTkinterSrc%"=="false" set libraries=%libraries% tk-8.6.15.0 +if NOT "%IncludeTkinterSrc%"=="false" set libraries=%libraries% tcl-9.0.4.0 +if NOT "%IncludeTkinterSrc%"=="false" set libraries=%libraries% tk-9.0.4.1 set libraries=%libraries% xz-5.2.5 set libraries=%libraries% zlib-ng-2.2.4 set libraries=%libraries% zstd-1.5.7 @@ -80,7 +80,7 @@ echo.Fetching external binaries... set binaries= if NOT "%IncludeLibffi%"=="false" set binaries=%binaries% libffi-3.4.4 if NOT "%IncludeSSL%"=="false" set binaries=%binaries% openssl-bin-3.5.7 -if NOT "%IncludeTkinter%"=="false" set binaries=%binaries% tcltk-8.6.15.0 +if NOT "%IncludeTkinter%"=="false" set binaries=%binaries% tcltk-9.0.4.0 if NOT "%IncludeSSLSrc%"=="false" set binaries=%binaries% nasm-2.11.06 if NOT "%IncludeLLVM%"=="false" set binaries=%binaries% llvm-19.1.7.0 diff --git a/PCbuild/readme.txt b/PCbuild/readme.txt index 13ab06a3cf73a67..84f81d92ef95d0b 100644 --- a/PCbuild/readme.txt +++ b/PCbuild/readme.txt @@ -234,7 +234,7 @@ _sqlite3 Homepage: https://www.sqlite.org/ _tkinter - Wraps version 8.6.15 of the Tk windowing system, which is downloaded + Wraps version 9.0.4 of the Tk windowing system, which is downloaded from our binaries repository at https://github.com/python/cpython-bin-deps. diff --git a/PCbuild/tcltk.props b/PCbuild/tcltk.props index d26b36ba98e493d..1ab8e96122aa2a9 100644 --- a/PCbuild/tcltk.props +++ b/PCbuild/tcltk.props @@ -2,7 +2,7 @@ <Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Import Project="pyproject.props" Condition="$(__PyProject_Props_Imported) != 'true'" /> <PropertyGroup> - <TclVersion Condition="$(TclVersion) == ''">8.6.15.0</TclVersion> + <TclVersion Condition="$(TclVersion) == ''">9.0.4.0</TclVersion> <TkVersion Condition="$(TkVersion) == ''">$(TclVersion)</TkVersion> <TclMajorVersion>$([System.Version]::Parse($(TclVersion)).Major)</TclMajorVersion> <TclMinorVersion>$([System.Version]::Parse($(TclVersion)).Minor)</TclMinorVersion> @@ -12,7 +12,9 @@ <TkMinorVersion>$([System.Version]::Parse($(TkVersion)).Minor)</TkMinorVersion> <TkPatchLevel>$([System.Version]::Parse($(TkVersion)).Build)</TkPatchLevel> <TkRevision>$([System.Version]::Parse($(TkVersion)).Revision)</TkRevision> - <tclDir Condition="$(tclDir) == ''">$(ExternalsDir)tcl-core-$(TclVersion)\</tclDir> + <!-- Back compat hack. If you're here wondering about -core vs not, do us both a favor and just override the whole tclDir variable --> + <tclDir Condition="$(tclDir) == '' and $(TclMajorVersion) == '8'">$(ExternalsDir)tcl-core-$(TclVersion)\</tclDir> + <tclDir Condition="$(tclDir) == ''">$(ExternalsDir)tcl-$(TclVersion)\</tclDir> <tkDir Condition="$(tkDir) == ''">$(ExternalsDir)tk-$(TkVersion)\</tkDir> <tcltkDir Condition="$(tcltkDir) == ''">$(ExternalsDir)tcltk-$(TclVersion)\$(ArchName)\</tcltkDir> <tclWin32Exe Condition="$(Platform) == 'Win32'">$(tcltkDir)\bin\tclsh$(TclMajorVersion)$(TclMinorVersion)t.exe</tclWin32Exe> diff --git a/Tools/msi/tcltk/tcltk_files.wxs b/Tools/msi/tcltk/tcltk_files.wxs index 5dad7c98d4f048a..7c7784741d9178d 100644 --- a/Tools/msi/tcltk/tcltk_files.wxs +++ b/Tools/msi/tcltk/tcltk_files.wxs @@ -10,11 +10,14 @@ <Component Id="_tkinter.lib" Directory="libs" Guid="*"> <File Name="_tkinter.lib" KeyPath="yes" /> </Component> - <Component Id="tcl86t.dll" Directory="DLLs" Guid="*"> - <File Name="tcl86t.dll" KeyPath="yes" /> + <Component Id="tcl90.dll" Directory="DLLs" Guid="*"> + <File Name="tcl90.dll" KeyPath="yes" /> </Component> - <Component Id="tk86t.dll" Directory="DLLs" Guid="*"> - <File Name="tk86t.dll" KeyPath="yes" /> + <Component Id="tcl9tk90.dll" Directory="DLLs" Guid="*"> + <File Name="tcl9tk90.dll" KeyPath="yes" /> + </Component> + <Component Id="libtommath.dll" Directory="DLLs" Guid="*"> + <File Name="libtommath.dll" KeyPath="yes" /> </Component> <Component Id="zlib1.dll" Directory="DLLs" Guid="*"> <File Name="zlib1.dll" KeyPath="yes" /> diff --git a/Tools/msi/testrelease.bat b/Tools/msi/testrelease.bat index 02bcca943cf79b4..db98f690151196c 100644 --- a/Tools/msi/testrelease.bat +++ b/Tools/msi/testrelease.bat @@ -88,9 +88,7 @@ exit /B 0 ) @if not errorlevel 1 ( @echo Testing Tcl/tk - @set TCL_LIBRARY=%~2\Python\tcl\tcl8.6 "%~2\Python\python.exe" -m test -uall -v test_ttk_guionly test_tk test_idle > "%~2\tcltk.txt" 2>&1 - @set TCL_LIBRARY= ) @set EXITCODE=%ERRORLEVEL% _______________________________________________ Python-checkins mailing list -- [email protected] To unsubscribe send an email to [email protected] https://mail.python.org/mailman3//lists/python-checkins.python.org Member address: [email protected]