FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

bpo-41176: revise Tkinter mainloop dispatching flag behavior by richardsheridan · Pull Request #21299 · python/cpython · GitHub

Repository navigation

Closed
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
90a6343
bpo-41176: Expose tkinter dispatching state
richardsheridan Jul 3, 2020
f426278
bpo-41176: Deprecate implicit mainloop waiting behavior
richardsheridan Jul 3, 2020
3350dbc
bpo-41176: additional docstring corrections
richardsheridan Jul 3, 2020
9db47cf
bpo-41176: Correct tkinter test usage of `update`
richardsheridan Jul 3, 2020
2817b2a
bpo-41176: Rename according to comment and use Clinic
richardsheridan Jul 4, 2020
8e4371f
bpo-41176: Address PR comments, add willdispatch test
richardsheridan Jul 5, 2020
3732864
bpo-41176: deduplicate warning code
richardsheridan Jul 5, 2020
6df6433
bpo-41176: rectify typo
richardsheridan Jul 5, 2020
0f609d7
bpo-41176: ACKS
richardsheridan Jul 5, 2020
ad89a27
bpo-41176: fix future behavior
richardsheridan Jul 5, 2020
49ab712
bpo-41176: inline thread flag checks
richardsheridan Jul 5, 2020
ba079da
bpo-41176: internal flag should flip, not just be true
richardsheridan Jul 5, 2020
7c5d9fb
bpo-41176: improve dispatching docstring
richardsheridan Jul 5, 2020
2f22316
bpo-41176: Update whatsnew
richardsheridan Jul 5, 2020
5e9965c
bpo-41176: whitespace
richardsheridan Jul 5, 2020
5872f5b
📜🤖 Added by blurb_it.
blurb-it[bot] Jul 5, 2020
d130740
bpo-41176: data to method
richardsheridan Jul 5, 2020
648434f
bpo-41176: fix future behavior
richardsheridan Jul 6, 2020
44fe5fa
bpo-41176: Make dispatching return an int
richardsheridan Jul 6, 2020
fbddd0f
bpo-41176: attempt to expose CI error
richardsheridan Jul 6, 2020
b58f8a1
bpo-41176: revert internal memory of previous dispatching
richardsheridan Jul 6, 2020
ad7d6ec
bpo-41176: Attempt Ubuntu CI fix
richardsheridan Jul 7, 2020
a5bb180
bpo-41176: Attempt Ubuntu CI fix
richardsheridan Jul 7, 2020
2d557c5
bpo-41176: Quit, mainloop, dispatch docstrings
richardsheridan Jul 8, 2020
ff39387
bpo-41176: WIP Docs in tkinter.rst
richardsheridan Jul 9, 2020
8ea6c5f
bpo-41176: satisfy Doc make check
richardsheridan Jul 9, 2020
e7a0611
bpo-41176: use local max attempts variable
richardsheridan Jul 11, 2020
3165806
bpo-41176: dispatching returns PyBool
richardsheridan Jul 11, 2020
3912603
bpo-41176: update docstrings
richardsheridan Jul 11, 2020
4d81d59
bpo-41176: remove old deprecation warning
richardsheridan Jul 11, 2020
1f16b80
bpo-41176: update test with new deprecation and new future behavior
richardsheridan Jul 11, 2020
4ec839a
bpo-41176: update Docs
richardsheridan Jul 11, 2020
a5e4a86
bpo-41176: Comment new post-deprecation plan
richardsheridan Jul 11, 2020
8efe3fe
bpo-41176: New behavior plan: Doc and Warn fixes
richardsheridan Jul 11, 2020
bf2776c
bpo-41176: Resolve review issues
richardsheridan Jul 12, 2020
1be91e0
bpo-41176: Title underlines should be same length as title
richardsheridan Jul 12, 2020
ad6e882
bpo-41176: reset dispatching flag in test
richardsheridan Jul 12, 2020
6143a18
bpo-41176: layout Tk methods
richardsheridan Jul 12, 2020
516a385
bpo-41176: clarify dispatching() limitations
richardsheridan Jul 12, 2020
File filter

Filter by extension

Filter by extension .c  (1) .h  (1) .py  (5) All 3 file types selected
Viewed files
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Unified
Split
Hide whitespace
Diff view
Unified
Split
Hide whitespace
21 changes: 15 additions & 6 deletions Lib/tkinter/__init__.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -591,10 +591,15 @@ def get(self):


def mainloop(n=0):
"""Run the main loop of Tcl."""
"""Run the main loop of tkinter."""
_default_root.tk.mainloop(n)


def dispatching():
"""Determine if the tkinter main loop is running"""
return _default_root.tk.dispatching()


getint = int

getdouble = float
Expand Down Expand Up @@ -1303,13 +1308,13 @@ def winfo_y(self):
self.tk.call('winfo', 'y', self._w))

def update(self):
"""Enter event loop until all pending events have been processed by Tcl."""
"""Process all events, including idle tasks, in the Tcl queue."""
self.tk.call('update')

def update_idletasks(self):
"""Enter event loop until all idle callbacks have been called. This
will update the display of windows but not process events caused by
the user."""
"""Process all idle callbacks in the Tcl queue.
This will update the display of windows but not process events
caused by the user."""
self.tk.call('update', 'idletasks')

def bindtags(self, tagList=None):
Expand Down Expand Up @@ -1418,9 +1423,13 @@ def unbind_class(self, className, sequence):
self.tk.call('bind', className , sequence, '')

def mainloop(self, n=0):
"""Call the mainloop of Tk."""
"""Call the main loop of tkinter."""
self.tk.mainloop(n)

def dispatching(self):
"""Determine if the tkinter main loop is running."""
return self.tk.dispatching()

def quit(self):
"""Quit the Tcl interpreter. All widgets will be destroyed."""
self.tk.quit()
Expand Down
4 changes: 2 additions & 2 deletions Lib/tkinter/test/support.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ def setUpClass(cls):

@classmethod
def tearDownClass(cls):
cls.root.update_idletasks()
cls.root.update()
cls.root.destroy()
del cls.root
tkinter._default_root = None
Expand All @@ -38,7 +38,7 @@ def tearDown(self):

def destroy_default_root():
if getattr(tkinter, '_default_root', None):
tkinter._default_root.update_idletasks()
tkinter._default_root.update()
tkinter._default_root.destroy()
tkinter._default_root = None

Expand Down
49 changes: 47 additions & 2 deletions Lib/tkinter/test/test_tkinter/test_misc.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -109,15 +109,15 @@ def callback(start=0, step=1):
idle1 = root.after_idle(callback)
self.assertIn(idle1, root.tk.call('after', 'info'))
(script, _) = root.tk.splitlist(root.tk.call('after', 'info', idle1))
root.update_idletasks() # Process all pending events.
root.update() # Process all pending events.
self.assertEqual(count, 1)
with self.assertRaises(tkinter.TclError):
root.tk.call(script)

# Set up with callback with args.
count = 0
idle1 = root.after_idle(callback, 42, 11)
root.update_idletasks() # Process all pending events.
root.update() # Process all pending events.
self.assertEqual(count, 53)

# Cancel before called.
Expand Down Expand Up @@ -192,6 +192,51 @@ def test_clipboard_astral(self):
with self.assertRaises(tkinter.TclError):
root.clipboard_get()

def test_mainloop_dispatching(self):
# reconstruct default root destroyed by AbstractTkTest
root = tkinter._default_root = self.root
for thing in (root.tk, root, tkinter):
#mainloop, dispatching, willdispatch
self.assertFalse(thing.dispatching())
root.after(0, lambda:self.assertTrue(thing.dispatching()))
root.after(0, root.quit)
Comment thread
richardsheridan marked this conversation as resolved.
root.mainloop()
self.assertFalse(thing.dispatching())

def test_thread_must_wait_for_mainloop(self):
import threading, time
Comment thread
richardsheridan marked this conversation as resolved.
Outdated
def target():
self.assertFalse(root.dispatching())
Comment thread
richardsheridan marked this conversation as resolved.
Outdated
with self.assertRaises(RuntimeError):
root.after(0) # Null op

ready_for_mainloop.set()

# self.assertTrue(root.dispatching()) but patient
t = time.monotonic()
while not root.dispatching():
time.sleep(.001)
Comment thread
richardsheridan marked this conversation as resolved.
Outdated
self.assertTrue(time.monotonic() < (t + 10))

root.quit()

root = self.root

# remove on eventual WaitForMainloop behavior change
root.tk.setmainloopwaitattempts(0)

ready_for_mainloop = threading.Event()
thread = threading.Thread(target=target)
self.assertFalse(root.dispatching())
Comment thread
richardsheridan marked this conversation as resolved.
Outdated
thread.start()
ready_for_mainloop.wait()
root.mainloop()
self.assertFalse(root.dispatching())
thread.join()

with self.assertWarns(DeprecationWarning):
root.tk.setmainloopwaitattempts(10)


tests_gui = (MiscTest, )

Expand Down
4 changes: 2 additions & 2 deletions Lib/tkinter/test/test_ttk/test_extensions.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
class LabeledScaleTest(AbstractTkTest, unittest.TestCase):

def tearDown(self):
self.root.update_idletasks()
self.root.update()
super().tearDown()

def test_widget_destroy(self):
Expand Down Expand Up @@ -219,7 +219,7 @@ def test_widget_destroy(self):
var = tkinter.StringVar(self.root)
optmenu = ttk.OptionMenu(self.root, var)
name = var._name
optmenu.update_idletasks()
optmenu.update()
optmenu.destroy()
self.assertEqual(optmenu.tk.globalgetvar(name), var.get())
del var
Expand Down
12 changes: 6 additions & 6 deletions Lib/tkinter/test/test_ttk/test_widgets.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ def setUp(self):


def test_identify(self):
self.widget.update_idletasks()
self.widget.update()
self.assertEqual(self.widget.identify(
int(self.widget.winfo_width() / 2),
int(self.widget.winfo_height() / 2)
Expand Down Expand Up @@ -327,7 +327,7 @@ def test_bbox(self):
def test_identify(self):
self.entry.pack()
self.entry.wait_visibility()
self.entry.update_idletasks()
self.entry.update()

# bpo-27313: macOS Cocoa widget differs from X, allow either
if sys.platform == 'darwin':
Expand Down Expand Up @@ -439,7 +439,7 @@ def _show_drop_down_listbox(self):
width = self.combo.winfo_width()
self.combo.event_generate('<ButtonPress-1>', x=width - 5, y=5)
self.combo.event_generate('<ButtonRelease-1>', x=width - 5, y=5)
self.combo.update_idletasks()
self.combo.update()


def test_virtual_event(self):
Expand Down Expand Up @@ -1134,7 +1134,7 @@ def _click_increment_arrow(self):
y = height//2 - 5
self.spin.event_generate('<ButtonPress-1>', x=x, y=y)
self.spin.event_generate('<ButtonRelease-1>', x=x, y=y)
self.spin.update_idletasks()
self.spin.update()

def _click_decrement_arrow(self):
width = self.spin.winfo_width()
Expand All @@ -1143,7 +1143,7 @@ def _click_decrement_arrow(self):
y = height//2 + 4
self.spin.event_generate('<ButtonPress-1>', x=x, y=y)
self.spin.event_generate('<ButtonRelease-1>', x=x, y=y)
self.spin.update_idletasks()
self.spin.update()

def test_command(self):
success = []
Expand All @@ -1159,7 +1159,7 @@ def test_command(self):

# testing postcommand removal
self.spin['command'] = ''
self.spin.update_idletasks()
self.spin.update()
self._click_increment_arrow()
self._click_decrement_arrow()
self.spin.update()
Expand Down
101 changes: 92 additions & 9 deletions Modules/_tkinter.c
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -360,21 +360,36 @@ Sleep(int milli)
}
#endif /* MS_WINDOWS */

/* Wait up to 1s for the mainloop to come up. */
/* Wait for the mainloop to come up. */
static int mainloopwaitattempts = 10; // 1 second

static int
WaitForMainloop(TkappObject* self)
{
int i;
for (i = 0; i < 10; i++) {
if (self->dispatching)
return 1;
if (self->dispatching)
{
return 1;
}
for (i = 0; i < mainloopwaitattempts; i++) {
Py_BEGIN_ALLOW_THREADS
Sleep(100);
Py_END_ALLOW_THREADS
if (self->dispatching)
{
if (PyErr_WarnEx(PyExc_DeprecationWarning,
"It seems you are implicitly waiting for "
"the mainloop to come up.\n"
"This behavior is deprecated; consider polling "
"dispatching() instead.\n", 1))
Comment thread
richardsheridan marked this conversation as resolved.
Outdated
{
/* return something nonzero, an error will be
raised elsewhere soon */
return -1;
}
return 1;
}
}
if (self->dispatching)
return 1;
PyErr_SetString(PyExc_RuntimeError, "main thread is not in main loop");
return 0;
}
Expand Down Expand Up @@ -1500,7 +1515,10 @@ Tkapp_Call(PyObject *selfptr, PyObject *args)
marshal the parameters to the interpreter thread. */
Tkapp_CallEvent *ev;
Tcl_Condition cond = NULL;
PyObject *exc_type, *exc_value, *exc_tb;
PyObject *exc_type, *exc_value, *exc_tb;
/* After WaitForMainloop deprecation:
if (!self->dispatching)
return NULL; */
if (!WaitForMainloop(self))
return NULL;
ev = (Tkapp_CallEvent*)attemptckalloc(sizeof(Tkapp_CallEvent));
Expand Down Expand Up @@ -1777,6 +1795,10 @@ var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags)
/* The current thread is not the interpreter thread. Marshal
the call to the interpreter thread, then wait for
completion. */

/* After WaitForMainloop deprecation:
if (!self->dispatching)
return NULL; */
if (!WaitForMainloop(self))
return NULL;

Expand Down Expand Up @@ -2477,6 +2499,10 @@ _tkinter_tkapp_createcommand_impl(TkappObject *self, const char *name,
return NULL;
}

/*After WaitForMainloop deprecation:
if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
!self->dispatching)
return NULL; */
if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
!WaitForMainloop(self))
return NULL;
Expand Down Expand Up @@ -3024,15 +3050,70 @@ _tkinter.tkapp.willdispatch

[clinic start generated code]*/

static PyObject *
_tkinter_tkapp_willdispatch_impl(TkappObject *self)
static PyObject*
_tkinter_tkapp_willdispatch_impl(TkappObject* self)
/*[clinic end generated code: output=0e3f46d244642155 input=d88f5970843d6dab]*/
{
if (PyErr_WarnEx(PyExc_DeprecationWarning,
"willdispatch() is deprecated; consider polling dispatch() instead.", 1))
{
return NULL;
}
self->dispatching = 1;

Py_RETURN_NONE;
}

/*[clinic input]
_tkinter.tkapp.dispatching

[clinic start generated code]*/

static PyObject*
_tkinter_tkapp_dispatching_impl(TkappObject* self)
/*[clinic end generated code: output=0e3f46d244642155 input=d88f5970843d6dab]*/
{
return PyLong_FromLong(self->dispatching);
Comment thread
richardsheridan marked this conversation as resolved.
Outdated
}

/*[clinic input]
_tkinter.setmainloopwaitattempts

new_val: int
/

Set number of 100 millisecond mainloop wait attempts that call(), var_invoke(),
and createcommand() will use.

Current default is 10 for a 1 second wait, but future behavior will be equivalent 0.

Setting anything other than 0 will trigger a DeprecationWarning.

[clinic start generated code]*/

static PyObject*
_tkinter_tkapp_setmainloopwaitattempts_impl(PyObject* self, int new_val)
/*[clinic end generated code: output=42bf7757dc2d0ab6 input=deca1d6f9e6dae47]*/
{
if (new_val < 0)
{
PyErr_SetString(PyExc_ValueError,
"mainloopwaitattempts must be >= 0");
return NULL;
}
if (new_val)
{
if (PyErr_WarnEx(PyExc_DeprecationWarning,
"It seems you want to wait for the mainloop to come up.\n"
"This behavior is deprecated; consider polling dispatch() instead.", 1))
{
return NULL;
}
}
mainloopwaitattempts = new_val;
Py_RETURN_NONE;
}


/**** Tkapp Type Methods ****/

Expand Down Expand Up @@ -3252,6 +3333,8 @@ static PyType_Spec Tktt_Type_spec = {
static PyMethodDef Tkapp_methods[] =
{
_TKINTER_TKAPP_WILLDISPATCH_METHODDEF
_TKINTER_TKAPP_DISPATCHING_METHODDEF
_TKINTER_TKAPP_SETMAINLOOPWAITATTEMPTS_METHODDEF
{"wantobjects", Tkapp_WantObjects, METH_VARARGS},
{"call", Tkapp_Call, METH_VARARGS},
_TKINTER_TKAPP_EVAL_METHODDEF
Expand Down
Loading

Back | FazBrowse Home | New Git URL