https://github.com/python/cpython/commit/b83a217558ee30c48a3aa08f0cb7c869f9c75e96
commit: b83a217558ee30c48a3aa08f0cb7c869f9c75e96
branch: 3.15
author: Miss Islington (bot) <[email protected]>
committer: zware <[email protected]>
date: 2026-06-19T18:31:12-05:00
summary:

[3.15] gh-150836: Mount embedded Tk ZIP in _tkinter on Windows (GH-151735)

Tcl/Tk 9 may embed the Tk script library in the Tk DLL on Windows. This 
embedded library is not found by Tcl by default.

Mount the loaded Tk DLL as a zipfs archive before calling Tk_Init(), so Tk can 
find its embedded tk_library using its existing library discovery logic.

Preserve Tk_Init()'s normal path if the library is not embedded.
(cherry picked from commit c4eb3adbb42d781e2ad35bee5621f1c621c6767b)

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
M Modules/_tkinter.c
M Modules/tkappinit.c
M Modules/tkinter.h

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/Modules/_tkinter.c b/Modules/_tkinter.c
index 6eca98a3c8033fa..1deff4ed44684cd 100644
--- a/Modules/_tkinter.c
+++ b/Modules/_tkinter.c
@@ -53,6 +53,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
@@ -175,6 +179,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.
 
@@ -544,7 +599,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;
     }
@@ -2988,7 +3043,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 */

_______________________________________________
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]

Reply via email to