Issue #15133: _tkinter.tkapp.getboolean() now supports long and Tcl_Obj and

always returns bool.  tkinter.BooleanVar now validates input values (accepted
bool, int, long, str, unicode, and Tcl_Obj).  tkinter.BooleanVar.get() now
always returns bool.
This commit is contained in:
Serhiy Storchaka 2015-04-04 12:42:25 +03:00
parent baa6efdceb
commit f29bc70bff
6 changed files with 80 additions and 17 deletions

View File

@ -401,6 +401,10 @@ class BooleanVar(Variable):
"""
Variable.__init__(self, master, value, name)
def set(self, value):
"""Set the variable to VALUE."""
return self._tk.globalsetvar(self._name, self._tk.getboolean(value))
def get(self):
"""Return the value of the variable as a bool."""
return self._tk.getboolean(self._tk.globalgetvar(self._name))

View File

@ -1,6 +1,7 @@
import unittest
from Tkinter import Variable, StringVar, IntVar, DoubleVar, BooleanVar, Tcl, TclError
from Tkinter import (Variable, StringVar, IntVar, DoubleVar, BooleanVar, Tcl,
TclError)
class TestBase(unittest.TestCase):
@ -139,16 +140,57 @@ class TestBooleanVar(TestBase):
def test_default(self):
v = BooleanVar(self.root)
self.assertEqual(False, v.get())
self.assertIs(v.get(), False)
def test_get(self):
v = BooleanVar(self.root, True, "name")
self.assertAlmostEqual(True, v.get())
self.assertIs(v.get(), True)
self.root.globalsetvar("name", "0")
self.assertAlmostEqual(False, v.get())
self.assertIs(v.get(), False)
self.root.globalsetvar("name", 42 if self.root.wantobjects() else 1)
self.assertIs(v.get(), True)
self.root.globalsetvar("name", 0)
self.assertIs(v.get(), False)
self.root.globalsetvar("name", 42L if self.root.wantobjects() else 1L)
self.assertIs(v.get(), True)
self.root.globalsetvar("name", 0L)
self.assertIs(v.get(), False)
self.root.globalsetvar("name", "on")
self.assertIs(v.get(), True)
self.root.globalsetvar("name", u"0")
self.assertIs(v.get(), False)
self.root.globalsetvar("name", u"on")
self.assertIs(v.get(), True)
def test_set(self):
true = 1 if self.root.wantobjects() else "1"
false = 0 if self.root.wantobjects() else "0"
v = BooleanVar(self.root, name="name")
v.set(True)
self.assertEqual(self.root.globalgetvar("name"), true)
v.set("0")
self.assertEqual(self.root.globalgetvar("name"), false)
v.set(42)
self.assertEqual(self.root.globalgetvar("name"), true)
v.set(0)
self.assertEqual(self.root.globalgetvar("name"), false)
v.set(42L)
self.assertEqual(self.root.globalgetvar("name"), true)
v.set(0L)
self.assertEqual(self.root.globalgetvar("name"), false)
v.set("on")
self.assertEqual(self.root.globalgetvar("name"), true)
v.set(u"0")
self.assertEqual(self.root.globalgetvar("name"), false)
v.set(u"on")
self.assertEqual(self.root.globalgetvar("name"), true)
def test_invalid_value_domain(self):
false = 0 if self.root.wantobjects() else "0"
v = BooleanVar(self.root, name="name")
with self.assertRaises(TclError):
v.set("value")
self.assertEqual(self.root.globalgetvar("name"), false)
self.root.globalsetvar("name", "value")
with self.assertRaises(TclError):
v.get()

View File

@ -575,7 +575,7 @@ class Widget(Tkinter.Widget):
if ret and callback:
return callback(*args, **kw)
return bool(ret)
return ret
def state(self, statespec=None):
@ -683,7 +683,7 @@ class Entry(Widget, Tkinter.Entry):
"""Force revalidation, independent of the conditions specified
by the validate option. Returns False if validation fails, True
if it succeeds. Sets or clears the invalid state accordingly."""
return bool(self.tk.getboolean(self.tk.call(self._w, "validate")))
return self.tk.getboolean(self.tk.call(self._w, "validate"))
class Combobox(Entry):
@ -1233,7 +1233,7 @@ class Treeview(Widget, Tkinter.XView, Tkinter.YView):
def exists(self, item):
"""Returns True if the specified item is present in the tree,
False otherwise."""
return bool(self.tk.getboolean(self.tk.call(self._w, "exists", item)))
return self.tk.getboolean(self.tk.call(self._w, "exists", item))
def focus(self, item=None):

View File

@ -182,7 +182,12 @@ class TclTest(unittest.TestCase):
tcl = self.interp.tk
self.assertIs(tcl.getboolean('on'), True)
self.assertIs(tcl.getboolean('1'), True)
self.assertEqual(tcl.getboolean(42), 42)
self.assertIs(tcl.getboolean(u'on'), True)
self.assertIs(tcl.getboolean(u'1'), True)
self.assertIs(tcl.getboolean(42), True)
self.assertIs(tcl.getboolean(0), False)
self.assertIs(tcl.getboolean(42L), True)
self.assertIs(tcl.getboolean(0L), False)
self.assertRaises(TypeError, tcl.getboolean)
self.assertRaises(TypeError, tcl.getboolean, 'on', '1')
self.assertRaises(TypeError, tcl.getboolean, 1.0)

View File

@ -21,6 +21,11 @@ Core and Builtins
Library
-------
- Issue #15133: _tkinter.tkapp.getboolean() now supports long and Tcl_Obj and
always returns bool. tkinter.BooleanVar now validates input values (accepted
bool, int, long, str, unicode, and Tcl_Obj). tkinter.BooleanVar.get() now
always returns bool.
- Issue #23338: Fixed formatting ctypes error messages on Cygwin.
Patch by Makoto Kato.

View File

@ -2163,19 +2163,26 @@ Tkapp_GetDouble(PyObject *self, PyObject *args)
}
static PyObject *
Tkapp_GetBoolean(PyObject *self, PyObject *args)
Tkapp_GetBoolean(PyObject *self, PyObject *arg)
{
char *s;
int v;
if (PyTuple_Size(args) == 1) {
PyObject *o = PyTuple_GetItem(args, 0);
if (PyInt_Check(o)) {
Py_INCREF(o);
return o;
}
if (PyInt_Check(arg)) /* int or bool */
return PyBool_FromLong(PyInt_AS_LONG(arg));
if (PyLong_Check(arg))
return PyBool_FromLong(Py_SIZE(arg) != 0);
if (PyTclObject_Check(arg)) {
if (Tcl_GetBooleanFromObj(Tkapp_Interp(self),
((PyTclObject*)arg)->value,
&v) == TCL_ERROR)
return Tkinter_Error(self);
return PyBool_FromLong(v);
}
if (!PyArg_ParseTuple(args, "s:getboolean", &s))
if (!PyArg_Parse(arg, "s:getboolean", &s))
return NULL;
CHECK_STRING_LENGTH(s);
if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
@ -3236,7 +3243,7 @@ static PyMethodDef Tkapp_methods[] =
{"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
{"getint", Tkapp_GetInt, METH_VARARGS},
{"getdouble", Tkapp_GetDouble, METH_VARARGS},
{"getboolean", Tkapp_GetBoolean, METH_VARARGS},
{"getboolean", Tkapp_GetBoolean, METH_O},
{"exprstring", Tkapp_ExprString, METH_VARARGS},
{"exprlong", Tkapp_ExprLong, METH_VARARGS},
{"exprdouble", Tkapp_ExprDouble, METH_VARARGS},