Skip to content

Commit 67034b9

Browse files
committed
BUG: restore tcl/tk patch on python 3.14+
Restore patch used to find Tcl/Tk libraries relative to the base prefix on Python 3.14+. This patches was accidentally removed in #845. Rewrite the conditionals in the patch block to make it more obvious what patches are applied for each python version. closes #913
1 parent 91f343f commit 67034b9

File tree

2 files changed

+123
-4
lines changed

2 files changed

+123
-4
lines changed

cpython-unix/build-cpython.sh

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -188,13 +188,15 @@ fi
188188
# On Windows, CPython looks for the Tcl/Tk libraries relative to the base prefix,
189189
# which we want. But on Unix, it doesn't. This patch applies similar behavior on Unix,
190190
# thereby ensuring that the Tcl/Tk libraries are found in the correct location.
191-
if [ "${PYTHON_MAJMIN_VERSION}" = "3.13" ]; then
191+
if [ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_14}" ]; then
192+
patch -p1 -i ${ROOT}/patch-tkinter-3.14.patch
193+
elif [ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_13}" ]; then
192194
patch -p1 -i ${ROOT}/patch-tkinter-3.13.patch
193-
elif [ "${PYTHON_MAJMIN_VERSION}" = "3.12" ]; then
195+
elif [ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_12}" ]; then
194196
patch -p1 -i ${ROOT}/patch-tkinter-3.12.patch
195-
elif [ "${PYTHON_MAJMIN_VERSION}" = "3.11" ]; then
197+
elif [ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_11}" ]; then
196198
patch -p1 -i ${ROOT}/patch-tkinter-3.11.patch
197-
elif [ "${PYTHON_MAJMIN_VERSION}" = "3.10" ]; then
199+
elif [ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_10}" ]; then
198200
patch -p1 -i ${ROOT}/patch-tkinter-3.10.patch
199201
fi
200202

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
diff --git a/Modules/_tkinter.c b/Modules/_tkinter.c
2+
index e153047b778..02f5d12db1a 100644
3+
--- a/Modules/_tkinter.c
4+
+++ b/Modules/_tkinter.c
5+
@@ -115,6 +115,7 @@ Copyright (C) 1994 Steen Lumholt.
6+
#ifdef MS_WINDOWS
7+
#include <conio.h>
8+
#define WAIT_FOR_STDIN
9+
+#endif
10+
11+
static PyObject *
12+
_get_tcl_lib_path()
13+
@@ -132,6 +133,7 @@ _get_tcl_lib_path()
14+
return NULL;
15+
}
16+
17+
+#ifdef MS_WINDOWS
18+
/* Check expected location for an installed Python first */
19+
tcl_library_path = PyUnicode_FromString("\\tcl\\tcl" TCL_VERSION);
20+
if (tcl_library_path == NULL) {
21+
@@ -169,11 +171,31 @@ _get_tcl_lib_path()
22+
tcl_library_path = NULL;
23+
#endif
24+
}
25+
+#else
26+
+ /* Check expected location for an installed Python first */
27+
+ tcl_library_path = PyUnicode_FromString("/lib/tcl" TCL_VERSION);
28+
+ if (tcl_library_path == NULL) {
29+
+ return NULL;
30+
+ }
31+
+ tcl_library_path = PyUnicode_Concat(prefix, tcl_library_path);
32+
+ if (tcl_library_path == NULL) {
33+
+ return NULL;
34+
+ }
35+
+ stat_return_value = _Py_stat(tcl_library_path, &stat_buf);
36+
+ if (stat_return_value == -2) {
37+
+ return NULL;
38+
+ }
39+
+ if (stat_return_value == -1) {
40+
+ /* install location doesn't exist, reset errno and leave Tcl
41+
+ to its own devices */
42+
+ errno = 0;
43+
+ tcl_library_path = NULL;
44+
+ }
45+
+#endif
46+
already_checked = 1;
47+
}
48+
return tcl_library_path;
49+
}
50+
-#endif /* MS_WINDOWS */
51+
52+
/* The threading situation is complicated. Tcl is not thread-safe, except
53+
when configured with --enable-threads.
54+
@@ -822,6 +844,30 @@ Tkapp_New(const char *screenName, const char *className,
55+
56+
ret = GetEnvironmentVariableW(L"TCL_LIBRARY", NULL, 0);
57+
if (!ret && GetLastError() == ERROR_ENVVAR_NOT_FOUND) {
58+
+ str_path = _get_tcl_lib_path();
59+
+ if (str_path == NULL && PyErr_Occurred()) {
60+
+ return NULL;
61+
+ }
62+
+ if (str_path != NULL) {
63+
+ utf8_path = PyUnicode_AsUTF8String(str_path);
64+
+ if (utf8_path == NULL) {
65+
+ return NULL;
66+
+ }
67+
+ Tcl_SetVar(v->interp,
68+
+ "tcl_library",
69+
+ PyBytes_AS_STRING(utf8_path),
70+
+ TCL_GLOBAL_ONLY);
71+
+ Py_DECREF(utf8_path);
72+
+ }
73+
+ }
74+
+ }
75+
+#else
76+
+ {
77+
+ const char *env_val = getenv("TCL_LIBRARY");
78+
+ if (!env_val) {
79+
+ PyObject *str_path;
80+
+ PyObject *utf8_path;
81+
+
82+
str_path = _get_tcl_lib_path();
83+
if (str_path == NULL && PyErr_Occurred()) {
84+
return NULL;
85+
@@ -3631,7 +3677,32 @@ PyInit__tkinter(void)
86+
PyMem_Free(wcs_path);
87+
}
88+
#else
89+
+ int set_var = 0;
90+
+ PyObject *str_path;
91+
+ char *path;
92+
+
93+
+ if (!getenv("TCL_LIBRARY")) {
94+
+ str_path = _get_tcl_lib_path();
95+
+ if (str_path == NULL && PyErr_Occurred()) {
96+
+ Py_DECREF(m);
97+
+ return NULL;
98+
+ }
99+
+ if (str_path != NULL) {
100+
+ path = PyUnicode_AsUTF8(str_path);
101+
+ if (path == NULL) {
102+
+ Py_DECREF(m);
103+
+ return NULL;
104+
+ }
105+
+ setenv("TCL_LIBRARY", path, 1);
106+
+ set_var = 1;
107+
+ }
108+
+ }
109+
+
110+
Tcl_FindExecutable(PyBytes_AS_STRING(cexe));
111+
+
112+
+ if (set_var) {
113+
+ unsetenv("TCL_LIBRARY");
114+
+ }
115+
#endif /* MS_WINDOWS */
116+
}
117+
Py_XDECREF(cexe);

0 commit comments

Comments
 (0)