From 3ab440ac98c62802d9714ad16e79f93d31ca6161 Mon Sep 17 00:00:00 2001 From: Matthias Kievernagel Date: Sun, 13 May 2018 21:46:17 +0200 Subject: [PATCH 1/3] bpo-3405: Add support for user data of Tk virtual events in tkinter (%d substitution). --- Lib/tkinter/__init__.py | 15 ++++++++++++--- .../2018-05-11-12-26-16.bpo-3405.CacMw9.rst | 1 + 2 files changed, 13 insertions(+), 3 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2018-05-11-12-26-16.bpo-3405.CacMw9.rst diff --git a/Lib/tkinter/__init__.py b/Lib/tkinter/__init__.py index bf0b3b92155938..177d9195bc4822 100644 --- a/Lib/tkinter/__init__.py +++ b/Lib/tkinter/__init__.py @@ -251,6 +251,10 @@ class Event: type - type of the event as a number widget - widget in which the event occurred delta - delta of wheel movement (MouseWheel) + detail - certain fixed strings (see tcl/tk documentation) + (Enter, Leave, FocusIn, FocusOut, ConfigureRequest) + user_data - data string which was passed to event_generate or empty string + (VirtualEvent) """ def __repr__(self): @@ -1595,7 +1599,7 @@ def _root(self): w = self while w.master is not None: w = w.master return w - _subst_format = ('%#', '%b', '%f', '%h', '%k', + _subst_format = ('%#', '%b', '%d', '%f', '%h', '%k', '%s', '%t', '%w', '%x', '%y', '%A', '%E', '%K', '%N', '%W', '%T', '%X', '%Y', '%D') _subst_format_str = " ".join(_subst_format) @@ -1613,11 +1617,14 @@ def getint_event(s): except (ValueError, TclError): return s - nsign, b, f, h, k, s, t, w, x, y, A, E, K, N, W, T, X, Y, D = args - # Missing: (a, c, d, m, o, v, B, R) + nsign, b, d, f, h, k, s, t, w, x, y, A, E, K, N, W, T, X, Y, D = args + # Missing: (a, c, m, o, v, B, R) e = Event() # serial field: valid for all events # number of button: ButtonPress and ButtonRelease events only + # detail: for Enter, Leave, FocusIn, FocusOut and ConfigureRequest + # events certain fixed strings (see tcl/tk documentation) + # user_data: data string from a virtual event or an empty string # height field: Configure, ConfigureRequest, Create, # ResizeRequest, and Expose events only # keycode field: KeyPress and KeyRelease events only @@ -1631,6 +1638,8 @@ def getint_event(s): # KeyRelease, and Motion events e.serial = getint(nsign) e.num = getint_event(b) + e.user_data = d + e.detail = d try: e.focus = getboolean(f) except TclError: pass e.height = getint_event(h) diff --git a/Misc/NEWS.d/next/Library/2018-05-11-12-26-16.bpo-3405.CacMw9.rst b/Misc/NEWS.d/next/Library/2018-05-11-12-26-16.bpo-3405.CacMw9.rst new file mode 100644 index 00000000000000..8caa5bccddb3c3 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-05-11-12-26-16.bpo-3405.CacMw9.rst @@ -0,0 +1 @@ +Add support for user data of Tk virtual events to :mod:`tkinter`. From bebae490264ce9f628b83cc7ae1c1abb2db4cc26 Mon Sep 17 00:00:00 2001 From: Matthias Kievernagel Date: Sun, 20 May 2018 18:17:39 +0200 Subject: [PATCH 2/3] Tests added to test_tk for virtual events --- Lib/tkinter/test/test_tkinter/test_event.py | 47 +++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 Lib/tkinter/test/test_tkinter/test_event.py diff --git a/Lib/tkinter/test/test_tkinter/test_event.py b/Lib/tkinter/test/test_tkinter/test_event.py new file mode 100644 index 00000000000000..f09693af32f505 --- /dev/null +++ b/Lib/tkinter/test/test_tkinter/test_event.py @@ -0,0 +1,47 @@ +import unittest +import tkinter +import _tkinter +from test.support import requires, run_unittest +from tkinter.test.support import AbstractTkTest + +requires('gui') + +class EventTest(AbstractTkTest, unittest.TestCase): + + called = False + test_data = None + + # pump_events function 'borrowed' from ivan_pozdeev on stackoverflow + def pump_events(self): + while self.root.dooneevent(_tkinter.ALL_EVENTS | _tkinter.DONT_WAIT): + pass + + def test_virtual_event(self): + def receive(e): + EventTest.called = True + self.assertIsInstance(e, tkinter.Event) + self.assertEqual(e.type, tkinter.EventType.VirtualEvent) + self.assertIsInstance(e.user_data, str) + if EventTest.test_data is not None: + self.assertEqual(e.user_data, EventTest.test_data) + self.pump_events() + EventTest.called = False + b = self.root.bind('<>', lambda e:receive(e)) + self.root.event_generate('<>') + self.pump_events() + self.assertTrue(EventTest.called) + EventTest.called = False + EventTest.test_data = 'test' + self.root.event_generate('<>', data='test') + self.pump_events() + self.assertTrue(EventTest.called) + self.root.unbind('<>', b) + EventTest.called = False + self.root.event_generate('<>') + self.pump_events() + self.assertFalse(EventTest.called) + +tests_gui = (EventTest, ) + +if __name__ == "__main__": + run_unittest(*tests_gui) From 36067fe3e4e5af65498d0e8fc062913028904cd7 Mon Sep 17 00:00:00 2001 From: Matthias Kievernagel Date: Sun, 27 May 2018 16:51:47 +0200 Subject: [PATCH 3/3] Also test for empty user_data --- Lib/tkinter/test/test_tkinter/test_event.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Lib/tkinter/test/test_tkinter/test_event.py b/Lib/tkinter/test/test_tkinter/test_event.py index f09693af32f505..d21c32ba709fd8 100644 --- a/Lib/tkinter/test/test_tkinter/test_event.py +++ b/Lib/tkinter/test/test_tkinter/test_event.py @@ -24,6 +24,8 @@ def receive(e): self.assertIsInstance(e.user_data, str) if EventTest.test_data is not None: self.assertEqual(e.user_data, EventTest.test_data) + else: + self.assertEqual(e.user_data, '') self.pump_events() EventTest.called = False b = self.root.bind('<>', lambda e:receive(e))