diff --git a/Misc/NEWS.d/next/Library/2024-06-22-22-23-56.gh-issue-101830.1BAoxH.rst b/Misc/NEWS.d/next/Library/2024-06-22-22-23-56.gh-issue-101830.1BAoxH.rst new file mode 100644 index 00000000000000..46c18b040f30d7 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-06-22-22-23-56.gh-issue-101830.1BAoxH.rst @@ -0,0 +1,2 @@ +Accessing the :mod:`tkinter` object's string representation no longer converts +the underlying Tcl object to a string on Windows. diff --git a/Modules/_tkinter.c b/Modules/_tkinter.c index a34646aecb3ec8..8a5347be7de6ad 100644 --- a/Modules/_tkinter.c +++ b/Modules/_tkinter.c @@ -493,24 +493,28 @@ unicodeFromTclString(const char *s) } static PyObject * -unicodeFromTclObj(Tcl_Obj *value) +unicodeFromTclObj(TkappObject *tkapp, Tcl_Obj *value) { Tcl_Size len; #if USE_TCL_UNICODE - int byteorder = NATIVE_BYTEORDER; - const Tcl_UniChar *u = Tcl_GetUnicodeFromObj(value, &len); - if (sizeof(Tcl_UniChar) == 2) - return PyUnicode_DecodeUTF16((const char *)u, len * 2, - "surrogatepass", &byteorder); - else if (sizeof(Tcl_UniChar) == 4) - return PyUnicode_DecodeUTF32((const char *)u, len * 4, - "surrogatepass", &byteorder); - else - Py_UNREACHABLE(); -#else + if (value->typePtr != NULL && tkapp != NULL && + (value->typePtr == tkapp->StringType || + value->typePtr == tkapp->UTF32StringType)) + { + int byteorder = NATIVE_BYTEORDER; + const Tcl_UniChar *u = Tcl_GetUnicodeFromObj(value, &len); + if (sizeof(Tcl_UniChar) == 2) + return PyUnicode_DecodeUTF16((const char *)u, len * 2, + "surrogatepass", &byteorder); + else if (sizeof(Tcl_UniChar) == 4) + return PyUnicode_DecodeUTF32((const char *)u, len * 4, + "surrogatepass", &byteorder); + else + Py_UNREACHABLE(); + } +#endif const char *s = Tcl_GetStringFromObj(value, &len); return unicodeFromTclStringAndSize(s, len); -#endif } /*[clinic input] @@ -793,7 +797,7 @@ PyTclObject_string(PyObject *_self, void *ignored) { PyTclObject *self = (PyTclObject *)_self; if (!self->string) { - self->string = unicodeFromTclObj(self->value); + self->string = unicodeFromTclObj(NULL, self->value); if (!self->string) return NULL; } @@ -808,7 +812,7 @@ PyTclObject_str(PyObject *_self) return Py_NewRef(self->string); } /* XXX Could cache result if it is non-ASCII. */ - return unicodeFromTclObj(self->value); + return unicodeFromTclObj(NULL, self->value); } static PyObject * @@ -1143,7 +1147,7 @@ FromObj(TkappObject *tkapp, Tcl_Obj *value) Tcl_Interp *interp = Tkapp_Interp(tkapp); if (value->typePtr == NULL) { - return unicodeFromTclObj(value); + return unicodeFromTclObj(tkapp, value); } if (value->typePtr == tkapp->BooleanType || @@ -1208,7 +1212,7 @@ FromObj(TkappObject *tkapp, Tcl_Obj *value) if (value->typePtr == tkapp->StringType || value->typePtr == tkapp->UTF32StringType) { - return unicodeFromTclObj(value); + return unicodeFromTclObj(tkapp, value); } if (tkapp->BignumType == NULL && @@ -1308,7 +1312,7 @@ Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, Tcl_Size *pobjc) static PyObject * Tkapp_UnicodeResult(TkappObject *self) { - return unicodeFromTclObj(Tcl_GetObjResult(self->interp)); + return unicodeFromTclObj(self, Tcl_GetObjResult(self->interp)); } @@ -1327,7 +1331,7 @@ Tkapp_ObjectResult(TkappObject *self) res = FromObj(self, value); Tcl_DecrRefCount(value); } else { - res = unicodeFromTclObj(value); + res = unicodeFromTclObj(self, value); } return res; } @@ -1860,7 +1864,7 @@ GetVar(TkappObject *self, PyObject *args, int flags) res = FromObj(self, tres); } else { - res = unicodeFromTclObj(tres); + res = unicodeFromTclObj(self, tres); } } LEAVE_OVERLAP_TCL @@ -2307,7 +2311,7 @@ PythonCmd(ClientData clientData, Tcl_Interp *interp, for (i = 0; i < (objc - 1); i++) { PyObject *s = objargs ? FromObj(data->self, objv[i + 1]) - : unicodeFromTclObj(objv[i + 1]); + : unicodeFromTclObj(data->self, objv[i + 1]); if (!s) { Py_DECREF(args); return PythonCmd_Error(interp);