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

returns bool.  tkinter.BooleanVar now validates input values (accepted bool,
int, str, and Tcl_Obj).  tkinter.BooleanVar.get() now always returns bool.
This commit is contained in:
Serhiy Storchaka 2015-04-04 12:43:01 +03:00
parent c9ba38c21c
commit 9a6e201f7d
6 changed files with 58 additions and 17 deletions

View File

@ -181,7 +181,8 @@ 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(42), True)
self.assertIs(tcl.getboolean(0), False)
self.assertRaises(TypeError, tcl.getboolean)
self.assertRaises(TypeError, tcl.getboolean, 'on', '1')
self.assertRaises(TypeError, tcl.getboolean, b'on')

View File

@ -391,6 +391,11 @@ 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))
initialize = set
def get(self):
"""Return the value of the variable as a bool."""
try:

View File

@ -1,6 +1,7 @@
import unittest
from tkinter import Variable, StringVar, IntVar, DoubleVar, BooleanVar, Tcl
from tkinter import (Variable, StringVar, IntVar, DoubleVar, BooleanVar, Tcl,
TclError)
class Var(Variable):
@ -159,16 +160,41 @@ 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", "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("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(ValueError):
v.get()

View File

@ -573,7 +573,7 @@ class Widget(tkinter.Widget):
if ret and callback:
return callback(*args, **kw)
return bool(ret)
return ret
def state(self, statespec=None):
@ -681,7 +681,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):
@ -1231,7 +1231,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

@ -24,6 +24,10 @@ Core and Builtins
Library
-------
- Issue #15133: _tkinter.tkapp.getboolean() now supports Tcl_Obj and always
returns bool. tkinter.BooleanVar now validates input values (accepted bool,
int, str, 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

@ -1929,19 +1929,24 @@ 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 (PyLong_Check(o)) {
Py_INCREF(o);
return o;
if (PyLong_Check(arg)) { /* int or bool */
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)
@ -2854,7 +2859,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},