changeset: 95371:d0554559de53 branch: 2.7 parent: 95365:4f2391e86643 user: Serhiy Storchaka date: Thu Apr 02 10:35:57 2015 +0300 files: Lib/test/test_tcl.py Misc/NEWS Modules/_tkinter.c description: Issue #21526: Tkinter now supports new boolean type in Tcl 8.5. diff -r 4f2391e86643 -r d0554559de53 Lib/test/test_tcl.py --- a/Lib/test/test_tcl.py Thu Apr 02 00:04:06 2015 -0400 +++ b/Lib/test/test_tcl.py Thu Apr 02 10:35:57 2015 +0300 @@ -391,6 +391,21 @@ if tcl_version >= (8, 5): check('2**64', True) + def test_booleans(self): + tcl = self.interp + def check(expr, expected): + result = tcl.call('expr', expr) + self.assertEqual(result, expected) + self.assertIsInstance(result, int) + check('true', True) + check('yes', True) + check('on', True) + check('false', False) + check('no', False) + check('off', False) + check('1 < 2', True) + check('1 > 2', False) + def test_passing_values(self): def passValue(value): return self.interp.call('set', '_', value) diff -r 4f2391e86643 -r d0554559de53 Misc/NEWS --- a/Misc/NEWS Thu Apr 02 00:04:06 2015 -0400 +++ b/Misc/NEWS Thu Apr 02 10:35:57 2015 +0300 @@ -21,6 +21,8 @@ Library ------- +- Issue #21526: Tkinter now supports new boolean type in Tcl 8.5. + - Issue #23838: linecache now clears the cache and returns an empty result on MemoryError. diff -r 4f2391e86643 -r d0554559de53 Modules/_tkinter.c --- a/Modules/_tkinter.c Thu Apr 02 00:04:06 2015 -0400 +++ b/Modules/_tkinter.c Thu Apr 02 10:35:57 2015 +0300 @@ -257,13 +257,14 @@ int dispatching; /* We cannot include tclInt.h, as this is internal. So we cache interesting types here. */ - Tcl_ObjType *BooleanType; - Tcl_ObjType *ByteArrayType; - Tcl_ObjType *DoubleType; - Tcl_ObjType *IntType; - Tcl_ObjType *ListType; - Tcl_ObjType *ProcBodyType; - Tcl_ObjType *StringType; + const Tcl_ObjType *OldBooleanType; + const Tcl_ObjType *BooleanType; + const Tcl_ObjType *ByteArrayType; + const Tcl_ObjType *DoubleType; + const Tcl_ObjType *IntType; + const Tcl_ObjType *ListType; + const Tcl_ObjType *ProcBodyType; + const Tcl_ObjType *StringType; } TkappObject; #define Tkapp_Check(v) (Py_TYPE(v) == &Tkapp_Type) @@ -733,7 +734,8 @@ } #endif - v->BooleanType = Tcl_GetObjType("boolean"); + v->OldBooleanType = Tcl_GetObjType("boolean"); + v->BooleanType = Tcl_GetObjType("booleanString"); v->ByteArrayType = Tcl_GetObjType("bytearray"); v->DoubleType = Tcl_GetObjType("double"); v->IntType = Tcl_GetObjType("int"); @@ -1129,21 +1131,30 @@ } } +static PyObject * +fromBoolean(PyObject* tkapp, Tcl_Obj *value) +{ + int boolValue; + if (Tcl_GetBooleanFromObj(Tkapp_Interp(tkapp), value, &boolValue) == TCL_ERROR) + return Tkinter_Error(tkapp); + return PyBool_FromLong(boolValue); +} + static PyObject* FromObj(PyObject* tkapp, Tcl_Obj *value) { PyObject *result = NULL; TkappObject *app = (TkappObject*)tkapp; + Tcl_Interp *interp = Tkapp_Interp(tkapp); if (value->typePtr == NULL) { result = fromTclStringAndSize(value->bytes, value->length); return result; } - if (value->typePtr == app->BooleanType) { - result = value->internalRep.longValue ? Py_True : Py_False; - Py_INCREF(result); - return result; + if (value->typePtr == app->BooleanType || + value->typePtr == app->OldBooleanType) { + return fromBoolean(tkapp, value); } if (value->typePtr == app->ByteArrayType) { @@ -1166,15 +1177,14 @@ PyObject *elem; Tcl_Obj *tcl_elem; - status = Tcl_ListObjLength(Tkapp_Interp(tkapp), value, &size); + status = Tcl_ListObjLength(interp, value, &size); if (status == TCL_ERROR) return Tkinter_Error(tkapp); result = PyTuple_New(size); if (!result) return NULL; for (i = 0; i < size; i++) { - status = Tcl_ListObjIndex(Tkapp_Interp(tkapp), - value, i, &tcl_elem); + status = Tcl_ListObjIndex(interp, value, i, &tcl_elem); if (status == TCL_ERROR) { Py_DECREF(result); return Tkinter_Error(tkapp); @@ -1222,6 +1232,15 @@ #endif } +#if TK_VERSION_HEX >= 0x08050000 + if (app->BooleanType == NULL && + strcmp(value->typePtr->name, "booleanString") == 0) { + /* booleanString type is not registered in Tcl */ + app->BooleanType = value->typePtr; + return fromBoolean(tkapp, value); + } +#endif + return newPyTclObject(value); }