Skip to content

Commit 2b9f263

Browse files
committed
Trigger events via standard callbacks in widget testing.
Sending actual events through the whole event processing pipeline is a more complete test, reveals a few minor issues (see changes below), and avoids being linked to the rather nonstandard widget method names ("press" or "_click"?). The coordinates in the "move first vertex after completing the polygon" subtest of test_polygon_selector(draw_bounding_box=True) were altered because the original coordinates would actually not work in a real case, as the mouse-drag would actually also trigger the polygon-rescaling behavior. The coordinates in test_rectangle_{drag,resize} were altered because for the original coordinates, the click_and_drag would actually be ignore()d due to starting (just) outside of the axes.
1 parent bff64cc commit 2b9f263

File tree

5 files changed

+235
-231
lines changed

5 files changed

+235
-231
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
``testing.widgets.mock_event`` and ``testing.widgets.do_event``
2+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3+
... are deprecated. Directly construct Event objects (typically `.MouseEvent`
4+
or `.KeyEvent`) and pass them to ``canvas.callbacks.process()`` instead.

lib/matplotlib/backend_bases.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1411,6 +1411,23 @@ def __init__(self, name, canvas, x, y, button=None, key=None,
14111411
self.step = step
14121412
self.dblclick = dblclick
14131413

1414+
@classmethod
1415+
def _from_ax_coords(cls, name, ax, xy, *args, **kwargs):
1416+
"""
1417+
Generate a synthetic event at a given axes coordinate.
1418+
1419+
This method is intended for creating events during testing. The event
1420+
can be emitted by calling its ``_process()`` method.
1421+
1422+
args and kwargs are mapped to `.MouseEvent.__init__` parameters,
1423+
starting with `button`.
1424+
"""
1425+
x, y = ax.transData.transform(xy)
1426+
event = cls(name, ax.figure.canvas, x, y, *args, **kwargs)
1427+
event.inaxes = ax
1428+
event.xdata, event.ydata = xy # Force exact xy to avoid fp roundtrip issues.
1429+
return event
1430+
14141431
def __str__(self):
14151432
return (f"{self.name}: "
14161433
f"xy=({self.x}, {self.y}) xydata=({self.xdata}, {self.ydata}) "
@@ -1503,6 +1520,22 @@ def __init__(self, name, canvas, key, x=0, y=0, guiEvent=None):
15031520
super().__init__(name, canvas, x, y, guiEvent=guiEvent)
15041521
self.key = key
15051522

1523+
@classmethod
1524+
def _from_ax_coords(cls, name, ax, xy, key, *args, **kwargs):
1525+
"""
1526+
Generate a synthetic event at a given axes coordinate.
1527+
1528+
This method is intended for creating events during testing. The event
1529+
can be emitted by calling its ``_process()`` method.
1530+
"""
1531+
# Separate from MouseEvent._from_ax_coords instead of being defined in the base
1532+
# class, due to different parameter order in the constructor signature.
1533+
x, y = ax.transData.transform(xy)
1534+
event = cls(name, ax.figure.canvas, key, x, y, *args, **kwargs)
1535+
event.inaxes = ax
1536+
event.xdata, event.ydata = xy # Force exact xy to avoid fp roundtrip issues.
1537+
return event
1538+
15061539

15071540
# Default callback for key events.
15081541
def _key_handler(event):

lib/matplotlib/testing/widgets.py

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88

99
from unittest import mock
1010

11+
from matplotlib import _api
12+
from matplotlib.backend_bases import MouseEvent, KeyEvent
1113
import matplotlib.pyplot as plt
1214

1315

@@ -24,6 +26,7 @@ def noop(*args, **kwargs):
2426
pass
2527

2628

29+
@_api.deprecated("3.11", alternative="MouseEvent or KeyEvent")
2730
def mock_event(ax, button=1, xdata=0, ydata=0, key=None, step=1):
2831
r"""
2932
Create a mock event that can stand in for `.Event` and its subclasses.
@@ -65,6 +68,7 @@ def mock_event(ax, button=1, xdata=0, ydata=0, key=None, step=1):
6568
return event
6669

6770

71+
@_api.deprecated("3.11", alternative="callbacks.process(event)")
6872
def do_event(tool, etype, button=1, xdata=0, ydata=0, key=None, step=1):
6973
"""
7074
Trigger an event on the given tool.
@@ -105,15 +109,12 @@ def click_and_drag(tool, start, end, key=None):
105109
An optional key that is pressed during the whole operation
106110
(see also `.KeyEvent`).
107111
"""
108-
if key is not None:
109-
# Press key
110-
do_event(tool, 'on_key_press', xdata=start[0], ydata=start[1],
111-
button=1, key=key)
112+
ax = tool.ax
113+
if key is not None: # Press key
114+
KeyEvent._from_ax_coords("key_press_event", ax, start, key)._process()
112115
# Click, move, and release mouse
113-
do_event(tool, 'press', xdata=start[0], ydata=start[1], button=1)
114-
do_event(tool, 'onmove', xdata=end[0], ydata=end[1], button=1)
115-
do_event(tool, 'release', xdata=end[0], ydata=end[1], button=1)
116-
if key is not None:
117-
# Release key
118-
do_event(tool, 'on_key_release', xdata=end[0], ydata=end[1],
119-
button=1, key=key)
116+
MouseEvent._from_ax_coords("button_press_event", ax, start, 1)._process()
117+
MouseEvent._from_ax_coords("motion_notify_event", ax, end, 1)._process()
118+
MouseEvent._from_ax_coords("button_release_event", ax, end, 1)._process()
119+
if key is not None: # Release key
120+
KeyEvent._from_ax_coords("key_release_event", ax, end, key)._process()

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy