1
PSEP: 101
2
Title: Adopt PyQt's API 2 for PySide
3
Version: $Revision$
4
Last-Modified: $Date$
5
Author: Mark Summerfield <mark@qtrac.eu>
6
Status: Final
7
Type: Standards Track
8
Content-Type: text/x-rst
9
Created: 14-Apr-2010
10
Post-History: 14-Apr-2010, 15-Apr-2010, 16-Apr-2010, 20-Apr-2010, 22-Apr-2010, 18-May-2010
11
12
Abstract
13
========
14
15
PyQt4 provides two different (and incompatible) APIs. API 1 is the
16
original API and the one supported by PySide. API 2 is a new Python
17
3-specific API that is much more Pythonic. This PSEP proposes that
18
PySide adopt PyQt4's API 2 for PySide.
19
20
21
Rationale
22
=========
23
24
PyQt4 provides two different (and incompatbile) APIs [#PyQt-APIs]_. API
25
1 is useful for those using PyQt4 to prototype C++/Qt programs since
26
it is very close to the C++/Qt API. However, for those who want to create
27
Python Qt programs in their own right, and especially for existing Python
28
programmers, API 1 is cumbersome and un-Pythonic when it comes to handling
29
QStrings and QVariants, both of which are used a lot.
30
31
If PySide were to support API 2, it will make PySide much more attractive
32
to Python 3 programmers.
33
34
Also, supporting API 2 will mean that existing Python 3/PyQt4 programs that
35
use API 2 by default will be able to switch to PySide.
36
37
One key purpose of API 2 is to avoid the need for Python programmers to
38
have to worry or even know about QString or QVariant. For Python
39
programmers str is the string they are used to so translation to/from
40
QString should be transparent and automatic. Similarly, why should
41
Python programmers have to know about QVariant when that is a C++
42
workaround for C++'s lack of support for duck typing etc.? Again,
43
translation to/from QVariant should be transparent and automatic. API 2
44
achieves this and eliminates QString and (to some extent) QVariant.
45
46
47
API 1 vs. API 2
48
===============
49
50
51
No QString and almost no QVariant
52
---------------------------------
53
54
The key difference between the APIs is that API 2 does not make QString
55
or (to some extent) QVariant available to programmers.
56
57
This means using Python's native string types for strings (e.g., unicode
58
for Python 2 and str for Python 3).
59
60
PyQt's approach to dealing with QVariants will be mimicked: Python
61
objects are automatically converted to and from QVariants wherever
62
QVariants must be passed as arguments and when QVariants are returned.
63
64
By supporting automatic conversion to and from QVariants, any Python
65
object (including dicts, lists, and tuples) can be used wherever a
66
QVariant is expected, so most programmers most of the time won't have to
67
know or care about QVariant at all.
68
69
For QString, API 2 goes beyond simply replacing QString with str (or
70
unicode on Python 2). In particular, API 2 also automatically converts
71
QChar and QStringRef to and from strs (or unicodes on Python 2). It also
72
converts QStringList to and from a Python list of strs (list of unicodes
73
on Python 2). (PyQt4's API 2 does not implement QLatin1Char,
74
QLatin1String, or QStringMatcher.)
75
76
Native C++/Qt QStrings are mutable, so PyQt4's API 2 has changed the
77
signatures of some of the affected functions to return a str (or a tuple
78
including a str) when in the C++/Qt API a QString parameter would have been
79
modified.
80
81
In addition, API 2 has added two methods to QFontMetrics and QFontMetricsF,
82
widthChar() and boundingRectChar(), which take a str of length one and call
83
QFontMetrics::width() and QFontMetrics::boundingRect() with a QChar
84
argument. These were added because the width of a single character may be
85
different from that of a string that contains a single character, even if
86
the characters are the same.
87
88
If the need arises during the implementation phase, the QVariant class
89
may be added to the API so that programmers can pass a QVariant
90
explicitly if they need to. If this is done, to support the creation of
91
QVariants, a set of static functions named after the types in
92
QVariant.Type will need to be implemented, e.g.::
93
94
     QVariant.fromUInt(pythonObject) -> QVariant
95
     QVariant.fromInt(pythonObject) -> QVariant
96
97
The benefit of API 2 in this regard is that programmers never have to
98
explicitly convert between QString and str, so programmers never get
99
caught out accidentally trying to use a QString method on a str or vice
100
versa. For the Qt APIs that accept or return QVariants, API 2 allows
101
programmers to pass any Python object and when a QVariant is returned
102
from Qt it is automatically converted to its original Python type (with
103
an invalid QVariant mapped to None).
104
105
106
Changes to Other Types
107
----------------------
108
109
API 2 also affects some other types, as follows.
110
111
Where QByteArrays are expected, bytes objects can be used, but unlike
112
QString, QByteArray has been retained to ease porting from API 1, so in
113
API 2 byte sequences can be represented by QByteArray, bytes, and
114
bytearray objects.
115
116
QDate, QDateTime, QTime, and QUrl's __hash__() methods return a string
117
representation so that identical dates (and identical date/times or times
118
or URLs) will have identical hash values.
119
120
QTextStream's bin(), hex(), and oct() functions have been renamed bin_(),
121
hex_(), and oct_(), to avoid conflicting with Python's built-ins of the
122
same names.
123
124
125
Support for Keyword Arguments
126
=============================
127
128
PyQt 4.7 adds support for keyword arguments which is very convenient and
129
much more Pythonic.
130
131
This change represents an extension to the PyQt APIs that a compatible
132
PySide ought to implement.
133
134
One problem with this is that while changes to argument names don't affect
135
C++/Qt, they would break the Python API. Furthermore, since changing
136
argument names is harmless in C++/Qt, such changes do take place between Qt
137
versions. This means that for PySide, sensible names must be used in the
138
first place---and stuck to. Naturally, for PyQt compatibility, PySide ought
139
to use the same names as PyQt.
140
141
PyQt does not integrate Python and Qt's property systems, but it does allow
142
Qt properties to be set when an object is constructed using keyword
143
arguments (i.e., where the keyword is the name of a Qt property). The
144
same functionality will be implemented in PySide. Also,
145
PyQt provides the pyqtConfigure() method for all objects that have
146
Qt properties: this method can be called at any time and the object's Qt
147
properties set by passing it keyword arguments. However, since
148
essentially the same functionality is already provided by
149
QObject.setProperty() and .property() methods, pyqtConfigure() will not be
150
implemented as part of this PSEP.
151
152
Compatibility
153
=============
154
155
The proposed API 2 is incompatible with API 1, but since PySide is not
156
yet widely used and hasn't reached version 1.0.0, it seems reasonable to
157
break compatibility for the sake of getting PySide "right". Furthermore,
158
if API 2 is adopted it means that PySide programs will have the same API
159
whether Python 2 or Python 3 is used which will make it much easier for
160
those who start out with PySide and Python 2 and later on port to Python
161
3---something that isn't so easy with PyQt.
162
163
164
References
165
==========
166
167
.. [#PyQt-APIs] PyQt v4 Reference Manual: Potential Incompatibilities
168
   section, Selecting Incompatible APIs section, Support for Keyword
169
   Arguments section, and Support for Qt Properties section
170
   (http://www.riverbankcomputing.co.uk/static/Docs/PyQt4/pyqt4ref.html)
171
172
173
Contributors
174
============
175
176
Richard Dale and Detlev Offenbach pointed out that QByteArray had been
177
retained in API 2.
178
179
Richard Dale and Lauro Moura gave suggestions regarding QVariant.
180
181
Hugo Lima proposed choosing one of PyQt's alternative APIs and implementing
182
only that for both Python 2 and Python 3 PySide versions.
183
184
The section of Exceptions was dropped as a result of feedback from Matti
185
Airas; Matti also added to the discussion in numerous ways.
186
187
Detlev Offenbach also contributed to the discussion on Compatibility.
188
189
190
Copyright
191
=========
192
193
This document has been placed in the public domain.