-
Notifications
You must be signed in to change notification settings - Fork 2
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
Add wx toolkit support #246
Conversation
Here's what Pyface is doing for wx on Linux: https://github.com/enthought/pyface/blob/0d1516e60051e52251627123891dff9085737f4c/etstool.py#L215-L219 Looks the same as what we have here, except for the version restriction (< 4.1). I'll try that. |
The faulthandler output is interesting: it shows clearly that the |
The pi example fails because of a wxPython 4 compatibility issue in enable (fixed by enthought/enable#403). Traceback (most recent call last):
File "examples/pi_iterations.py", line 20, in <module>
from chaco.api import ArrayPlotData, Plot
File "/Users/mdickinson/.edm/envs/traits-futures-py36-wxpython/lib/python3.6/site-packages/chaco/api.py", line 38, in <module>
from .abstract_plot_renderer import AbstractPlotRenderer
File "/Users/mdickinson/.edm/envs/traits-futures-py36-wxpython/lib/python3.6/site-packages/chaco/abstract_plot_renderer.py", line 7, in <module>
from .plot_component import PlotComponent
File "/Users/mdickinson/.edm/envs/traits-futures-py36-wxpython/lib/python3.6/site-packages/chaco/plot_component.py", line 4, in <module>
from enable.api import Component
File "/Users/mdickinson/.edm/envs/traits-futures-py36-wxpython/lib/python3.6/site-packages/enable/api.py", line 21, in <module>
from .markers import MarkerTrait, marker_trait, MarkerNameDict, marker_names, \
File "/Users/mdickinson/.edm/envs/traits-futures-py36-wxpython/lib/python3.6/site-packages/enable/markers.py", line 18, in <module>
from .compiled_path import CompiledPath
File "/Users/mdickinson/.edm/envs/traits-futures-py36-wxpython/lib/python3.6/site-packages/enable/compiled_path.py", line 17, in <module>
from .toolkit import toolkit_object
File "/Users/mdickinson/.edm/envs/traits-futures-py36-wxpython/lib/python3.6/site-packages/enable/toolkit.py", line 47, in <module>
_init_toolkit()
File "/Users/mdickinson/.edm/envs/traits-futures-py36-wxpython/lib/python3.6/site-packages/enable/toolkit.py", line 35, in _init_toolkit
__import__(backend)
File "/Users/mdickinson/.edm/envs/traits-futures-py36-wxpython/lib/python3.6/site-packages/enable/wx/quartz.py", line 14, in <module>
from .base_window import BaseWindow
File "/Users/mdickinson/.edm/envs/traits-futures-py36-wxpython/lib/python3.6/site-packages/enable/wx/base_window.py", line 22, in <module>
from .constants import (
File "/Users/mdickinson/.edm/envs/traits-futures-py36-wxpython/lib/python3.6/site-packages/enable/wx/constants.py", line 127, in <module>
wx.WXK_NEXT,
AttributeError: module 'wx' has no attribute 'WXK_NEXT' |
The "<4.1" in "wxPython<4.1" is problematic with EDM on Windows - the command passed to the EDM executable is not quoted properly by the EDM batch file, so it ends up interpreting the "<4.1" as a shell redirect. One solution is to use an EDM bootstrap environment: then the invocation of We've fixed the same issue for Traits previously in enthought/traits#512 |
Still having trouble with the quoting and redirection on Windows. If the "wxPython<4.1" argument is not quoted, we get the following traceback, where the "cannot find the file specified" presumably means that the system is looking for a file called "4.1":
If it is quoted, we get instead:
|
i'm not entirely sure why you're sticking with wxPython < 4.1 because traitsui doesn't place that restriction - https://github.com/enthought/traitsui/blob/b73c475fbf311465c244fe8a1e5b7a3aa16c294f/etstool.py#L254-L263 |
I'm getting segfaults on Linux with wxPython 4.1, and no segfaults with wxPython < 4.1. |
No longer. Thanks @kitchoi for pointing out the packages I was missing! |
@@ -45,42 +45,58 @@ def tearDown(self): | |||
def test_run_until_timeout(self): | |||
# Trait never fired, condition never true. | |||
dummy = Dummy() | |||
|
|||
start_time = time.monotonic() |
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.
Note to reviewer: the changes in this file aren't specific to wx, and could be moved to a separate PR. They're regression tests for a bug I discovered in the wx implementation of the GuiTestAssistant.
|
@rahulporuri Not ready for review yet - I'm trying to replace my own timer with the official Pyface timer, but the official Pyface timer is segfaulting. |
Giving up on this for now, at least for the purposes of this PR (I'll continue to investigate and open an issue in pyface if I find a way to consistently reproduce). @rahulporuri Yes, it's ready for review! I suspect that the wx-specific pieces are going to look alien to anyone other than Robin Dunn. :-) |
For making the examples work under wx, I'll open a new issue; I don't think it has to happen in this PR. The current status is:
|
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.
LGTM with a few questions/comments. The wx-specific code wasn't too hard to track down/understand.
traits_futures/wx/pinger.py
Outdated
""" | ||
Send a ping to the ping receiver. | ||
""" | ||
event = _PingEvent(-1) |
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.
Any specific reason why we set event_id
to -1
? It doesn't matter what integer value we use, IIUC.
Also, this might be overkill but do we want to raise an error if event_id
is not an integer? Looks like wx.PostEvent
is not thread-safe for event objects having string fields.
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.
It looks as though I don't actually need this at all. I'll remove it.
Done. I've opened issues both on the pyface repo and here. |
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.
still LGTM
wx.EvtHandler.__init__(self) | ||
self._on_ping = on_ping | ||
self._binder = wx.PyEventBinder(_PING_EVENT_TYPE, 1) | ||
self.Bind(self._binder, self._on_ping_event) |
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.
Having a Bind
without a corresponding Unbind
bothers me a bit here.
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.
I guess the Unbind
call needs to happen during garbage collection so we will need to override Pinger.__del__
?
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.
Having a Bind without a corresponding Unbind bothers me a bit here.
Same here, and I'd be tempted to add it back. If there is a reason Unbinding should cause issues, maybe it deserves a comment?
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.
It's not a case of adding it back, because it was never there, and the machinery to support "I'm done with this Pinger" isn't currently there. We'll need a `Pinger.close() method, or something similar.
Given that the lack of unbind isn't actually causing issues, I think I'll leave it as is for this PR, and then add the Pinger.close
functionality in a separate PR.
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.
IOW, there's currently no place in the code structure to put that Unbind
call. I can fix that with a refactor, but it'll be messier than just adding wx support.
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.
I guess the
Unbind
call needs to happen during garbage collection so we will need to overridePinger.__del__
?
I don't have any evidence that it needs to happen at all, and likely everything that needs to happen is already taken care of at garbage collection time. It's just the lack of the explicit counterpart that bothered me.
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.
And no, I definitely don't want to override __del__
. __del__
methods are evil. :-) If we're going to unbind, it should be done at a time of our choosing rather than whenever the g.c. happens to feel like it.
…lear what it does, and we don't seem to need it.
Opened #253. |
Thanks for all the review comments! I think the only thing outstanding is the |
One last pre-merge change: I removed the note in the documentation about the lack of wxPython support. |
[Code extracted from #173; includes the commits from #245]
Following #231, this PR adds support for the wxPython toolkit, providing wx-specific implementations of the
Pinger
,Pingee
andGuiTestAssistant
classes.Known issues / tasks: