summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRoman Lacko <backup.rlacko@gmail.com>2012-06-04 16:13:58 +0200
committerRoman Lacko <backup.rlacko@gmail.com>2012-06-04 16:13:58 +0200
commitf82195bf001f5f75ffb27735ecf6e98941ce4405 (patch)
treeb2d06173468e571469b3863b24768bd63ea0ad7f
Initial commit (copy of lck/pyside-dist repo)
-rw-r--r--.gitignore11
-rw-r--r--.gitmodules12
-rw-r--r--MANIFEST.in41
-rw-r--r--README.txt235
-rw-r--r--popenasync.py311
-rw-r--r--pyside_postinstall.py174
-rw-r--r--qtinfo.py51
-rw-r--r--setup.py609
m---------sources/pyside13
m---------sources/pyside-examples0
m---------sources/pyside-tools0
m---------sources/shiboken12
-rw-r--r--utils.py177
13 files changed, 1646 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 00000000..80f86bc3
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,11 @@
+/build
+/dist
+/pyside_build
+/pyside_install
+/PySide
+/PySide-*.*.*
+/SciTE.*
+/pysideuic
+*.egg-info
+*.pyc
+patchelf
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 00000000..2cb2d59e
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,12 @@
+[submodule "sources/shiboken"]
+ path = sources/shiboken
+ url = https://git.gitorious.org/pyside/shiboken.git
+[submodule "sources/pyside"]
+ path = sources/pyside
+ url = https://git.gitorious.org/pyside/pyside.git
+[submodule "sources/pyside-tools"]
+ path = sources/pyside-tools
+ url = https://git.gitorious.org/pyside/pyside-tools.git
+[submodule "sources/pyside-examples"]
+ path = sources/pyside-examples
+ url = https://git.gitorious.org/pyside/pyside-examples.git
diff --git a/MANIFEST.in b/MANIFEST.in
new file mode 100644
index 00000000..95f5ed0c
--- /dev/null
+++ b/MANIFEST.in
@@ -0,0 +1,41 @@
+#
+# MANIFEST.in
+#
+# Manifest template for creating the PySide source distribution.
+
+include MANIFEST.in
+include setup.py
+include pyside_postinstall.py
+include popenasync.py
+include qtinfo.py
+include utils.py
+
+# sources
+recursive-include sources/patchelf **
+recursive-include sources/shiboken **
+recursive-include sources/pyside **
+recursive-include sources/pyside-tools **
+recursive-include sources/pyside-examples **
+recursive-exclude sources/pyside-examples/examples/hyperui **
+recursive-exclude sources/pyside-examples/mobility **
+# ignore .git
+recursive-exclude sources/shiboken/.git **
+recursive-exclude sources/pyside/.git **
+recursive-exclude sources/pyside-tools/.git **
+recursive-exclude sources/pyside-examples/.git **
+
+# PySide package
+recursive-include PySide **
+recursive-include PySide/plugins **
+recursive-include PySide/imports **
+recursive-include PySide/translations **
+recursive-include PySide/include **
+recursive-include PySide/typesystems **
+recursive-include PySide/examples **
+
+# pysideuic package
+recursive-include pysideuic/ **
+recursive-include pysideuic/Compiler **
+recursive-include pysideuic/port_v2 **
+recursive-include pysideuic/port_v3 **
+recursive-include pysideuic/widget-plugins **
diff --git a/README.txt b/README.txt
new file mode 100644
index 00000000..2527401b
--- /dev/null
+++ b/README.txt
@@ -0,0 +1,235 @@
+============
+About PySide
+============
+
+PySide is the Python Qt bindings project, providing access the complete Qt 4.8 framework
+as well as to generator tools for rapidly generating bindings for any C++ libraries.
+
+The PySide project is developed in the open, with all facilities you'd expect
+from any modern OSS project such as all code in a git repository [1], an open
+Bugzilla [2] for reporting bugs, and an open design process [3]. We welcome
+any contribution without requiring a transfer of copyright.
+
+=======
+Changes
+=======
+
+1.1.1 (2012-04-19)
+==================
+
+Major changes
+-------------
+
+- Unified toolchain! No more GeneratorRunner and ApiExtractor, now you just need Shiboken to compile PySide.
+
+Bug fixes
+---------
+
+- 1105 Spyder fails with HEAD
+- 1126 Segfault when exception is raised in signalInstanceDisconnect
+- 1135 SIGSEGV when loading custom widget using QUiLoader when overriding createWidget()
+- 1041 QAbstractItemModel has wrong ownership policy for selectionModel()
+- 1086 generatorrunner segfault processing #include
+- 1110 Concurrency error causes GC heap corruption
+- 1113 Instantiating QObject in user-defined QML element's constructor crashes if instantiated from QML
+- 1129 Segmentation fault on close by QStandardItem/QStandardItemModel
+- 1104 QSettings has problems with long integers
+- 1108 tests/QtGui/pyside_reload_test.py fails when bytecode writing is disabled
+- 1138 Subclassing of QUiLoader leads to "Internal C++ object already deleted" exception (again)
+- 1124 QPainter.drawPixmapFragments should take a list as first argument
+- 1065 Invalid example in QFileDialog documentation
+- 1092 shiboken names itself a 'generator'
+- 1094 shiboken doesn't complain about invalid options
+- 1044 Incorrect call to parent constructor in example
+- 1139 Crash at exit due to thread state (tstate) being NULL
+- PYSIDE-41 QModelIndex unhashable
+
+1.1.0 (2012-01-02)
+==================
+
+Major changes
+-------------
+
+- New type converter scheme
+
+Bug fixes
+---------
+
+- 1010 Shiboken Cygwin patch
+- 1034 Error compiling PySide with Python 3.2.2 32bit on Windows
+- 1040 pyside-uic overwriting attributes before they are being used
+- 1053 pyside-lupdate used with .pro files can't handle Windows paths that contain spaces
+- 1060 Subclassing of QUiLoader leads to "Internal C++ object already deleted" exception
+- 1063 Bug writing to files using "QTextStream + QFile + QTextEdit" on Linux
+- 1069 QtCore.QDataStream silently fails on writing Python string
+- 1077 Application exit crash when call QSyntaxHighlighter.document()
+- 1082 OSX binary links are broken
+- 1083 winId returns a PyCObject making it impossible to compare two winIds
+- 1084 Crash (segfault) when writing unicode string on socket
+- 1091 PixmapFragment and drawPixmapFragments are not bound
+- 1095 No examples for shiboken tutorial
+- 1097 QtGui.QShortcut.setKey requires QKeySequence
+- 1101 Report invalid function signatures in typesystem
+- 902 Expose Shiboken functionality through a Python module
+- 969 viewOptions of QAbstractItemView error
+
+1.0.9 (2011-11-29)
+==================
+
+Bug fixes
+---------
+
+- 1058 Strange code in PySide/QtUiTools/glue/plugins.h
+- 1057 valgrind detected "Conditional jump or move depends on uninitialised value"
+- 1052 PySideConfig.cmake contains an infinite loop due to missing default for SHIBOKEN_PYTHON_SUFFIX
+- 1048 QGridLayout.itemAtPosition() crashes when it should return None
+- 1037 shiboken fails to build against python 3.2 (both normal and -dbg) on i386 (and others)
+- 1036 Qt.KeyboardModifiers always evaluates to zero
+- 1033 QDialog.DialogCode instances and return value from QDialog.exec_ hash to different values
+- 1031 QState.parentState() or QState.machine() causes python crash at exit
+- 1029 qmlRegisterType Fails to Increase the Ref Count
+- 1028 QWidget winId missing
+- 1016 Calling of Q_INVOKABLE method returning not QVariant is impossible...
+- 1013 connect to QSqlTableModel.primeInsert() causes crash
+- 1012 FTBFS with hardening flags enabled
+- 1011 PySide Cygwin patch
+- 1010 Shiboken Cygwin patch
+- 1009 GeneratorRunner Cygwin patch
+- 1008 ApiExtractor Cygwin patch
+- 891 ApiExtractor doesn't support doxygen as backend to doc generation.
+
+1.0.8 (2011-10-21)
+==================
+
+Major changes
+-------------
+
+- Experimental Python3.2 support
+- Qt4.8 beta support
+- Bug Fixes
+
+Bug fixes
+---------
+
+- 1022 RuntimeError: maximum recursion depth exceeded while getting the str of an object
+- 1019 Overriding QWidget.show or QWidget.hide do not work
+- 944 Segfault on QIcon(None).pixmap()
+
+1.0.7 (2011-09-21)
+==================
+
+Bug fixes
+---------
+
+- 996 Missing dependencies for QtWebKit in buildscripts for Fedora
+- 986 Documentation links
+- 985 Provide versioned pyside-docs zip file to help packagers
+- 981 QSettings docs should empathize the behavior changes of value() on different platforms
+- 902 Expose Shiboken functionality through a Python module
+- 997 QDeclarativePropertyMap doesn't work.
+- 994 QIODevice.readData must use qmemcpy instead of qstrncpy
+- 989 Pickling QColor fails
+- 987 Disconnecting a signal that has not been connected
+- 973 shouldInterruptJavaScript slot override is never called
+- 966 QX11Info.display() missing
+- 959 can't pass QVariant to the QtWebkit bridge
+- 1006 Segfault in QLabel init
+- 1002 Segmentation fault on PySide/Spyder exit
+- 998 Segfault with Spyder after switching to another app
+- 995 QDeclarativeView.itemAt returns faulty reference. (leading to SEGFAULT)
+- 990 Segfault when trying to disconnect a signal that is not connected
+- 975 Possible memory leak
+- 991 The __repr__ of various types is broken
+- 988 The type supplied with currentChanged signal in QTabWidget has changed in 1.0.6
+
+1.0.6 (2011-08-22)
+==================
+
+Major changes
+-------------
+
+- New documentation layout;
+- Fixed some regressions from the last release (1.0.5);
+- Optimizations during anonymous connection;
+
+Bug fixes
+---------
+
+- 972 anchorlayout.py of graphicsview example raised a unwriteable memory exception when exits
+- 953 Segfault when QObject is garbage collected after QTimer.singeShot
+- 951 ComponentComplete not called on QDeclarativeItem subclass
+- 965 Segfault in QtUiTools.QUiLoader.load
+- 958 Segmentation fault with resource files
+- 944 Segfault on QIcon(None).pixmap()
+- 941 Signals with QtCore.Qt types as arguments has invalid signatures
+- 964 QAbstractItemView.moveCursor() method is missing
+- 963 What's This not displaying QTableWidget column header information as in Qt Designer
+- 961 QColor.__repr__/__str__ should be more pythonic
+- 960 QColor.__reduce__ is incorrect for HSL colors
+- 950 implement Q_INVOKABLE
+- 940 setAttributeArray/setUniformValueArray do not take arrays
+- 931 isinstance() fails with Signal instances
+- 928 100's of QGraphicItems with signal connections causes slowdown
+- 930 Documentation mixes signals and functions.
+- 923 Make QScriptValue (or QScriptValueIterator) implement the Python iterator protocol
+- 922 QScriptValue's repr() should give some information about its data
+- 900 QtCore.Property as decorator
+- 895 jQuery version is outdated, distribution code de-duplication breaks documentation search
+- 731 Can't specify more than a single 'since' argument
+- 983 copy.deepcopy raises SystemError with QColor
+- 947 NETWORK_ERR during interaction QtWebKit window with server
+- 873 Deprecated methods could emit DeprecationWarning
+- 831 PySide docs would have a "Inherited by" list for each class
+
+1.0.5 (2011-07-22)
+==================
+
+Major changes
+-------------
+
+- Widgets present on "ui" files are exported in the root widget, check PySide ML thread for more information[1];
+- pyside-uic generate menubars without parent on MacOS plataform;
+- Signal connection optimizations;
+
+Bug fixes
+---------
+
+- 892 Segfault when destructing QWidget and QApplication has event filter installed
+- 407 Crash while multiple inheriting with QObject and native python class
+- 939 Shiboken::importModule must verify if PyImport_ImportModule succeeds
+- 937 missing pid method in QProcess
+- 927 Segfault on QThread code.
+- 925 Segfault when passing a QScriptValue as QObject or when using .toVariant() on a QScriptValue
+- 905 QtGui.QHBoxLayout.setMargin function call is created by pyside-uic, but this is not available in the pyside bindings
+- 904 Repeatedly opening a QDialog with Qt.WA_DeleteOnClose set crashes PySide
+- 899 Segfault with 'QVariantList' Property.
+- 893 Shiboken leak reference in the parent control
+- 878 Shiboken may generate incompatible modules if a new class is added.
+- 938 QTemporaryFile JPEG problem
+- 934 A __getitem__ of QByteArray behaves strange
+- 929 pkg-config files do not know about Python version tags
+- 926 qmlRegisterType does not work with QObject
+- 924 Allow QScriptValue to be accessed via []
+- 921 Signals not automatically disconnected on object destruction
+- 920 Cannot use same slot for two signals
+- 919 Default arguments on QStyle methods not working
+- 915 QDeclarativeView.scene().addItem(x) make the x object invalid
+- 913 Widgets inside QTabWidget are not exported as members of the containing widget
+- 910 installEventFilter() increments reference count on target object
+- 907 pyside-uic adds MainWindow.setMenuBar(self.menubar) to the generated code under OS X
+- 903 eventFilter in ItemDelegate
+- 897 QObject.property() and QObject.setProperty() methods fails for user-defined properties
+- 896 QObject.staticMetaObject() is missing
+- 916 Missing info about when is possible to use keyword arguments in docs [was: QListWidgetItem's constructor ignores text parameter]
+- 890 Add signal connection example for valueChanged(int) on QSpinBox to the docs
+- 821 Mapping interface for QPixmapCache
+- 909 Deletion of QMainWindow/QApplication leads to segmentation fault
+
+==========
+References
+==========
+
+- [1] http://qt.gitorious.org/pyside
+- [2] http://bugs.openbossa.org/
+- [3] http://www.pyside.org/docs/pseps/psep-0001.html
+- [4] http://developer.qt.nokia.com/wiki/PySideDownloads
diff --git a/popenasync.py b/popenasync.py
new file mode 100644
index 00000000..df4944ee
--- /dev/null
+++ b/popenasync.py
@@ -0,0 +1,311 @@
+################################################################################
+"""
+
+Modification of http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/440554
+
+"""
+
+#################################### IMPORTS ###################################
+
+import os
+import subprocess
+import errno
+import time
+import sys
+import unittest
+import tempfile
+
+def geterror ():
+ return sys.exc_info()[1]
+
+if sys.version_info >= (3,):
+ null_byte = '\x00'.encode('ascii')
+else:
+ null_byte = '\x00'
+
+if subprocess.mswindows:
+ if sys.version_info >= (3,):
+ # Test date should be in ascii.
+ def encode(s):
+ return s.encode('ascii')
+
+ def decode(b):
+ return b.decode('ascii')
+ else:
+ # Strings only; do nothing
+ def encode(s):
+ return s
+
+ def decode(b):
+ return b
+
+ try:
+ import ctypes
+ from ctypes.wintypes import DWORD
+ kernel32 = ctypes.windll.kernel32
+ TerminateProcess = ctypes.windll.kernel32.TerminateProcess
+ def WriteFile(handle, data, ol = None):
+ c_written = DWORD()
+ success = ctypes.windll.kernel32.WriteFile(handle, ctypes.create_string_buffer(encode(data)), len(data), ctypes.byref(c_written), ol)
+ return ctypes.windll.kernel32.GetLastError(), c_written.value
+ def ReadFile(handle, desired_bytes, ol = None):
+ c_read = DWORD()
+ buffer = ctypes.create_string_buffer(desired_bytes+1)
+ success = ctypes.windll.kernel32.ReadFile(handle, buffer, desired_bytes, ctypes.byref(c_read), ol)
+ buffer[c_read.value] = null_byte
+ return ctypes.windll.kernel32.GetLastError(), decode(buffer.value)
+ def PeekNamedPipe(handle, desired_bytes):
+ c_avail = DWORD()
+ c_message = DWORD()
+ if desired_bytes > 0:
+ c_read = DWORD()
+ buffer = ctypes.create_string_buffer(desired_bytes+1)
+ success = ctypes.windll.kernel32.PeekNamedPipe(handle, buffer, desired_bytes, ctypes.byref(c_read), ctypes.byref(c_avail), ctypes.byref(c_message))
+ buffer[c_read.value] = null_byte
+ return decode(buffer.value), c_avail.value, c_message.value
+ else:
+ success = ctypes.windll.kernel32.PeekNamedPipe(handle, None, desired_bytes, None, ctypes.byref(c_avail), ctypes.byref(c_message))
+ return "", c_avail.value, c_message.value
+
+ except ImportError:
+ from win32file import ReadFile, WriteFile
+ from win32pipe import PeekNamedPipe
+ from win32api import TerminateProcess
+ import msvcrt
+
+else:
+ from signal import SIGINT, SIGTERM, SIGKILL
+ import select
+ import fcntl
+
+################################### CONSTANTS ##################################
+
+PIPE = subprocess.PIPE
+
+################################################################################
+
+class Popen(subprocess.Popen):
+ def __init__(self, *args, **kwargs):
+ subprocess.Popen.__init__(self, *args, **kwargs)
+
+ def recv(self, maxsize=None):
+ return self._recv('stdout', maxsize)
+
+ def recv_err(self, maxsize=None):
+ return self._recv('stderr', maxsize)
+
+ def send_recv(self, input='', maxsize=None):
+ return self.send(input), self.recv(maxsize), self.recv_err(maxsize)
+
+ def read_async(self, wait=.1, e=1, tr=5, stderr=0):
+ if tr < 1:
+ tr = 1
+ x = time.time()+ wait
+ y = []
+ r = ''
+ pr = self.recv
+ if stderr:
+ pr = self.recv_err
+ while time.time() < x or r:
+ r = pr()
+ if r is None:
+ if e:
+ raise Exception("Other end disconnected!")
+ else:
+ break
+ elif r:
+ y.append(r)
+ else:
+ time.sleep(max((x-time.time())/tr, 0))
+ return ''.join(y)
+
+ def send_all(self, data):
+ while len(data):
+ sent = self.send(data)
+ if sent is None:
+ raise Exception("Other end disconnected!")
+ data = buffer(data, sent)
+
+ def get_conn_maxsize(self, which, maxsize):
+ if maxsize is None:
+ maxsize = 1024
+ elif maxsize < 1:
+ maxsize = 1
+ return getattr(self, which), maxsize
+
+ def _close(self, which):
+ conn = getattr(self, which)
+ flags = fcntl.fcntl(conn, fcntl.F_GETFL)
+ if not conn.closed:
+ fcntl.fcntl(conn, fcntl.F_SETFL, flags & ~os.O_NONBLOCK)
+ assert conn.read() == ''
+ getattr(self, which).close()
+ setattr(self, which, None)
+
+ if subprocess.mswindows:
+ def kill(self):
+ # Recipes
+ #http://me.in-berlin.de/doc/python/faq/windows.html#how-do-i-emulate-os-kill-in-windows
+ #http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/347462
+
+ """kill function for Win32"""
+ TerminateProcess(int(self._handle), 0) # returns None
+
+ def send(self, input):
+ if not self.stdin:
+ return None
+
+ try:
+ x = msvcrt.get_osfhandle(self.stdin.fileno())
+ (errCode, written) = WriteFile(x, input)
+ except ValueError:
+ return self._close('stdin')
+ except (subprocess.pywintypes.error, Exception):
+ if geterror()[0] in (109, errno.ESHUTDOWN):
+ return self._close('stdin')
+ raise
+
+ return written
+
+ def _recv(self, which, maxsize):
+ conn, maxsize = self.get_conn_maxsize(which, maxsize)
+ if conn is None:
+ return None
+
+ try:
+ x = msvcrt.get_osfhandle(conn.fileno())
+ (read, nAvail, nMessage) = PeekNamedPipe(x, 0)
+ if maxsize < nAvail:
+ nAvail = maxsize
+ if nAvail > 0:
+ (errCode, read) = ReadFile(x, nAvail, None)
+ except ValueError:
+ return self._close(which)
+ except (subprocess.pywintypes.error, Exception):
+ if geterror()[0] in (109, errno.ESHUTDOWN):
+ return self._close(which)
+ raise
+
+ if self.universal_newlines:
+ # Translate newlines. For Python 3.x assume read is text.
+ # If bytes then another solution is needed.
+ read = read.replace("\r\n", "\n").replace("\r", "\n")
+ return read
+
+ else:
+ def kill(self):
+ for i, sig in enumerate([SIGTERM, SIGKILL] * 2):
+ if i % 2 == 0: os.kill(self.pid, sig)
+ time.sleep((i * (i % 2) / 5.0) + 0.01)
+
+ killed_pid, stat = os.waitpid(self.pid, os.WNOHANG)
+ if killed_pid != 0: return
+
+ def send(self, input):
+ if not self.stdin:
+ return None
+
+ if not select.select([], [self.stdin], [], 0)[1]:
+ return 0
+
+ try:
+ written = os.write(self.stdin.fileno(), input)
+ except OSError:
+ if geterror()[0] == errno.EPIPE: #broken pipe
+ return self._close('stdin')
+ raise
+
+ return written
+
+ def _recv(self, which, maxsize):
+ conn, maxsize = self.get_conn_maxsize(which, maxsize)
+ if conn is None:
+ return None
+
+ flags = fcntl.fcntl(conn, fcntl.F_GETFL)
+ if not conn.closed:
+ fcntl.fcntl(conn, fcntl.F_SETFL, flags| os.O_NONBLOCK)
+
+ try:
+ if not select.select([conn], [], [], 0)[0]:
+ return ''
+
+ try:
+ r = conn.read(maxsize)
+ except IOError as e:
+ if e.errno == errno.EAGAIN:
+ return ''
+ raise
+ if not r:
+ return self._close(which)
+
+ if self.universal_newlines:
+ r = r.replace("\r\n", "\n").replace("\r", "\n")
+ return r
+ finally:
+ if not conn.closed:
+ fcntl.fcntl(conn, fcntl.F_SETFL, flags)
+
+################################################################################
+
+def proc_in_time_or_kill(cmd, time_out, wd = None, env = None):
+ proc = Popen (
+ cmd, cwd = wd, env = env,
+ stdin = subprocess.PIPE, stdout = subprocess.PIPE,
+ stderr = subprocess.STDOUT, universal_newlines = 1
+ )
+
+ ret_code = None
+ response = []
+
+ t = time.time()
+ while ret_code is None and ((time.time() -t) < time_out):
+ ret_code = proc.poll()
+ response += [proc.read_async(wait=0.1, e=0)]
+
+ if ret_code is None:
+ ret_code = '"Process timed out (time_out = %s secs) ' % time_out
+ try:
+ proc.kill()
+ ret_code += 'and was successfully terminated"'
+ except Exception:
+ ret_code += ('and termination failed (exception: %s)"' %
+ (geterror(),))
+
+ return ret_code, ''.join(response)
+
+################################################################################
+
+class AsyncTest(unittest.TestCase):
+ def test_proc_in_time_or_kill(self):
+ ret_code, response = proc_in_time_or_kill(
+ [sys.executable, '-c', 'while 1: pass'], time_out = 1
+ )
+
+ self.assert_( 'rocess timed out' in ret_code )
+ self.assert_( 'successfully terminated' in ret_code )
+
+################################################################################
+
+def _example():
+ if sys.platform == 'win32':
+ shell, commands, tail = ('cmd', ('echo "hello"', 'echo "HELLO WORLD"'), '\r\n')
+ else:
+ shell, commands, tail = ('sh', ('ls', 'echo HELLO WORLD'), '\n')
+
+ a = Popen(shell, stdin=PIPE, stdout=PIPE)
+ sys.stdout.write(a.read_async())
+ sys.stdout.write(" ")
+ for cmd in commands:
+ a.send_all(cmd + tail)
+ sys.stdout.write(a.read_async())
+ sys.stdout.write(" ")
+ a.send_all('exit' + tail)
+ print (a.read_async(e=0))
+ a.wait()
+
+################################################################################
+
+if __name__ == '__main__':
+ if 1: unittest.main()
+ else: _example()
diff --git a/pyside_postinstall.py b/pyside_postinstall.py
new file mode 100644
index 00000000..95d87513
--- /dev/null
+++ b/pyside_postinstall.py
@@ -0,0 +1,174 @@
+# Postinstall script for PySide
+#
+# Generates the qt.conf file
+#
+# This file is based on pywin32_postinstall.py file from pywin32 project
+
+import os, sys, traceback, shutil, fnmatch, stat
+
+try:
+ # When this script is run from inside the bdist_wininst installer,
+ # file_created() and directory_created() are additional builtin
+ # functions which write lines to Python23\pyside-install.log. This is
+ # a list of actions for the uninstaller, the format is inspired by what
+ # the Wise installer also creates.
+ file_created
+ is_bdist_wininst = True
+except NameError:
+ is_bdist_wininst = False # we know what it is not - but not what it is :)
+ def file_created(file):
+ pass
+
+def install():
+ if sys.platform == "win32":
+ install_win32()
+ else:
+ install_linux()
+
+def filter_match(name, patterns):
+ for pattern in patterns:
+ if pattern is None:
+ continue
+ if fnmatch.fnmatch(name, pattern):
+ return True
+ return False
+
+def set_exec(name):
+ mode = os.stat(name).st_mode
+ new_mode = mode
+ if new_mode & stat.S_IRUSR:
+ new_mode = new_mode | stat.S_IXUSR
+ if new_mode & stat.S_IRGRP:
+ new_mode = new_mode | stat.S_IXGRP
+ if new_mode & stat.S_IROTH:
+ new_mode = new_mode | stat.S_IXOTH
+ if (mode != new_mode):
+ print("Setting exec for '%s' (mode %o => %o)" % (name, mode, new_mode))
+ os.chmod(name, new_mode)
+
+def install_linux():
+ # Try to find PySide package
+ try:
+ import PySide
+ except ImportError:
+ print("The PySide package not found: %s" % traceback.print_exception(*sys.exc_info()))
+ return
+ pyside_path = os.path.abspath(os.path.dirname(PySide.__file__))
+ print("PySide package found in %s..." % pyside_path)
+
+ # Set exec mode on executables
+ for elf in ["patchelf", "shiboken"]:
+ elfpath = os.path.join(pyside_path, elf)
+ set_exec(elfpath)
+
+ # Update rpath in PySide libs
+ from distutils.spawn import spawn
+ patchelf_path = os.path.join(pyside_path, "patchelf")
+ for srcname in os.listdir(pyside_path):
+ if os.path.isdir(srcname):
+ continue
+ if not filter_match(srcname, ["Qt*.so", "phonon.so", "shiboken"]):
+ continue
+ srcpath = os.path.join(pyside_path, srcname)
+ cmd = [
+ patchelf_path,
+ "--set-rpath",
+ pyside_path,
+ srcpath,
+ ]
+ spawn(cmd, search_path=0, verbose=1)
+ print("Patched rpath in %s to %s." % (srcpath, pyside_path))
+
+ # Check PySide installation status
+ try:
+ from PySide import QtCore
+ print("PySide package successfully installed in %s..." % \
+ os.path.abspath(os.path.dirname(QtCore.__file__)))
+ except ImportError:
+ print("The PySide package not installed: %s" % traceback.print_exception(*sys.exc_info()))
+
+def install_win32():
+ # Try to find PySide package
+ try:
+ from PySide import QtCore
+ except ImportError:
+ print("The PySide package not found: %s" % traceback.print_exception(*sys.exc_info()))
+ return
+ pyside_path = os.path.dirname(QtCore.__file__)
+ pyside_path = pyside_path.replace("\\", "/")
+ pyside_path = pyside_path.replace("lib/site-packages", "Lib/site-packages")
+ print("PySide package found in %s..." % pyside_path)
+
+ if is_bdist_wininst:
+ # Run from inside the bdist_wininst installer
+ import distutils.sysconfig
+ exec_prefix = distutils.sysconfig.get_config_var("exec_prefix")
+ else:
+ # Run manually
+ exec_prefix = os.path.dirname(sys.executable)
+
+ # Generate qt.conf
+ qtconf_path = os.path.join(exec_prefix, "qt.conf")
+ print("Generating file %s..." % qtconf_path)
+ f = open(qtconf_path, 'wt')
+ file_created(qtconf_path)
+ f.write("""[Paths]
+Prefix = %(pyside_prefix)s
+Binaries = %(pyside_prefix)s
+Plugins = %(pyside_prefix)s/plugins
+Translations = %(pyside_prefix)s/translations
+""" % { "pyside_prefix": pyside_path })
+ print("The PySide extensions were successfully installed.")
+
+ # Install OpenSSL libs
+ for dll in ["libeay32.dll", "ssleay32.dll"]:
+ dest_path = os.path.join(exec_prefix, dll)
+ src_path = os.path.join(pyside_path, dll)
+ if not os.path.exists(dest_path) and os.path.exists(src_path):
+ shutil.copy(src_path, dest_path)
+ file_created(dest_path)
+ print("Installed %s to %s." % (dll, exec_prefix))
+
+def uninstall():
+ print("The PySide extensions were successfully uninstalled.")
+
+def usage():
+ msg = \
+"""%s: A post-install script for the PySide extensions.
+
+This should be run automatically after installation, but if it fails you
+can run it again with a '-install' parameter, to ensure the environment
+is setup correctly.
+"""
+ print(msg.strip() % os.path.basename(sys.argv[0]))
+
+# NOTE: If this script is run from inside the bdist_wininst created
+# binary installer or uninstaller, the command line args are either
+# '-install' or '-remove'.
+
+# Important: From inside the binary installer this script MUST NOT
+# call sys.exit() or raise SystemExit, otherwise not only this script
+# but also the installer will terminate! (Is there a way to prevent
+# this from the bdist_wininst C code?)
+
+if __name__ == '__main__':
+ if len(sys.argv)==1:
+ usage()
+ sys.exit(1)
+
+ arg_index = 1
+ while arg_index < len(sys.argv):
+ arg = sys.argv[arg_index]
+ if arg == "-install":
+ install()
+ elif arg == "-remove":
+ # bdist_msi calls us before uninstall, so we can undo what we
+ # previously did. Sadly, bdist_wininst calls us *after*, so
+ # we can't do much at all.
+ if not is_bdist_wininst:
+ uninstall()
+ else:
+ print("Unknown option: %s" % arg)
+ usage()
+ sys.exit(0)
+ arg_index += 1
diff --git a/qtinfo.py b/qtinfo.py
new file mode 100644
index 00000000..1369bff6
--- /dev/null
+++ b/qtinfo.py
@@ -0,0 +1,51 @@
+import subprocess
+from distutils.spawn import find_executable
+from popenasync import Popen
+
+class QtInfo(object):
+ def __init__(self, qmake_path=None):
+ if qmake_path:
+ self._qmake_path = qmake_path
+ else:
+ self._qmake_path = find_executable("qmake")
+
+ def getQMakePath(self):
+ return self._qmake_path
+
+ def getVersion(self):
+ return self.getProperty("QT_VERSION")
+
+ def getBinsPath(self):
+ return self.getProperty("QT_INSTALL_BINS")
+
+ def getPluginsPath(self):
+ return self.getProperty("QT_INSTALL_PLUGINS")
+
+ def getImportsPath(self):
+ return self.getProperty("QT_INSTALL_IMPORTS")
+
+ def getTranslationsPath(self):
+ return self.getProperty("QT_INSTALL_TRANSLATIONS")
+
+ def getProperty(self, prop_name):
+ cmd = [self._qmake_path, "-query", prop_name]
+ proc = Popen(cmd,
+ stdin = subprocess.PIPE,
+ stdout = subprocess.PIPE,
+ stderr = subprocess.STDOUT,
+ universal_newlines = 1,
+ shell=False)
+ prop = ''
+ while proc.poll() is None:
+ prop += proc.read_async(wait=0.1, e=0)
+ proc.wait()
+ if proc.returncode != 0:
+ return None
+ return prop.strip()
+
+ version = property(getVersion)
+ bins_dir = property(getBinsPath)
+ plugins_dir = property(getPluginsPath)
+ qmake_path = property(getQMakePath)
+ imports_dir = property(getImportsPath)
+ translations_dir = property(getTranslationsPath)
diff --git a/setup.py b/setup.py
new file mode 100644
index 00000000..94d74fb3
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,609 @@
+"""This is a distutils setup-script for the PySide project
+
+To build the PySide, simply execute:
+ python setup.py build --qmake=</path/to/qt/bin/qmake> [--cmake=</path/to/cmake>] [--opnessl=</path/to/openssl/bin>]
+or
+ python setup.py install --qmake=</path/to/qt/bin/qmake> [--cmake=</path/to/cmake>] [--opnessl=</path/to/openssl/bin>]
+to build and install into your current Python installation.
+
+You can use special option --only-package, if you want to create more binary packages (bdist_egg, bdist_wininst, ...)
+without rebuilding entire PySide every time.
+
+Examples:
+ # First time we create bdist_winist with full PySide build
+ python setup.py bdist_winist --qmake=c:\Qt\4.7.4\bin\qmake.exe --cmake=c:\tools\cmake\bin\cmake.exe --opnessl=c:\libs\OpenSSL32bit\bin
+
+ # Then we crate bdist_egg reusing PySide build with option --only-package
+ python setup.py bdist_egg --only-package --qmake=c:\Qt\4.7.4\bin\qmake.exe --cmake=c:\tools\cmake\bin\cmake.exe --opnessl=c:\libs\OpenSSL32bit\bin
+
+REQUIREMENTS:
+- Python: 2.6, 2.7 and 3.2 is supported
+- Distribute: http://pypi.python.org/pypi/distribute
+- Cmake: Specify the path to cmake with --cmake option or add cmake to the system path.
+
+OPTIONAL:
+OpenSSL: You can specify the location of OpenSSL DLLs with option --opnessl=</path/to/openssl/bin>.
+ You can download OpenSSL for windows here: http://slproweb.com/products/Win32OpenSSL.html
+
+NOTES:
+On Windows You need to execute this script from Visual Studio 2008 Command Prompt.
+Building 64bit version is not supported with Visual Studio 2008 Express Edition.
+"""
+
+__version__ = "1.1.1"
+
+import os
+import sys
+import platform
+
+from distutils import log
+from distutils.errors import DistutilsOptionError
+from distutils.errors import DistutilsSetupError
+from distutils.sysconfig import get_config_var
+from distutils.spawn import find_executable
+from distutils.command.build import build as _build
+
+from setuptools import setup
+from setuptools import find_packages
+from setuptools.command.install import install as _install
+from setuptools.command.bdist_egg import bdist_egg as _bdist_egg
+
+from qtinfo import QtInfo
+from utils import rmtree
+from utils import makefile
+from utils import copyfile
+from utils import copydir
+from utils import run_process
+
+# Change the cwd to our source dir
+try:
+ this_file = __file__
+except NameError:
+ this_file = sys.argv[0]
+this_file = os.path.abspath(this_file)
+if os.path.dirname(this_file):
+ os.chdir(os.path.dirname(this_file))
+
+# Clean temp build folders
+script_dir = os.getcwd()
+for n in ["build", "PySide.egg-info", "PySide-%s" % __version__,
+ "PySide", "pysideuic"]:
+ d = os.path.join(script_dir, n)
+ if os.path.isdir(d):
+ print("Removing %s" % d)
+ rmtree(d)
+
+# Create empty package folders
+for pkg in ["PySide", "pysideuic"]:
+ pkg_dir = os.path.join(script_dir, pkg)
+ os.makedirs(pkg_dir)
+
+def has_option(name):
+ try:
+ sys.argv.remove('--%s' % name)
+ return True
+ except ValueError:
+ pass
+ # allow passing all cmd line options also as environment variables
+ env_val = os.getenv(name.upper().replace('-', '_'), 'false').lower()
+ if env_val == "true":
+ return True
+ return False
+
+def option_value(name):
+ for index, option in enumerate(sys.argv):
+ if option == '--' + name:
+ if index+1 >= len(sys.argv):
+ raise DistutilsOptionError(
+ 'The option %s requires a value' % option)
+ value = sys.argv[index+1]
+ sys.argv[index:index+2] = []
+ return value
+ if option.startswith('--' + name + '='):
+ value = option[len(name)+3:]
+ sys.argv[index:index+1] = []
+ return value
+ env_val = os.getenv(name.upper().replace('-', '_'))
+ return env_val
+
+OPTION_DEBUG = has_option("debug")
+OPTION_QMAKE = option_value("qmake")
+OPTION_CMAKE = option_value("cmake")
+OPTION_OPENSSL = option_value("openssl")
+OPTION_ONLYPACKAGE = has_option("only-package")
+
+if OPTION_QMAKE is None:
+ OPTION_QMAKE = find_executable("qmake")
+if OPTION_CMAKE is None:
+ OPTION_CMAKE = find_executable("cmake")
+
+class pyside_install(_install):
+ def run(self):
+ _install.run(self)
+ # Custom script we run at the end of installing - this is the same script
+ # run by bdist_wininst
+ # If self.root has a value, it means we are being "installed" into
+ # some other directory than Python itself (eg, into a temp directory
+ # for bdist_wininst to use) - in which case we must *not* run our
+ # installer
+ if not self.dry_run and not self.root:
+ if sys.platform == "win32":
+ filename = os.path.join(self.prefix, "Scripts", "pyside_postinstall.py")
+ else:
+ filename = os.path.join(self.prefix, "bin", "pyside_postinstall.py")
+ if not os.path.isfile(filename):
+ raise RuntimeError("Can't find '%s'" % (filename,))
+ print("Executing post install script '%s'..." % filename)
+ cmd = [
+ os.path.abspath(sys.executable),
+ filename,
+ "-install"
+ ]
+ run_process(cmd)
+
+class pyside_bdist_egg(_bdist_egg):
+
+ def __init__(self, *args, **kwargs):
+ _bdist_egg.__init__(self, *args, **kwargs)
+
+ def run(self):
+ self.run_command("build")
+ _bdist_egg.run(self)
+
+class pyside_build(_build):
+
+ def __init__(self, *args, **kwargs):
+ _build.__init__(self, *args, **kwargs)
+
+ def initialize_options(self):
+ _build.initialize_options(self)
+ self.debug = False
+ self.script_dir = None
+ self.sources_dir = None
+ self.build_dir = None
+ self.install_dir = None
+ self.qmake_path = None
+ self.py_executable = None
+ self.py_include_dir = None
+ self.py_library = None
+ self.py_version = None
+ self.build_type = "Release"
+ self.qtinfo = None
+
+ def run(self):
+ # Check env
+ if not OPTION_ONLYPACKAGE:
+ make_name = sys.platform == "win32" and "nmake" or "make"
+ make_path = find_executable(make_name)
+ if make_path is None or not os.path.exists(make_path):
+ raise DistutilsSetupError(
+ "You need the program \"%s\" on your system path to compile PySide." \
+ % make_name)
+
+ if OPTION_CMAKE is None or not os.path.exists(OPTION_CMAKE):
+ raise DistutilsSetupError(
+ "Failed to find cmake."
+ " Please specify the path to cmake with --cmake parameter.")
+
+ if OPTION_QMAKE is None or not os.path.exists(OPTION_QMAKE):
+ raise DistutilsSetupError(
+ "Failed to find qmake."
+ " Please specify the path to qmake with --qmake parameter.")
+
+ # Prepare parameters
+ build_type = OPTION_DEBUG and "Debug" or "Release"
+
+ py_version = "%s.%s" % (sys.version_info[0], sys.version_info[1])
+ py_include_dir = get_config_var("INCLUDEPY")
+ py_libdir = get_config_var("LIBDIR")
+ py_executable = sys.executable
+ dbgPostfix = ""
+ if build_type == "Debug":
+ dbgPostfix = "_d"
+ py_executable = py_executable[:-4] + "_d.exe"
+ if sys.platform == "win32":
+ py_library = os.path.join(py_libdir, "python%s%s.lib" % \
+ (py_version.replace(".", ""), dbgPostfix))
+ else:
+ py_library = os.path.join(py_libdir, "libpython%s%s.so" % \
+ (py_version, dbgPostfix))
+ if not os.path.exists(py_library):
+ raise DistutilsSetupError(
+ "Failed to locate the Python library %s" % py_library)
+
+ qtinfo = QtInfo(OPTION_QMAKE)
+
+ # Update os.path
+ paths = os.environ['PATH'].lower().split(os.pathsep)
+ def updatepath(path):
+ if not path.lower() in paths:
+ log.info("Adding path \"%s\" to environment" % path)
+ paths.append(path)
+ qt_dir = os.path.dirname(OPTION_QMAKE)
+ updatepath(qt_dir)
+ os.environ['PATH'] = os.pathsep.join(paths)
+
+ qt_version = qtinfo.version
+ if not qt_version:
+ log.error("Failed to query the Qt version with qmake %s" % qtinfo.qmake_path)
+ sys.exit(1)
+
+ build_name = "py%s-qt%s-%s-%s" % \
+ (py_version, qt_version, platform.architecture()[0], build_type.lower())
+
+ script_dir = os.getcwd()
+ sources_dir = os.path.join(script_dir, "sources")
+ build_dir = os.path.join(script_dir, os.path.join("pyside_build", "%s" % build_name))
+ install_dir = os.path.join(script_dir, os.path.join("pyside_install", "%s" % build_name))
+
+ self.debug = OPTION_DEBUG
+ self.script_dir = script_dir
+ self.sources_dir = sources_dir
+ self.build_dir = build_dir
+ self.install_dir = install_dir
+ self.qmake_path = OPTION_QMAKE
+ self.py_executable = py_executable
+ self.py_include_dir = py_include_dir
+ self.py_library = py_library
+ self.py_version = py_version
+ self.build_type = build_type
+ self.qtinfo = qtinfo
+
+ log.info("=" * 30)
+ log.info("Build type: %s" % self.build_type)
+ log.info("Package version: %s" % __version__)
+ log.info("-" * 3)
+ log.info("Script directory: %s" % self.script_dir)
+ log.info("Sources directory: %s" % self.sources_dir)
+ log.info("Build directory: %s" % self.build_dir)
+ log.info("Install directory: %s" % self.install_dir)
+ log.info("-" * 3)
+ log.info("Python executable: %s" % self.py_executable)
+ log.info("Python includes: %s" % self.py_include_dir)
+ log.info("Python library: %s" % self.py_library)
+ log.info("-" * 3)
+ log.info("Qt qmake: %s" % self.qmake_path)
+ log.info("Qt bins: %s" % qtinfo.bins_dir)
+ log.info("Qt plugins: %s" % qtinfo.plugins_dir)
+ log.info("-" * 3)
+ log.info("OpenSSL libs: %s" % OPTION_OPENSSL)
+ log.info("=" * 30)
+
+ # Prepare folders
+ if not os.path.exists(self.sources_dir):
+ log.info("Creating sources folder %s..." % self.sources_dir)
+ os.makedirs(self.sources_dir)
+ if not os.path.exists(self.build_dir):
+ log.info("Creating build folder %s..." % self.build_dir)
+ os.makedirs(self.build_dir)
+ if not os.path.exists(self.install_dir):
+ log.info("Creating install folder %s..." % self.install_dir)
+ os.makedirs(self.install_dir)
+
+ if not OPTION_ONLYPACKAGE:
+ # Build extensions
+ for ext in ['shiboken', 'pyside', 'pyside-tools']:
+ self.build_extension(ext)
+
+ # Build patchelf
+ self.build_patchelf()
+
+ # Prepare packages
+ self.prepare_packages()
+
+ # Build packages
+ _build.run(self)
+
+ def build_patchelf(self):
+ if sys.platform != "linux2":
+ return
+
+ log.info("Building patchelf...")
+
+ module_src_dir = os.path.join(self.sources_dir, "patchelf")
+
+ build_cmd = [
+ "g++",
+ "%s/patchelf.cc" % (module_src_dir),
+ "-o",
+ "patchelf",
+ ]
+
+ if run_process(build_cmd, log) != 0:
+ raise DistutilsSetupError("Error building patchelf")
+
+ def build_extension(self, extension):
+ log.info("Building module %s..." % extension)
+
+ # Prepare folders
+ os.chdir(self.build_dir)
+ module_build_dir = os.path.join(self.build_dir, extension)
+ if os.path.exists(module_build_dir):
+ log.info("Deleting module build folder %s..." % module_build_dir)
+ rmtree(module_build_dir)
+ log.info("Creating module build folder %s..." % module_build_dir)
+ os.mkdir(module_build_dir)
+ os.chdir(module_build_dir)
+
+ module_src_dir = os.path.join(self.sources_dir, extension)
+
+ # Build module
+ if sys.platform == "win32":
+ cmake_generator = "NMake Makefiles"
+ make_cmd = "nmake"
+ else:
+ cmake_generator = "Unix Makefiles"
+ make_cmd = "make"
+ cmake_cmd = [
+ "cmake",
+ "-G", cmake_generator,
+ "-DQT_QMAKE_EXECUTABLE=%s" % self.qmake_path,
+ "-DBUILD_TESTS=False",
+ "-DDISABLE_DOCSTRINGS=True",
+ "-DCMAKE_BUILD_TYPE=%s" % self.build_type,
+ "-DCMAKE_INSTALL_PREFIX=%s" % self.install_dir,
+ module_src_dir
+ ]
+ if sys.version_info[0] > 2:
+ cmake_cmd.append("-DPYTHON3_EXECUTABLE=%s" % self.py_executable)
+ cmake_cmd.append("-DPYTHON3_INCLUDE_DIR=%s" % self.py_include_dir)
+ cmake_cmd.append("-DPYTHON3_LIBRARY=%s" % self.py_library)
+ if self.build_type.lower() == 'debug':
+ cmake_cmd.append("-DPYTHON3_DBG_EXECUTABLE=%s" % self.py_executable)
+ cmake_cmd.append("-DPYTHON3_DEBUG_LIBRARY=%s" % self.py_library)
+ else:
+ cmake_cmd.append("-DPYTHON_EXECUTABLE=%s" % self.py_executable)
+ cmake_cmd.append("-DPYTHON_INCLUDE_DIR=%s" % self.py_include_dir)
+ cmake_cmd.append("-DPYTHON_LIBRARIES=%s" % self.py_library)
+ if self.build_type.lower() == 'debug':
+ cmake_cmd.append("-DPYTHON_DEBUG_LIBRARY=%s" % self.py_library)
+ if extension.lower() == "shiboken":
+ cmake_cmd.append("-DCMAKE_INSTALL_RPATH_USE_LINK_PATH=yes")
+ if sys.version_info[0] > 2:
+ cmake_cmd.append("-DUSE_PYTHON3=ON")
+
+ log.info("Configuring module %s (%s)..." % (extension, module_src_dir))
+ if run_process(cmake_cmd, log) != 0:
+ raise DistutilsSetupError("Error configuring " + extension)
+
+ log.info("Compiling module %s..." % extension)
+ if run_process(make_cmd, log) != 0:
+ raise DistutilsSetupError("Error compiling " + extension)
+
+ log.info("Installing module %s..." % extension)
+ if run_process([make_cmd, "install/fast"], log) != 0:
+ raise DistutilsSetupError("Error pseudo installing " + extension)
+
+ os.chdir(self.script_dir)
+
+ def prepare_packages(self):
+ log.info("Preparing packages...")
+ version_str = "%sqt%s%s" % (__version__, self.qtinfo.version.replace(".", "")[0:3],
+ self.debug and "dbg" or "")
+ vars = {
+ "sources_dir": self.sources_dir,
+ "install_dir": self.install_dir,
+ "build_dir": self.build_dir,
+ "setup_dir": self.script_dir,
+ "ssl_libs_dir": OPTION_OPENSSL,
+ "py_version": self.py_version,
+ "qt_bin_dir": self.qtinfo.bins_dir,
+ "qt_plugins_dir": self.qtinfo.plugins_dir,
+ "qt_imports_dir": self.qtinfo.imports_dir,
+ "qt_translations_dir": self.qtinfo.translations_dir,
+ "version": version_str,
+ }
+ os.chdir(self.script_dir)
+ if sys.platform == "win32":
+ return self.prepare_packages_win32(vars)
+ return self.prepare_packages_linux(vars)
+
+ def prepare_packages_linux(self, vars):
+ # patchelf -> PySide/patchelf
+ copyfile(
+ "${setup_dir}/patchelf",
+ "${setup_dir}/PySide/patchelf",
+ logger=log, vars=vars)
+ # <install>/lib/site-packages/PySide/* -> <setup>/PySide
+ copydir(
+ "${install_dir}/lib/python${py_version}/site-packages/PySide",
+ "${setup_dir}/PySide",
+ logger=log, vars=vars)
+ # <install>/lib/site-packages/pysideuic/* -> <setup>/pysideuic
+ copydir(
+ "${install_dir}/lib/python${py_version}/site-packages/pysideuic",
+ "${setup_dir}/pysideuic",
+ force=False, logger=log, vars=vars)
+ # <install>/bin/pyside-uic -> PySide/scripts/uic.py
+ makefile(
+ "${setup_dir}/PySide/scripts/__init__.py",
+ logger=log, vars=vars)
+ copyfile(
+ "${install_dir}/bin/pyside-uic",
+ "${setup_dir}/PySide/scripts/uic.py",
+ force=False, logger=log, vars=vars)
+ # <install>/bin/* -> PySide/
+ copydir(
+ "${install_dir}/bin/",
+ "${setup_dir}/PySide",
+ filter=[
+ "pyside-lupdate",
+ "pyside-rcc",
+ "shiboken",
+ ],
+ recursive=False, logger=log, vars=vars)
+ # <install>/lib/lib* -> PySide/
+ copydir(
+ "${install_dir}/lib/",
+ "${setup_dir}/PySide",
+ filter=[
+ "libpyside*",
+ "libshiboken*",
+ ],
+ recursive=False, logger=log, vars=vars)
+ # <install>/share/PySide/typesystems/* -> <setup>/PySide/typesystems
+ copydir(
+ "${install_dir}/share/PySide/typesystems",
+ "${setup_dir}/PySide/typesystems",
+ logger=log, vars=vars)
+ # <install>/include/* -> <setup>/PySide/include
+ copydir(
+ "${install_dir}/include",
+ "${setup_dir}/PySide/include",
+ logger=log, vars=vars)
+ # <sources>/pyside-examples/examples/* -> <setup>/PySide/examples
+ copydir(
+ "${sources_dir}/pyside-examples/examples",
+ "${setup_dir}/PySide/examples",
+ force=False, logger=log, vars=vars)
+
+ def prepare_packages_win32(self, vars):
+ # <install>/lib/site-packages/PySide/* -> <setup>/PySide
+ copydir(
+ "${install_dir}/lib/site-packages/PySide",
+ "${setup_dir}/PySide",
+ logger=log, vars=vars)
+ if self.debug:
+ # <build>/pyside/PySide/*.pdb -> <setup>/PySide
+ copydir(
+ "${build_dir}/pyside/PySide",
+ "${setup_dir}/PySide",
+ filter=["*.pdb"],
+ recursive=False, logger=log, vars=vars)
+ # <install>/lib/site-packages/pysideuic/* -> <setup>/pysideuic
+ copydir(
+ "${install_dir}/lib/site-packages/pysideuic",
+ "${setup_dir}/pysideuic",
+ force=False, logger=log, vars=vars)
+ # <install>/bin/pyside-uic -> PySide/scripts/uic.py
+ makefile(
+ "${setup_dir}/PySide/scripts/__init__.py",
+ logger=log, vars=vars)
+ copyfile(
+ "${install_dir}/bin/pyside-uic",
+ "${setup_dir}/PySide/scripts/uic.py",
+ force=False, logger=log, vars=vars)
+ # <install>/bin/*.exe,*.dll -> PySide/
+ copydir(
+ "${install_dir}/bin/",
+ "${setup_dir}/PySide",
+ filter=["*.exe", "*.dll"],
+ recursive=False, logger=log, vars=vars)
+ # <install>/lib/*.lib -> PySide/
+ copydir(
+ "${install_dir}/lib/",
+ "${setup_dir}/PySide",
+ filter=["*.lib"],
+ recursive=False, logger=log, vars=vars)
+ # <install>/share/PySide/typesystems/* -> <setup>/PySide/typesystems
+ copydir(
+ "${install_dir}/share/PySide/typesystems",
+ "${setup_dir}/PySide/typesystems",
+ logger=log, vars=vars)
+ # <install>/include/* -> <setup>/PySide/include
+ copydir(
+ "${install_dir}/include",
+ "${setup_dir}/PySide/include",
+ logger=log, vars=vars)
+ # <ssl_libs>/* -> <setup>/PySide/
+ copydir("${ssl_libs_dir}", "${setup_dir}/PySide",
+ filter=[
+ "libeay32.dll",
+ "ssleay32.dll"],
+ force=False, logger=log, vars=vars)
+ # <qt>/bin/*.dll -> <setup>/PySide
+ copydir("${qt_bin_dir}", "${setup_dir}/PySide",
+ filter=[
+ "*.dll",
+ "designer.exe",
+ "linguist.exe",
+ "lrelease.exe",
+ "lupdate.exe",
+ "lconvert.exe"],
+ ignore=["*d4.dll"],
+ recursive=False, logger=log, vars=vars)
+ if self.debug:
+ # <qt>/bin/*d4.dll -> <setup>/PySide
+ copydir("${qt_bin_dir}", "${setup_dir}/PySide",
+ filter=["*d4.dll"],
+ recursive=False, logger=log, vars=vars)
+ # <qt>/plugins/* -> <setup>/PySide/plugins
+ copydir("${qt_plugins_dir}", "${setup_dir}/PySide/plugins",
+ filter=["*.dll"],
+ logger=log, vars=vars)
+ # <qt>/imports/* -> <setup>/PySide/imports
+ copydir("${qt_imports_dir}", "${setup_dir}/PySide/imports",
+ filter=["qmldir", "*.dll"],
+ logger=log, vars=vars)
+ # <qt>/translations/* -> <setup>/PySide/translations
+ copydir("${qt_translations_dir}", "${setup_dir}/PySide/translations",
+ filter=["*.ts"],
+ logger=log, vars=vars)
+ # <sources>/pyside-examples/examples/* -> <setup>/PySide/examples
+ copydir(
+ "${sources_dir}/pyside-examples/examples",
+ "${setup_dir}/PySide/examples",
+ force=False, logger=log, vars=vars)
+
+def read(fname):
+ return open(os.path.join(os.path.dirname(__file__), fname)).read()
+
+setup(
+ name = "PySide",
+ version = __version__,
+ description = ("Python bindings for the Qt cross-platform application and UI framework"),
+ long_description = read('README.txt'),
+ options = {
+ "bdist_wininst": {
+ "install_script": "pyside_postinstall.py",
+ },
+ "bdist_msi": {
+ "install_script": "pyside_postinstall.py",
+ },
+ },
+ scripts = [
+ "pyside_postinstall.py"
+ ],
+ classifiers = [
+ 'Development Status :: 5 - Production/Stable',
+ 'Environment :: Console',
+ 'Environment :: MacOS X',
+ 'Environment :: X11 Applications :: Qt',
+ 'Intended Audience :: Developers',
+ 'License :: OSI Approved :: GNU Library or Lesser General Public License (LGPL)',
+ 'Operating System :: MacOS :: MacOS X',
+ 'Operating System :: POSIX',
+ 'Operating System :: POSIX :: Linux',
+ 'Programming Language :: C++',
+ 'Programming Language :: Python',
+ 'Programming Language :: Python :: 2',
+ 'Programming Language :: Python :: 2.6',
+ 'Programming Language :: Python :: 2.7',
+ 'Programming Language :: Python :: 3',
+ 'Programming Language :: Python :: 3.2',
+ 'Topic :: Database',
+ 'Topic :: Software Development',
+ 'Topic :: Software Development :: Code Generators',
+ 'Topic :: Software Development :: Libraries :: Application Frameworks',
+ 'Topic :: Software Development :: User Interfaces',
+ 'Topic :: Software Development :: Widget Sets',
+ ],
+ keywords = 'Qt',
+ author = 'PySide Team',
+ author_email = 'contact@pyside.org',
+ url = 'http://www.pyside.org',
+ license = 'LGPL',
+ packages = ['PySide', 'pysideuic'],
+ include_package_data = True,
+ zip_safe = False,
+ entry_points = {
+ 'console_scripts': [
+ 'pyside-uic = PySide.scripts.uic:main',
+ ]
+ },
+ cmdclass = {
+ 'build': pyside_build,
+ 'bdist_egg': pyside_bdist_egg,
+ 'install': pyside_install,
+ },
+)
diff --git a/sources/pyside b/sources/pyside
new file mode 160000
+Subproject ee95e881929b3b51e535ad9024025cc7ac91d57
diff --git a/sources/pyside-examples b/sources/pyside-examples
new file mode 160000
+Subproject 060dca8e4b82f301dfb33a7182767eaf8ad3d02
diff --git a/sources/pyside-tools b/sources/pyside-tools
new file mode 160000
+Subproject 92062bcf842814328a9f4a89f10c115bfcace0b
diff --git a/sources/shiboken b/sources/shiboken
new file mode 160000
+Subproject 54cce10fa8a9942450c9e1a9d9a9d2a1b688f24
diff --git a/utils.py b/utils.py
new file mode 100644
index 00000000..59cb50d4
--- /dev/null
+++ b/utils.py
@@ -0,0 +1,177 @@
+import sys
+import os
+import stat
+import errno
+import time
+import shutil
+import subprocess
+import popenasync
+import fnmatch
+
+
+def filter_match(name, patterns):
+ for pattern in patterns:
+ if pattern is None:
+ continue
+ if fnmatch.fnmatch(name, pattern):
+ return True
+ return False
+
+
+def subst_vars(input, **vars):
+ if vars is not None:
+ for key in vars:
+ input = input.replace("${%s}" % key, str(vars[key]))
+ return input
+
+
+def copyfile(src, dst, logger=None, force=True, vars=None, subst_content=False):
+ if vars is not None:
+ src = subst_vars(src, **vars)
+ dst = subst_vars(dst, **vars)
+
+ if not os.path.exists(src) and not force:
+ if logger is not None:
+ logger.info("**Skiping copy file %s to %s. Source does not exists." % (src, dst))
+ return
+
+ if logger is not None:
+ logger.info("Copying file %s to %s." % (src, dst))
+
+ if vars is None or not subst_content:
+ shutil.copy2(src, dst)
+ return
+
+ print ("copyfile " + src)
+ f = open(src, "rt")
+ content = f.read()
+ f.close()
+ content = subst_vars(content, **vars)
+ f = open(dst, "wt")
+ f.write(content)
+ f.close()
+
+
+def makefile(dst, content=None, logger=None, vars=None):
+ if vars is not None:
+ if content is not None:
+ content = subst_vars(content, **vars)
+ dst = subst_vars(dst, **vars)
+
+ if logger is not None:
+ logger.info("Making file %s." % (dst))
+
+ dstdir = os.path.dirname(dst)
+ if not os.path.exists(dstdir):
+ os.makedirs(dstdir)
+
+ f = open(dst, "wt")
+ if content is not None:
+ f.write(content)
+ f.close()
+
+
+def copydir(src, dst, logger=None, filter=None, ignore=None, force=True,
+ recursive=True, vars=None, subst_files_content=False):
+
+ if vars is not None:
+ src = subst_vars(src, **vars)
+ dst = subst_vars(dst, **vars)
+
+ if not os.path.exists(src) and not force:
+ if logger is not None:
+ logger.info("**Skiping copy tree %s to %s. Source does not exists. filter=%s. ignore=%s." % \
+ (src, dst, filter, ignore))
+ return
+
+ if logger is not None:
+ logger.info("Copying tree %s to %s. filter=%s. ignore=%s." % \
+ (src, dst, filter, ignore))
+
+ names = os.listdir(src)
+
+ if not os.path.exists(dst):
+ os.makedirs(dst)
+
+ errors = []
+ for name in names:
+ srcname = os.path.join(src, name)
+ dstname = os.path.join(dst, name)
+ try:
+ if os.path.isdir(srcname):
+ if recursive:
+ copydir(srcname, dstname, logger, filter, ignore, force, recursive,
+ vars, subst_files_content)
+ else:
+ if (filter is not None and not filter_match(name, filter)) or \
+ (ignore is not None and filter_match(name, ignore)):
+ continue
+ copyfile(srcname, dstname, logger, True, vars, subst_files_content)
+ # catch the Error from the recursive copytree so that we can
+ # continue with other files
+ except shutil.Error as err:
+ errors.extend(err.args[0])
+ except EnvironmentError as why:
+ errors.append((srcname, dstname, str(why)))
+ try:
+ shutil.copystat(src, dst)
+ except OSError as why:
+ if WindowsError is not None and isinstance(why, WindowsError):
+ # Copying file access times may fail on Windows
+ pass
+ else:
+ errors.extend((src, dst, str(why)))
+ if errors:
+ raise EnvironmentError(errors)
+
+
+def rmtree(dirname):
+ def handleRemoveReadonly(func, path, exc):
+ excvalue = exc[1]
+ if func in (os.rmdir, os.remove) and excvalue.errno == errno.EACCES:
+ os.chmod(path, stat.S_IRWXU| stat.S_IRWXG| stat.S_IRWXO) # 0777
+ func(path)
+ else:
+ raise
+ shutil.rmtree(dirname, ignore_errors=False, onerror=handleRemoveReadonly)
+
+
+def run_process(args, logger=None):
+ def log(buffer, checkNewLine):
+ endsWithNewLine = False
+ if buffer.endswith('\n'):
+ endsWithNewLine = True
+ if checkNewLine and buffer.find('\n') == -1:
+ return buffer
+ lines = buffer.splitlines()
+ buffer = ''
+ if checkNewLine and not endsWithNewLine:
+ buffer = lines[-1]
+ lines = lines[:-1]
+ for line in lines:
+ if not logger is None:
+ logger.info(line.rstrip('\r'))
+ else:
+ print(line.rstrip('\r'))
+ return buffer
+
+ shell = False
+ if sys.platform == "win32":
+ shell = True
+
+ proc = popenasync.Popen(args,
+ stdin = subprocess.PIPE,
+ stdout = subprocess.PIPE,
+ stderr = subprocess.STDOUT,
+ universal_newlines = 1,
+ shell = shell,
+ env = os.environ)
+
+ log_buffer = None;
+ while proc.poll() is None:
+ log_buffer = log(proc.read_async(wait=0.1, e=0), False)
+ if log_buffer:
+ log(log_buffer, False)
+
+ proc.wait()
+ return proc.returncode