Skip to content

Commit

Permalink
pythongh-103194: Fix Tkinter’s Tcl value type handling for Tcl 8.7/9.0 (
Browse files Browse the repository at this point in the history
pythonGH-103846)

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 94e9585)

Co-authored-by: Christopher Chavez <chrischavez@gmx.us>
  • Loading branch information
chrstphrchvz authored and miss-islington committed May 31, 2024
1 parent 978b86a commit dc8da3e
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 18 deletions.
Original file line number Diff line number Diff line change
@@ -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`.
50 changes: 32 additions & 18 deletions Modules/_tkinter.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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");
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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 */
Expand Down

0 comments on commit dc8da3e

Please sign in to comment.