Skip to content

Commit

Permalink
Remove QT_STRICT
Browse files Browse the repository at this point in the history
  • Loading branch information
mottosso committed Jan 24, 2017
1 parent 1ad7ecc commit 21dfae1
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 82 deletions.
65 changes: 28 additions & 37 deletions Qt.py
Original file line number Diff line number Diff line change
Expand Up @@ -355,8 +355,16 @@ def _cli(args):
raise ImportError("No Qt binding were found.")


# Members of Qt.py in Strict Mode.
# Find or add excluded members in build_membership.py
"""Members of Qt.py
This is where each member of Qt.py is explicitly defined.
It is based on a "lowest commond denominator" of all bindings;
including members found in each of the 4 bindings.
Find or add excluded members in build_membership.py
"""

_strict_members = {
"QtGui": [
"QAbstractTextDocumentLayout",
Expand Down Expand Up @@ -882,49 +890,32 @@ def _cli(args):
]
}

QtCompat.__version__ = "0.7.0"
QtCompat._cli = _cli
QtCompat._convert = _convert

QtCompat.__added__ = list() # DEPRECATED
QtCompat.__remapped__ = list() # DEPRECATED
QtCompat.__modified__ = list() # DEPRECATED
QtCompat.__wrapper_version__ = "0.7.0" # DEPRECATED

"""Augment QtCompat
def _strict():
"""Apply strict mode
This make Qt.py into a subset of PySide2 members that exist
across all other bindings.
"""

for module, members in _strict_members.items():
for member in members:
orig = getattr(sys.modules[__name__], "_%s" % module)
repl = getattr(sys.modules[__name__], module)
setattr(repl, member, getattr(orig, member))
QtCompat contains wrappers and added functionality
to the original bindings, such as the CLI interface
and otherwise incompatible members between bindings,
such as `QHeaderView.setSectionResizeMode`.
"""

def _loose():
"""Apply loose mode
QtCompat.__version__ = "1.0.0.b1"
QtCompat._cli = _cli
QtCompat._convert = _convert

This forwards attribute access to Qt.py submodules
onto the original binding.

"""
"""Apply strict mode
self = sys.modules[__name__]
self.QtWidgets = self._QtWidgets
self.QtGui = self._QtGui
self.QtCore = self._QtCore
self.QtNetwork = self._QtNetwork
self.QtHelp = self._QtHelp
self.QtXml = self._QtXml
This make Qt.py into a subset of PySide2 members that exist
across all other bindings.
"""

_strict() if QT_STRICT else _loose()
for module, members in _strict_members.items():
for member in members:
orig = getattr(sys.modules[__name__], "_%s" % module)
repl = getattr(sys.modules[__name__], module)
setattr(repl, member, getattr(orig, member))


# Enable direct import of submodules
Expand Down
56 changes: 12 additions & 44 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

### Qt.py

Qt.py enables you to write software that dynamically chooses the most desireable bindings based on what's available, including PySide2, PyQt5, PySide and PyQt4; in that (configurable) order (see below).
Qt.py enables you to write software that runs on any of the 4 supported bindings - PySide2, PyQt5, PySide and PyQt4.

**Guides**

Expand Down Expand Up @@ -31,15 +31,15 @@ Qt.py enables you to write software that dynamically chooses the most desireable

### Project goals

Write for PySide2, run in any binding.
Write once, run in any binding.

Qt.py was born in the film and visual effects industry to address the growing need for software capable of running with more than one flavor of the Qt bindings for Python - PySide, PySide2, PyQt4 and PyQt5.

| Goal | Description
|:-------------------------------------|:---------------
| *Support co-existence* | Qt.py should not affect other bindings running in same interpreter session.
| *Build for one, run with all* | Code written with Qt.py should run on any binding.
| *Explicit is better than implicit* | Differences between bindings should be visible to you.
| *Support co-existence* | Qt.py should not affect other bindings running in same interpreter session.
| *Build for one, run with all* | Code written with Qt.py should run on any binding.
| *Explicit is better than implicit* | Differences between bindings should be visible to you.

See [`CONTRIBUTING.md`](CONTRIBUTING.md) for more details.

Expand Down Expand Up @@ -117,20 +117,15 @@ These are the publicly facing environment variables that in one way or another a
| Variable | Type | Description
|:---------------------|:------|:----------
| QT_PREFFERED_BINDING | str | Override order and content of binding to try.
| QT_STRICT | bool | Enforce compatibility with other bindings.
| QT_VERBOSE | bool | Be a little more chatty when importing Qt
| QT_VERBOSE | bool | Be a little more chatty about what's going on with Qt.py

<br>

##### Strict Mode
##### Subset

Enforce compatibility with all bindings.
Members of Qt.py is a subset of PySide2. Which means for a member to be made accessible via Qt.py, it will need to (1) be accessible via PySide2 and (2) each of the other supported bindings. This excludes large portions of the Qt framework, including the newly added QtQml and QtQuick modules but guarantees that anything you develop with Qt.py will work identically on any binding - PySide, PySide2, PyQt4 and PyQt5.

Use this to ensure that your program will run identically on all bindings.

When enabling `QT_STRICT`, Qt.py becomes a subset of PySide2. All members are guaranteed to exist across all bindings, meaning many will be missing. Including QtQml and QtQuick modules.

Strict mode follows the [VFX Platform](http://www.vfxplatform.com/) to determine which version of PySide2 to use for reference. Currently version is 2.0.0.
The version of PySide2 used as reference is the one specified on [VFX Platform](http://www.vfxplatform.com/). Currently version is 2.0.0.

<br>

Expand Down Expand Up @@ -239,34 +234,6 @@ PyQt5.Slot = PyQt5.pyqtSlot
PySide2.QtCore.QStringListModel = PySide2.QtGui.QStringListModel
```

**Portability**

Qt.py has two modes - loose and strict.

Loose means Qt.py does not hide members from the original binding. This can be problematic if, for example, you accidentally use a member that only exists PyQt5 and later try running your software with a different binding.

```python
from Qt import QtCore

# Incompatible with PySide
signal = QtCore.pyqtSignal()
```

But it enables use of Qt.py as a helper library, in conjunction with an existing binding, simplifying the transition of an existing project from a particular binding.

```python
# This is ok
from Qt import QtCore
from PyQt4 import QtGui
```

Strict on the other hand only exposes members that are guaranteed to work identically across all bindings. This mode is ideal if you are looking for the most cross-compatible experience and you would like your software to run on all bindings.

```python
from Qt import QtGui
assert not hasattr(QtGui, "QWidget")
```

**Caveats**

There are cases where Qt.py is not handling incompatibility issues. Please see [`CAVEATS.md`](CAVEATS.md) for more information.
Expand Down Expand Up @@ -304,6 +271,7 @@ Send us a pull-request with your studio here.
- [Fido](http://fido.se/)
- [Bläck](http://www.blackstudios.se/)
- [CGRU](http://cgru.info/)
- [MPC](http://www.moving-picture.com)

Presented at Siggraph 2016, BOF!

Expand Down Expand Up @@ -377,8 +345,8 @@ Tests that are written at module level are run four times - once per binding - w

```python
if binding("PyQt4"):
def test_something_related_to_pyqt4():
pass
def test_something_related_to_pyqt4():
pass
```

**Running tests**
Expand Down
12 changes: 12 additions & 0 deletions build_membership.py
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,9 @@ def test_{binding}_members():
"qTan",
"qtTrId",

# missing from all bindings
"QFileSelector",

# missing from PyQt5
"SIGNAL",
"SLOT",
Expand All @@ -225,6 +228,15 @@ def test_{binding}_members():
"QMatrix",
"QPyTextObject",
"QStringListModel",

# missing from all bindings
"QAccessible",
"QAccessibleInterface",
"QExposeEvent",
"QOpenGLContext",
"QOpenGLFramebufferObject",
"QOpenGLShader",
"QScreen",
],

"QtWebKit": [
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from setuptools import setup

os.environ["QT_PREFERRED_BINDING"] = "None"
version = __import__("Qt").__wrapper_version__
version = __import__("Qt").__version__


classifiers = [
Expand Down

0 comments on commit 21dfae1

Please sign in to comment.