wxPython 4.0.1 Released

wxPython 4.0.1 is now available at PyPI, with some additional files at the Extras archive.

This release is a quick hot-fix of some issues discovered in 4.0.0 just after the release, plus a bit of low-hanging fruit that was easy to squeeze in too. Changes in this release include the following:

  • A fix for a segfault that happens upon startup on newer linux releases. (#648)

  • Set LD_RUN_PATH for the wxWidgets part of the build so the wx libs that are loaded by other wx libs can be found successfully. (#723)

  • Use wxApp::GetInstance to check if there is an existing wxApp object. (#720)

wxPython 4.0.0 Released

The Phoenix Takes Flight!

wxPython 4.0.0 is now available at PyPI, with some additional files at the Extras archive.

Changes in this release include the following:

  • Fixes in wx.aui to properly transfer ownership of the menubar, and also some tweaks in the AUI_MDI sample in the demo. (#540)

  • Added a wx.BUILD_TYPE value to distinguish between development, snapshot, and release builds. The value is also appended to wx.PlatformInfo. (Thanks Mesalu!)

  • Fix crash when trying to fetch multiple items from a composite data object in wx.DropTarget.OnData. (#550) Also fixed the CustomDragAndDrop sample to not fail on Python 2.7.

  • Add ability for wxArray wrappers to return a copy of the item in the __getitem__ method. This solves problems where an array that is the return value of some method call is indexed immediately and a reference to the array is not held, which could result in garbage values for the indexed item. Currently this is turned on for just GridCellCoordsArray, but others can be switched in the future if needed. (#297)

  • Add missing wx.GetLocale function. (#572)

  • Add methods to wx.TextCtrl for output "file-like" compatibility. (#578)

  • Fix object ownership issue for menus added to toolbar items. (#580)

  • Updated SIP to version 4.19.5. One of the new features of this version is that integer overflows are no longer silently truncated and ignored. In other words, if a wrapped API has a parameter that is a C int type, and you pass a value that is larger than what will fit in that type of integer then an OverflowError exception will be raised.

  • Fixed wx.richtext.RichTextBuffer.GetExtWildcard to return a tuple of 2 values, as was done in Classic. (#594)

  • Various fixes in UltimateListCtrl, HyperTreeList and CheckListCtrlMixin. (#592, #349, #612)

  • Fixes in TextEditMixin to ensure that the new value is passed in the event. (#605)

  • Fix comparing DataViewItem and TreeListItem objects with None. (#595)

  • Fix event type name in wx/lib/sheet.py (#613)

  • The wx.MessageDialog methods which take ButtonLabel parameters are now able to accept either strings or stock IDs. (#607, #276)

  • Fix wx.EvtHandler.Unbind to work correctly when specifying the handler and it is a bound method. (#624)

  • Fix OGL's ShapeCanvas to draw properly when the window is scrolled, and to also adjust the mouse coordinates, etc. (#635)

  • Set a default background color for the generic buttons. (#651)

  • Fixed HtmlWindow's OnFoo virtual methods so calls to them are propagated to the Python class. (#642)

  • Fixed wx.CallLater to explicitly hold a reference instead of depending on an uncollectable cycle to keep the instance around. Like before the cycle is broken and the saved reference is deleted after the timer expires and the callable has been called. (#457)

  • Although it's more or less just an implementation detail, add wrappers for wx.aui.AuiTabCtrl so references to it will get the correct type. (#664)

  • List-like wrapper classes generated for accessing wxLists and wxArrays now support reverse indexing. (#669) For example:

    child = panel.GetChildren()[-1]

  • Ported some of the classes in Classic's gizmos module from C++ to Python, including LEDNumberCtrl, DynamicSashWindow, and TreeListCtrl. The classes are now located in the wx.lib.gizmos package, with a compatibility module at the old wx.gizmos location. Please note that this TreeListCtrl class is a very different implementation than wx.dataview.TreeListCtrl, although there is some overlap in purpose. In addition, the new TreeListCtrl class is not actually a port from the old gizmos.TreeListCtrl but rather just a thin layer around AGW's HyperTreeList. This means that if you are using a non- default style flag you'll need to pass it to the agwStyle parameter instead of the style parameter.

  • Fix crash when deleting all wx.dataview.TreeListCtrl items with wxGTK3. (#679, #704)

  • Fix displaying '&' in the label of wx.RadioBox on GTK. (#39)

  • Fix problems of the wrong C++ method being called in wx.ProgressDialog on MS Windows. (#701)

  • Fixed how the scrollbar events are captured in DynamicSashWindow in order to fix regression in the sample. (#687)

  • Allow extra CLI args to be passed to build.py by setting WXPYTHON_BUILD_ARGS in the environment.

  • Added context manager methods to wx.DC that explicitly destroys the C++ part of the DC upon exit. Using DCs as context managers is not required, but can be handy in the rare cases where something holds on to a DC for too long, perhaps unintentionally. (#680)

  • Fixed crash due to too aggressive management of wxModules when we load subordinate extensions that have their own wxModules (wx.html, wx.adv, etc.) (#688)

  • Fixed StyledTextCtrl.MarkerDefineRGBAImage and RegisterRGBAImage methods to be able to accept any Python buffer compatible object for the pixel data. (#716)

But Wait! There's More!

Be sure to also check out the release announcements for the 4.0 pre-release builds in order to get the full picture of everything that went into the 4.0 release.

Building wxPython for Linux via Pip

[ Post updated 2018-02-03, see new Build Steps section below. ]

wxPython Wheels for Linux?

Before reading further, you may want to check and see if there are already some wxPython wheels available for your flavor of Linux. A few are built as part of the release process and are available from one of wxPython's servers. More details and some links are on the download page.

If there are no existing wheels there for your distro, (or perhaps a close relative,) then read on to find out why we can't just provide wheels for all Linuxes, and what you need to build one for yourself.

The Problem

There have been some issues flowing into Phoenix's issue tracker since the release of wxPython 4.0.0b1 related to installation issues on Linux using pip, which have caused some overhead and soaked up unnecessary amounts of time. So lets start with getting some of the basics out of the way. There are a lot of flavors of linux. To name a few there's the Debian family, Debian, Ubuntu, Kubuntu, Elementary, Mint, etc., Arch, Gentoo, RHEL and CentOS, and so on. Each flavor has differences which can make binary distributions incompatible across flavors.

Why does this affect wxPython you may ask? It's just a Python package, and Python source is independent across operating systems after all, right?. Well, not all Python packages are just Python. wxPython as an example contains binary extension modules (compiled C or C++ code that is platform and architecture dependent.) wxPython by default also contains a copy of the compiled version of the wxWidgets library written in C++, which also depends on other 3rd party libraries which need to not only be present at runtime, but also have their development-related files present at wxWidgets' and wxPython's compile time.

Pip in its infinite wisdom can detect this, and knows how to select the appropriate binary wheel for the following criteria:

  • OS (Windows, macOS, Linux)
  • Architecture (i386, x86_64, etc)
  • Python Version (2.7, 3.5, 3.6, etc)

See how pip doesn't care about the specific linux distribution? That's the issue. The binary content and dependencies of wxPython can't be delivered consistently via pip. There are some efforts to get around this (eg. PEP 513 a.k.a. manylinux1) but they don't quite work for wxPython yet. Packages that are able to fit into the very narrow manylinux1 requirements can be hosted on PyPI and will install with pip just as smoothly as pure-python packages do. Unfortunately the manylinux1 spec does not include a version of GTK+ and its dependencies that are new enough to be able to provide all the features that wxWidgets requires.

The Fix

In order to deploy to linux systems wxPython4 (Phoenix) simply builds itself from a source tarball as part of the pip setup process. All of the code generated by wxPython's build system is already present in the tarball, it merely needs to be compiled. This causes a very lengthy installation times, but is a necessary evil. Because the build is just that, a build, you will need all of wxWidgets and wxPython's binary dependencies present at build time. wxWidgets' configure will be run, and if it detects missing libraries the whole build, and therefore the pip installation, will fail.

What You Need

You will need the following packages (please consult your distribution's package list for the appropriate package names) and their dependencies:

  • python-dev (for your version of python)
  • gtk (preferably version 3, but depends on your needs)
  • gstreamer
  • gstreamer-plugins-base
  • glut
  • libwebkitgtk (matching your gtk version)
  • libjpeg
  • libpng
  • libtiff
  • libsdl
  • libnotify
  • libsm

on Debian based systems, or other systems that separate development packages from standard packages, you will need the corresponding -dev or -devel package in addition to the standard package.

Once the appropriate packages are present on your system then wxPython should build with no problems, either with pip or from a source tree extracted from the source tarball. If it still doesn't work for you then be sure to look closely at the build log as there will likely be some clues there that may point you in the right direction. For example, this:

checking for OpenGL headers... not found
checking for GL/gl.h... no
configure: error: OpenGL libraries not available

will tell you that the OpenGL libraries are missing. They are usually a dependency of the glut or freeglut packages and should have been installed along with that library, but perhaps your system's dependencies are different and you'll need to do a little investigation to determine the proper system packages that need to be installed.

Build Steps

Once you have installed the required depenency libraries, it should take just a few steps to build a wxPython that will work on your system with your Python. The steps shown here are just one option, but seems to be one of the simpler approaches to take, and will require nothing extra to be installed in your system Python. These instructions assume that you will be using a 3.4+ version of Python and that the executable is called "python3". If you are using 2.7 or the binary is called something else then adapt accordingly.

Step 1: The first thing we'll do is create and activate a new virtual environment for the build and the initial testing. This is optional, but highly recommended as it will ensure that there is nothing left over from a previous build that could trip things up. The last two commands shown here are just so you can verify that the python and pip commands are now being found in the new virtual environment instead of from the system or other Python environment.

cd [some tmp folder]

python3 -m venv builder_py
source builder_py/bin/activate

which python
which pip

Step 2: Next, you'll want to update pip and add a few more packages.

pip install -U pip
pip install -U six wheel setuptools

Step 3: Use pip to download the latest source archive from PyPI.

pip download wxPython

Step 4: Use pip to build a wxPython wheel file. We'll also redirect the build output to a file so you can review it later if needed. This step will take a while to complete, as it will be compiling all the wxWidgets and wxPython source code, but you'll be able to watch the build output to monitor the progress. Be sure to use the actual name of the downloaded source archive file, which may be different than the one shown here.

pip wheel -v wxPython-4.0.1.tar.gz  2>&1 | tee build.log

Step 5: If the build was successful then you should now have a wxPython wheel file in the current working directory. If there was a problem then review the build.log file and see if you can spot any clues as to what dependencies may be missing or out of date. (Build problems from wxPython release sources are almost always due to missing dependencies.) Once you think you have solved the problem go back to step 4 and try the build again.

Step 6: The next step is to install the wheel file in the virtual environment and give it a quick test run. (Use the actual name of the wheel file you built, which may be different than the one shown here.)

pip install wxPython-4.0.1-cp35-cp35m-linux_x86_64.whl

python -c "import wx; a=wx.App(); wx.Frame(None,title='hello world').Show(); a.MainLoop();"

You should see a new window open with a "hello world" title bar, which will indicate that this build was successful and this wxPython wheel can be used on your system. You can now use pip to install the wheel file in other Python environments or virtual environments that use the same base Python executable that you used for this build.


Q1: "Why can't you just install the necessary packages as part of wxPython's installation"

A1: Lots of good reasons, among them are: Pip is NOT your linux package manager, Phoenix is not responsible for maintaining your system.

Q2: "I can install PyQt(4/5) just fine via pip! Why can't wxPython do the same?"

A2: Qt does not depend on system provided libraries other than the low- level basic libs. wxWidgets does, it's one of the defining differences of the two toolkits. As such PyQt can deliver to all linuxes in the same manner.

New wxPython Website

"The 2000s called, they want their website back..."

Not any more! I finally gave the old clunky site back to the dinosaurs and have implemented a brand new site (using the awesome static site generator Nikola) which you are gazing at with much adoration now. The new site combines most of what was on the old site, plus a news feed (you're reading a news post right now) and I also resurrected my old wxForty-Two blog from the wordpress graveyard and added it here too. Being a static site I no longer have to worry about the perpetual stream of wordpress security issues.

Read more…