Multi-Version Installs
Introduction
Starting with 2.5.3.0 the wx and wxPython pacakge directories will be installed in a subdirectory of the site-packages directory, instead of directly in site-pacakges. This is done to help facilitate having multiple versions of wxPython installed side-by-side. Why would you want to do this? One possible scenario is you have an app that requires wxPython 2.4 but you want to use the newest 2.5 to do your development with. Or perhaps you want to be able to test your app with several different versions of wxPython to ensure compatibility. Before everyone panics, rest asured that if you only install one version of wxPython then you should notice no difference in how things work.
In addition to installing wxPython into a "versioned" subdirectory of site-packages, a file named wx.pth is optionally installed that will contain the name of the versioned subdirectory. This will cause that subdirectory to be automatically added to the sys.path and so doing an "import wx" will find the package in the subdirectory like it would have if it was still located in site-packages. I say "optionally" above because that is how you can control which install of wxPython is the default one. Which ever version installs the wx.pth file will be the one that is imported with a plain "import wx" statement. Of course you can always manipulate that by editing the wx.pth file, or by setting PYTHONPATH in the environment, or by the method described in the next paragraph.
Finally, a new module named wxversion.py is installed to the site-pacakges directory. It can be used to manipulate the sys.path at runtime so your applications can select which version of wxPython they would like to to have imported. You use it like this:
import wxversion wxversion.select("2.4") import wx
Then, eventhough a 2.5 version of wxPython may be the default the application that does the above the first time that wx is imported will actually get a 2.4 version. NOTE: There isn't actually a 2.4 version of wxPython that supports this, but there will be.
Install Directory Name Format
The site-packages subdirectory used for installing wxPython will have the following format, with some parts being optional depending on platform and build options:
wx-VERSION [-PORT-CHARTYPE [-FLAVOUR]]
VERSION: By default this will be just the first two components of the version number, (or the first three in an "unstable" release series) but the version selection code will support using all four components of the version number if you would like to manage it that way on your own.
PORT: This represents the wxWidgets port that was used to build wxPython. For Windows and Mac you can ignore this as there is only one port each that is currently supported for those platforms. Currently on unix systems there are two possible values, "gtk" and "gtk2".
CHARTYPE: This will either be "ansi" or "unicode" depending on how wxWidgets and wxPyton were built. In the unicode build then all strings passed to wx functions and methods will first be converted to unicode objects using the default encoding, and all string values returned from wx functions and methods will actually be unicode objects. See UnicodeBuild for more info.
FLAVOUR: This is an arbitrary tag that can be used in wxWidgets builds to further distinguish custom builds from stock ones. wxPython supports it as well but doesn't use it by default.
Here are some possible directory names:
wx-2.5.3 wx-2.5.3-gtk2-unicode wx-2.5.3.0-gtk2-unicode
So as you can see the complexity of the name really depends on the level of ganularity that you need to support. By default wxPython will allow you to install all supported versions of wxPython for a single platform at the same time. That means that the middle example above with the short version and the port and chartype is what the official binaries will use.
How do I use wxversion?
As mentioned above there is a new module called wxversion.py. It is installed directly in site-packages, outside of any of the versioned wxPython directories, and can be used to control at runtime which version of wxPython is imported.
Usage is very simple, you simply import the module at the very begining of your app and call its select function. It will then go and look at all of the directories in sys.path and check if there are any subdirectories that match wxPython's installation pattern. All of the matches found are compared with the version(s) requested by your app and a score is calculated. The directory containing the version with the best score is inserted at the begining of the sys.path and then select returns. Now when your app imports the wx package the matching version will be the one that is imported. Pretty slick, eh?
The way the score is calculated is pretty simple and flexible. First, the version number part of the string is converted to a tuple of integers, and the rest of the string is split at the hyphens and strored as a list of options. Finally the version tuple is compared with the installed package and if they don't match the score is an automatic zero. Otherwise it starts with a score of one. Then for every option you ask for that matches an installed version the score will be increased by one more point.
You can be as detailed or as generic as you want in how you ask for a version. For example, all of these are valid requests:
wxversion.select("2.4") wxversion.select("2.5.3") wxversion.select("2.5-unicode") wxversion.select("2.5.3-gtk-ansi")
Whichever installed version has the best score when compared with your request will be the one chosen. This means that you may not get exactly what you ask for, but at least the version will match.
You can also pass a list of versions to select from, and again, whichever installed version has the best score with any of your requests will be the one chosen. Since the installed versions are in reverse sorted order when doing the scoring any ties will be broken by choosing the one with the largest version number. For example:
wxversion.select(["2.5.4", "2.6"])
In the example above if both 2.5.4 and 2.6.1 are installed then 2.6.1 will be chosen.
What is the reccomended usage?
Although wxversion will allow you to be very specific your choice of version if you really need to, I think that it makes the most sense most of the time to use it more generically and only ask for the release series that your app requires. For example, if you write your app with 2.6.0.1 and expect it to continue working with all 2.6.x releases (since that will be a stable API release series) then just use
wxversion.select("2.6")
Please also read the section below on installing upgrades for another reason why just selecting my release series makes the most sense.
What about library modules?
To be written...
What about py2exe or similar tools?
There are several tools available that allow you to bundle everything needed to make your Python application a stand-alone application, able to be installed independently of Python and any extensions that your app uses, such as wxPython. They usually work by inspecting all the modules imported by your app and collecting the modules, extensions and shared libraries that it needs and "bundling" it all together in a way that it can be distributed to other machines.
Since wxversion scans the filesystem using sys.path looking for installed versions of wxPython, there is no need for it to do that from a bundled app since wxPython will be included in the bundle. So it is recommended that if your app will bundled by one of these tools that you either don't use wxversion, or that you use it conditionally. For example, with py2exe you can tell if running from a bundled application by checking for the "frozen" attribute in the sys module. So you could do something like this in the main module of your application:
import sys if not hasattr(sys, "frozen"): import wxversion wxversion.select("2.5") import wx
If you have multiple versions installed and need to have a specific version bundled with your app, then simply ensure that version is found by default when wx is imported. You can do that by setting the PYTHONPATH variable in the environment.
How do I convert an existing install to a multi-version?
To be written...
Which Installer pacakges do I need?
To be written...
What happens when I install a new version of wxPython?
To be written...
This is confusing, why did you do it?
To be written...