mirror of https://github.com/python/cpython
[3.13] gh-103194: Fix Tkinter’s Tcl value type handling for Tcl 8.7/9.0 (GH-103846) (GH-119830)
Some of standard Tcl types were renamed, removed, or no longer
registered in Tcl 8.7/9.0. This change fixes automatic conversion of Tcl
values to Python values to avoid returning a Tcl_Obj where the primary
Python types (int, bool, str, bytes) were returned in older Tcl.
(cherry picked from commit 94e9585e99
)
Co-authored-by: Christopher Chavez <chrischavez@gmx.us>
This commit is contained in:
parent
38bf39cb4b
commit
5539bd9df2
|
@ -0,0 +1,4 @@
|
|||
Prepare Tkinter for C API changes in Tcl 8.7/9.0 to avoid
|
||||
:class:`!_tkinter.Tcl_Obj` being unexpectedly returned
|
||||
instead of :class:`bool`, :class:`str`,
|
||||
:class:`bytearray`, or :class:`int`.
|
|
@ -318,6 +318,7 @@ typedef struct {
|
|||
const Tcl_ObjType *BignumType;
|
||||
const Tcl_ObjType *ListType;
|
||||
const Tcl_ObjType *StringType;
|
||||
const Tcl_ObjType *UTF32StringType;
|
||||
} TkappObject;
|
||||
|
||||
#define Tkapp_Interp(v) (((TkappObject *) (v))->interp)
|
||||
|
@ -588,14 +589,40 @@ Tkapp_New(const char *screenName, const char *className,
|
|||
}
|
||||
|
||||
v->OldBooleanType = Tcl_GetObjType("boolean");
|
||||
v->BooleanType = Tcl_GetObjType("booleanString");
|
||||
v->ByteArrayType = Tcl_GetObjType("bytearray");
|
||||
{
|
||||
Tcl_Obj *value;
|
||||
int boolValue;
|
||||
|
||||
/* Tcl 8.5 "booleanString" type is not registered
|
||||
and is renamed to "boolean" in Tcl 9.0.
|
||||
Based on approach suggested at
|
||||
https://core.tcl-lang.org/tcl/info/3bb3bcf2da5b */
|
||||
value = Tcl_NewStringObj("true", -1);
|
||||
Tcl_GetBooleanFromObj(NULL, value, &boolValue);
|
||||
v->BooleanType = value->typePtr;
|
||||
Tcl_DecrRefCount(value);
|
||||
|
||||
// "bytearray" type is not registered in Tcl 9.0
|
||||
value = Tcl_NewByteArrayObj(NULL, 0);
|
||||
v->ByteArrayType = value->typePtr;
|
||||
Tcl_DecrRefCount(value);
|
||||
}
|
||||
v->DoubleType = Tcl_GetObjType("double");
|
||||
/* TIP 484 suggests retrieving the "int" type without Tcl_GetObjType("int")
|
||||
since it is no longer registered in Tcl 9.0. But even though Tcl 8.7
|
||||
only uses the "wideInt" type on platforms with 32-bit long, it still has
|
||||
a registered "int" type, which FromObj() should recognize just in case. */
|
||||
v->IntType = Tcl_GetObjType("int");
|
||||
if (v->IntType == NULL) {
|
||||
Tcl_Obj *value = Tcl_NewIntObj(0);
|
||||
v->IntType = value->typePtr;
|
||||
Tcl_DecrRefCount(value);
|
||||
}
|
||||
v->WideIntType = Tcl_GetObjType("wideInt");
|
||||
v->BignumType = Tcl_GetObjType("bignum");
|
||||
v->ListType = Tcl_GetObjType("list");
|
||||
v->StringType = Tcl_GetObjType("string");
|
||||
v->UTF32StringType = Tcl_GetObjType("utf32string");
|
||||
|
||||
/* Delete the 'exit' command, which can screw things up */
|
||||
Tcl_DeleteCommand(v->interp, "exit");
|
||||
|
@ -1124,14 +1151,6 @@ FromObj(TkappObject *tkapp, Tcl_Obj *value)
|
|||
return PyFloat_FromDouble(value->internalRep.doubleValue);
|
||||
}
|
||||
|
||||
if (value->typePtr == tkapp->IntType) {
|
||||
long longValue;
|
||||
if (Tcl_GetLongFromObj(interp, value, &longValue) == TCL_OK)
|
||||
return PyLong_FromLong(longValue);
|
||||
/* If there is an error in the long conversion,
|
||||
fall through to wideInt handling. */
|
||||
}
|
||||
|
||||
if (value->typePtr == tkapp->IntType ||
|
||||
value->typePtr == tkapp->WideIntType) {
|
||||
result = fromWideIntObj(tkapp, value);
|
||||
|
@ -1176,17 +1195,12 @@ FromObj(TkappObject *tkapp, Tcl_Obj *value)
|
|||
return result;
|
||||
}
|
||||
|
||||
if (value->typePtr == tkapp->StringType) {
|
||||
if (value->typePtr == tkapp->StringType ||
|
||||
value->typePtr == tkapp->UTF32StringType)
|
||||
{
|
||||
return unicodeFromTclObj(value);
|
||||
}
|
||||
|
||||
if (tkapp->BooleanType == NULL &&
|
||||
strcmp(value->typePtr->name, "booleanString") == 0) {
|
||||
/* booleanString type is not registered in Tcl */
|
||||
tkapp->BooleanType = value->typePtr;
|
||||
return fromBoolean(tkapp, value);
|
||||
}
|
||||
|
||||
if (tkapp->BignumType == NULL &&
|
||||
strcmp(value->typePtr->name, "bignum") == 0) {
|
||||
/* bignum type is not registered in Tcl */
|
||||
|
|
Loading…
Reference in New Issue