-
Notifications
You must be signed in to change notification settings - Fork 52
Wx Test Assistants #266
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Draft
corranwebster
wants to merge
7
commits into
main
Choose a base branch
from
feature/wx-test-assistant
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Wx Test Assistants #266
Changes from all commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
10482c0
Checkin of gui test assistant and some other fixes.
corranwebster d5af239
Add silence_output method.
corranwebster 261f4ba
add missing import
itziakos 9efe020
Merge branch 'master' into feature/wx-test-assistant
corranwebster 1f022b4
Fixes based on PR comments.
corranwebster 5807318
Merge branch 'master' into feature/wx-test-assistant
corranwebster 0194547
Fix imports in wx test helpers.
corranwebster File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
Empty file.
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 |
---|---|---|
@@ -0,0 +1,157 @@ | ||
|
||
# (C) Copyright 2014-15 Enthought, Inc., Austin, TX | ||
# All right reserved. | ||
# | ||
# This software is provided without warranty under the terms of the BSD | ||
# license included in enthought/LICENSE.txt and may be redistributed only | ||
# under the conditions described in the aforementioned license. The license | ||
# is also available online at http://www.enthought.com/licenses/BSD.txt | ||
# | ||
# Code modified from pyface.ui.qt4.util.event_loop_helper | ||
import contextlib | ||
import threading | ||
|
||
import wx | ||
from traits.api import HasStrictTraits, Instance | ||
from pyface.api import GUI | ||
from pyface.util.guisupport import start_event_loop_wx | ||
|
||
|
||
class ConditionTimeoutError(RuntimeError): | ||
pass | ||
|
||
|
||
@contextlib.contextmanager | ||
def dont_quit_when_last_window_closed(wx_app): | ||
""" | ||
Suppress exit of the application when the last window is closed. | ||
|
||
""" | ||
flag = wx_app.GetExitOnFrameDelete() | ||
wx_app.SetExitOnFrameDelete(False) | ||
try: | ||
yield | ||
finally: | ||
wx_app.SetExitOnFrameDelete(flag) | ||
|
||
|
||
class EventLoopHelper(HasStrictTraits): | ||
""" A helper class to provide basic event loop functionality. """ | ||
|
||
#: The gui toolkit application. | ||
gui_app = Instance(wx.App) | ||
|
||
#: The pyface gui implementation | ||
gui = Instance(GUI, ()) | ||
|
||
#: Reference to a dummy wx event handler that will help bind events for | ||
#: the timers. | ||
_handler = Instance(wx.EvtHandler, ()) | ||
|
||
@contextlib.contextmanager | ||
def event_loop(self, repeat=1): | ||
""" Emulates an event loop `repeat` times. | ||
|
||
Parameters | ||
---------- | ||
repeat : int | ||
Number of times to process events. Default is 1. | ||
|
||
""" | ||
yield | ||
for i in range(repeat): | ||
self.gui_app.ProcessPendingEvents() | ||
|
||
def event_loop_until_condition(self, condition, start=None, timeout=10.0): | ||
""" Runs the real event loop until the provided condition evaluates | ||
to True. | ||
|
||
Raises ConditionTimeoutError if the timeout occurs before the condition | ||
is satisfied. | ||
|
||
Parameters | ||
---------- | ||
condition : callable | ||
A callable to determine if the stop criteria have been met. This | ||
should accept no arguments. | ||
|
||
start : callable | ||
A callable to use in order to start the event loop. Default is | ||
to create a small frame or reuse the top level window if it is | ||
still available. | ||
|
||
timeout : float | ||
Number of seconds to run the event loop in the case that the trait | ||
change does not occur. | ||
|
||
""" | ||
def handler(event): | ||
if condition(): | ||
self.gui_app.Exit() | ||
|
||
# Make sure we don't get a premature exit from the event loop. | ||
with dont_quit_when_last_window_closed(self.gui_app): | ||
condition_timer = wx.Timer(self._handler) | ||
timeout_timer = wx.Timer(self._handler) | ||
self._handler.Bind(wx.EVT_TIMER, handler, condition_timer) | ||
self._handler.Bind( | ||
wx.EVT_TIMER, | ||
lambda event: self.gui_app.Exit(), | ||
timeout_timer | ||
) | ||
timeout_timer.Start(int(timeout * 1000), True) | ||
condition_timer.Start(50) | ||
try: | ||
if start is None: | ||
self._start_event_loop() | ||
else: | ||
start() | ||
if not condition(): | ||
raise ConditionTimeoutError( | ||
'Timed out waiting for condition') | ||
finally: | ||
timeout_timer.Stop() | ||
condition_timer.Stop() | ||
|
||
@contextlib.contextmanager | ||
def delete_window(self, window, timeout=2.0): | ||
""" Runs the real event loop until the window provided has been deleted. | ||
|
||
Parameters | ||
---------- | ||
window : | ||
The toolkit window widget whose deletion will stop the event loop. | ||
|
||
timeout : float | ||
Number of seconds to run the event loop in the case that the | ||
widget is not deleted. | ||
|
||
Raises | ||
------ | ||
ConditionTimeoutError: | ||
Raised on timeout. | ||
|
||
""" | ||
timer = wx.Timer(self._handler) | ||
self._handler.Bind( | ||
wx.EVT_TIMER, | ||
lambda event: self.gui_app.Exit(), | ||
timer | ||
) | ||
yield | ||
timer.Start(int(timeout * 1000), True) | ||
self._start_event_loop() | ||
if not timer.IsRunning(): | ||
# We exited the event loop on timeout | ||
raise ConditionTimeoutError( | ||
'Could not destroy widget before timeout: {!r}'.format(window)) | ||
|
||
def _start_event_loop(self): | ||
app = self.gui_app | ||
window = app.GetTopWindow() | ||
if window is None: | ||
# The wx EventLoop needs an active Window in order to work. | ||
window = wx.Frame(None, size=(1, 1)) | ||
app.SetTopWindow(window) | ||
window.Show(True) | ||
start_event_loop_wx(app) |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be in a try-finally block? If there is an exception from within the context, we would still want to process the fired events right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point, I think a try-finally might be a good thing to do