-
Notifications
You must be signed in to change notification settings - Fork 79
Updating the repository
This document is intended for contributors who wishes to update or modify this repository.
Before we get started, let's make sure we're on the same page.
- You are running a 64-bit version of Windows 7 or above
- You have downloaded and installed Visual Studio 2013
- You have downloaded and installed the MSVC 2013 version of Qt
- You have downloaded and installed Python 2.7.9 x86-64
- You have downloaded and extracted sip and PyQt5
- You can run Python by typing
python
from your command prompt - You are in the parent directory of the extracted sip and PyQt5 distributions.
$ cd %HOMEPATH%\Downloads\
Head on over to your terminal and let's get compiling.
Please note that the compilation can take over an hour to finish.
# Setup Visual C++ x64
$ "c:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\bin\amd64\vcvars64.bat"
$ cd sip-4.16.5
$ python configure.py
$ nmake
$ nmake install
$ cd ..\PyQt-gpl-5.4
# This part requires that the Qt binaries are on your PATH
$ set PATH=%PATH%;C:\Qt\5.4\msvc2013_64\bin
$ python configure.py
$ nmake
$ nmake install
Several minutes later, you should have a working copy of PyQt5 and sip in your Python's site-packages directory.
c:\Python27\Lib\site-packages\PyQt5
- Download
test.py
from the helper gist. - Run
test.py
You should be seeing a window with a single clickable button in it.
Now for the tricky part.
Qt, and therefore PyQt, have a number of requirements on the environment in which it is to be run. Right off the bat, you'll notice that if you run run the same test from above in a new terminal, it will fail.
$ python test.py
ImportError: DLL load failed: The specified module could not be found.
The reason it worked before was because of the PATH
environment variable we set up for compilation, remember? The one pointing to the Qt \bin
directory? But we can't ask users to first install PyQt5, and then install Qt. We'd like them to install just PyQt5 and be done with it.
And that's exactly what we'll be doing in this part.
Table of contents
- Bundling binaries
- Bundling plugins
- Bundling QML libraries
- Bundling sip
- Bundling Extras
- Bundling Visual C++ redistributable
The first and most obvious fact is that we need to include the Qt binaries into the distribution. PyQt is merely a C-to-Python translator for these binaries and without them it won't do much.
We can prove this by including the binaries to the PATH
and running the test again.
$ set PATH=%PATH%;C:\Qt\5.4\msvc2013_64\bin
$ python test.py
The \bin
directory is however very large, how do we know which ones to include? I'm glad you asked. In a nutshell, without rigorious testing and assumption making, the safest thing we can do is to include all of them, except for..
- Files ending with "d.dll"
- Files ending with ".pdb"
- exclusion_list.yaml
Which is only used for development.
Copy binaries
- Copy everything under
C:\Qt\5.4\msvc2013_64\bin
- To
C:\Python27\Lib\site-packages\PyQt5
- Download
clean_binaries.py
from the helper gist - Run
clean_bin.py
within thePyQt5
directory
$ cd c:\Python27\Lib\site-packages\PyQt5
$ python clean_binaries.py
...
Removing .\Qt5Widgetsd.dll
Removing .\Qt5Widgetsd.pdb
Removing .\Qt5WinExtrasd.dll
Removing .\Qt5WinExtrasd.pdb
Removing .\Qt5Xmld.dll
Removing .\Qt5Xmld.pdb
Removing .\Qt5XmlPatternsd.dll
Removing .\Qt5XmlPatternsd.pdb
Finished
With that out of the way, let's test it.
$ python test.py
Excellent. What's next?
Qt ships with a number of plug-ins; one of these plug-ins is the QPA, for Qt Platform Abstraction. Without this, we will not be able to make much use of PyQt5.
We can prove this by temporarily renaming the plugins
directory of the original Qt distribution.
Proving the dependency of plugins
- Rename
plugins
inC:\Qt\5.4\msvc2013_64
- To
_plugins
- Run
test.py
$ python test.py
This application failed to start because it could not find or load the Qt platform plugin "windows".
To bundle the plugins
- Copy
plugins
fromc:\Qt\5.4\msvc2013_64
- To
C:\Python27\Lib\site-packages\PyQt5
- Run
clean_binaries.py
to clean up unwanted files. - You should now have a directory
C:\Python27\Lib\site-packages\PyQt5\plugins
- Run
test.py
$ python test.py
It's still not working? That's because although we have copied the plugins, Qt doesn't know where to look for them. We can tell it by including a special file called qt.conf
, which looks like this.
qt.conf
[Paths]
Prefix = .
This tells Qt to prefix all of it's default search paths with the parent directory of qt.conf
. This includes paths to plugins, but also QML libraries.
- Save
qt.conf
in yourC:\Python27\Lib\site-packages\PyQt5
directory. - Run the test again to confirm.
Read more about QPA and Qt.conf here
As mentioned above, if we want to be able to use QML, we must include it's libraries. Let's start by confirming that running a QML application currently does not work.
- Download
test.qml
- Run
test.qml
$ C:\Python27\Lib\site-packages\PyQt5\qmlscene.exe test.qml
module "QtQuick" is not installed
**Bundle the QML libraries.
- Copy
qml
fromC:\Qt\5.4\msvc2013_64
- To
C:\Python27\Lib\site-packages\PyQt5
- You should now have a directory called
C:\Python27\Lib\site-packages\PyQt5\qml
- Run
test.qml
$ C:\Python27\Lib\site-packages\PyQt5\qmlscene.exe test.qml
Due to qt.conf
, Qt will know to look for this exact directory in the parent directory of qt.conf
.
Sip is a dependency of PyQt5, we can prove this by temporarily renaming it from the Python site-packages directory.
Prove that sip is a dependency
- Rename
sip.pyd
inC:\Python27\Lib\site-packages
- To
_sip.pyd
- Run test
$ python test.py
ImportError: No module named sip
Bundling sip
- Copy
sip.pyd
fromC:\Python27\Lib\site-packages
- To
C:\Python27\Lib\site-packages\PyQt5
- Run test
$ python test.py
Apart from including everything Qt, we are also going to want to include the work done by Riverbank Software.
To bundle all extras
- Download and install the [PyQt5 for Python 3][py3qt5] distribution (you won't need Python 3 installed).
- Copy the following directories from
C:\Python34\Lib\site-packages\PyQt5
doc
examples
include
mkspecs
qsci
sip
translations
uic
- Into
C:\Python27\Lib\site-packages\PyQt5
- Remove
C:\Python27\Lib\site-packages\PyQt5\uic\port_v3
(as it only applies to Python 3)
The next and final step is coming to us from Visual Studio-land. And that is the Visual C++ re-distributable.
msvcr120.dll
msvcp120.dll
# Located in
C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\redist\x64\Microsoft.VC120.CRT
To prove this, let us temporarily rename this file and run our test.
To prove the dependency on Visual C++ redistributable
- Rename either
msvcr120.dll
ormsvcp120.dll
inC:\Windows\System32
- To
_msvcr120.dll
or_msvcp120.dll
- Run the test.
$ python test.py
ImportError: DLL load failed: The specified module could not be found.
- Restore the names.
To bundle the Visual C++ redistributable
- Copy
msvcr120.dll
andmsvcp120.dll
fromC:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\redist\x64\Microsoft.VC120.CRT
- To
C:\Python27\Lib\site-packages\PyQt5
- Run the test
$ python test.py
You should now be able to run the test successfully regardless of the files in your System32
directory.
In addition to bundling, we'll need to append versioning information to the package so as to keep track of which python-qt5
release is the latest one.
- Start by copying [the original
__init__.py
][init] - To
C:\Python27\Lib\site-packages\PyQt5
- Overwrite existing
Next we'll increment the version number according to our toolchain.
To append version numbers
- Open
C:\Python27\Lib\site-packages\PyQt5\__init__.py
in your favorite text editor. - Increment the following.
version_info = (0, 2, 0)
The scheme is:
- (0, 2, 0) means fixes
- (0, 2, 0) means updates to the Qt library (such as this).
- (0, 2, 0) means backwards-incompatible changes.
In addition, we'll also increment the PyQt and Qt versions that were used in the making of this distribution.
pyqt_version_info = (5, 4, 0)
qt_version_info = (5, 4, 0)
The reason we need both is because it's possible that these two differ.
Now that we've got a working copy of PyQt5, it's time to update the repository. The first thing we'll need to do is clone the exiting state of the repository.
$ cd c:\
$ mkdir github
$ cd github
$ git clone https://github.com/pyqt/python-qt5.git
$ cd python-qt5
Now we will rip it apart, leaving only the what is needed for GitHub and Travis to function.
- Remove the
c:\github\python-qt5\PyQt5
directory. - Remove everything in
c:\github\python-qt5\src
Now we fill it back up with our newly compiled distribution.
- Copy
PyQt5
fromC:\Python27\Lib\site-packages
- To
c:\github\python-qt5
- Copy the source distributions
PyQt-gpl-5.4
andsip-4.16.5
- Into
c:\github\python-qt5\src
- The GPL requires that we include these.
Before we push it out into the wild, let's make sure it works.
To make sure it works
- On another machine/environment
- Install with pip.
$ pip install virtualenv
$ virtualenv test-qt5 --no-site-packages
$ test-qt5\Scripts\activate
(test-qt5) $ pip install c:\github\python-qt5
(test-qt5) $ python c:\github\test.py
Assuming everything worked out, we can now push.
$ git add .
$ git commit -m "Updating Qt to 5.4"
$ git push
This potion requires that you have write access to the repository. If you don't, please feel free to push to your own fork and submit a pull-request and I'll ensure it gets uploaded to PyPI as soon as possible!
- Go to the Releases page on GitHub.
- Tag the release with it's version name; e.g.
0.2.0
- From here, Travis will compile and upload the release to PyPI.
See Releases for examples of previous releases.
And you're done. Thanks for taking the time to update the PyQt5 distribution and happy programming!
- Script this guide
- More testing
- Number of files installed via pip vs. number of original files (they should match)
- Simplify setup.py:get_package_data()
- Update exclusion_list.yaml
Help wanted.
Welcome to the wiki for PyQt5 using Python 2.7. For Python 3.4, head here
Table of contents
Developer Resources
Compilation Instructions