Hello community,

here is the log from the commit of package python-Qt.py for openSUSE:Factory 
checked in at 2020-09-22 21:12:10
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-Qt.py (Old)
 and      /work/SRC/openSUSE:Factory/.python-Qt.py.new.4249 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-Qt.py"

Tue Sep 22 21:12:10 2020 rev:4 rq:835961 version:1.3.1

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-Qt.py/python-Qt.py.changes        
2019-11-08 15:25:49.999001557 +0100
+++ /work/SRC/openSUSE:Factory/.python-Qt.py.new.4249/python-Qt.py.changes      
2020-09-22 21:12:25.091994328 +0200
@@ -1,0 +2,8 @@
+Tue Sep 22 04:41:36 UTC 2020 - Steve Kowalik <[email protected]>
+
+- Update to 1.3.1:
+  * Stability improvements and greater ability for QtCompat.wrapInstance
+    to do its job
+  * Bugfixes and additional members 
+
+-------------------------------------------------------------------

Old:
----
  Qt.py-1.1.0.tar.gz

New:
----
  Qt.py-1.3.1.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-Qt.py.spec ++++++
--- /var/tmp/diff_new_pack.dBeHBn/_old  2020-09-22 21:12:26.139995245 +0200
+++ /var/tmp/diff_new_pack.dBeHBn/_new  2020-09-22 21:12:26.143995249 +0200
@@ -1,7 +1,7 @@
 #
 # spec file for package python-Qt.py
 #
-# Copyright (c) 2019 SUSE LINUX GmbH, Nuernberg, Germany.
+# Copyright (c) 2020 SUSE LLC
 # Copyright (c) 2018, Martin Hauke <[email protected]>
 #
 # All modifications and additions to the file contributed by third parties
@@ -19,7 +19,7 @@
 
 %{?!python_module:%define python_module() python-%{**} python3-%{**}}
 Name:           python-Qt.py
-Version:        1.1.0
+Version:        1.3.1
 Release:        0
 Summary:        Python compat-wrapper around all Qt bindings
 License:        MIT

++++++ Qt.py-1.1.0.tar.gz -> Qt.py-1.3.1.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Qt.py-1.1.0/PKG-INFO new/Qt.py-1.3.1/PKG-INFO
--- old/Qt.py-1.1.0/PKG-INFO    2018-01-25 11:56:43.000000000 +0100
+++ new/Qt.py-1.3.1/PKG-INFO    2020-09-20 16:00:46.000000000 +0200
@@ -1,12 +1,11 @@
 Metadata-Version: 1.1
 Name: Qt.py
-Version: 1.1.0
+Version: 1.3.1
 Summary: Python 2 & 3 compatibility wrapper around all Qt bindings - PySide, 
PySide2, PyQt4 and PyQt5.
 Home-page: https://github.com/mottosso/Qt
 Author: Marcus Ottosson
 Author-email: [email protected]
 License: MIT
-Description-Content-Type: UNKNOWN
 Description: UNKNOWN
 Platform: UNKNOWN
 Classifier: Development Status :: 4 - Beta
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Qt.py-1.1.0/Qt.py new/Qt.py-1.3.1/Qt.py
--- old/Qt.py-1.1.0/Qt.py       2018-01-25 11:53:46.000000000 +0100
+++ new/Qt.py-1.3.1/Qt.py       2020-09-20 15:58:17.000000000 +0200
@@ -41,15 +41,18 @@
 import sys
 import types
 import shutil
+import importlib
+import json
 
 
-__version__ = "1.1.0"
+__version__ = "1.3.1"
 
 # Enable support for `from Qt import *`
 __all__ = []
 
 # Flags from environment variables
 QT_VERBOSE = bool(os.getenv("QT_VERBOSE"))
+QT_PREFERRED_BINDING_JSON = os.getenv("QT_PREFERRED_BINDING_JSON", "")
 QT_PREFERRED_BINDING = os.getenv("QT_PREFERRED_BINDING", "")
 QT_SIP_API_HINT = os.getenv("QT_SIP_API_HINT")
 
@@ -63,6 +66,7 @@
     # Python 3 compatibility
     long = int
 
+
 """Common members of all bindings
 
 This is where each member of Qt.py is explicitly defined.
@@ -677,6 +681,322 @@
     ]
 }
 
+""" Missing members
+
+This mapping describes members that have been deprecated
+in one or more bindings and have been left out of the
+_common_members mapping.
+
+The member can provide an extra details string to be
+included in exceptions and warnings.
+"""
+
+_missing_members = {
+    "QtGui": {
+        "QMatrix": "Deprecated in PyQt5",
+    },
+}
+
+
+def _qInstallMessageHandler(handler):
+    """Install a message handler that works in all bindings
+
+    Args:
+        handler: A function that takes 3 arguments, or None
+    """
+    def messageOutputHandler(*args):
+        # In Qt4 bindings, message handlers are passed 2 arguments
+        # In Qt5 bindings, message handlers are passed 3 arguments
+        # The first argument is a QtMsgType
+        # The last argument is the message to be printed
+        # The Middle argument (if passed) is a QMessageLogContext
+        if len(args) == 3:
+            msgType, logContext, msg = args
+        elif len(args) == 2:
+            msgType, msg = args
+            logContext = None
+        else:
+            raise TypeError(
+                "handler expected 2 or 3 arguments, got {0}".format(len(args)))
+
+        if isinstance(msg, bytes):
+            # In python 3, some bindings pass a bytestring, which cannot be
+            # used elsewhere. Decoding a python 2 or 3 bytestring object will
+            # consistently return a unicode object.
+            msg = msg.decode()
+
+        handler(msgType, logContext, msg)
+
+    passObject = messageOutputHandler if handler else handler
+    if Qt.IsPySide or Qt.IsPyQt4:
+        return Qt._QtCore.qInstallMsgHandler(passObject)
+    elif Qt.IsPySide2 or Qt.IsPyQt5:
+        return Qt._QtCore.qInstallMessageHandler(passObject)
+
+
+def _getcpppointer(object):
+    if hasattr(Qt, "_shiboken2"):
+        return getattr(Qt, "_shiboken2").getCppPointer(object)[0]
+    elif hasattr(Qt, "_shiboken"):
+        return getattr(Qt, "_shiboken").getCppPointer(object)[0]
+    elif hasattr(Qt, "_sip"):
+        return getattr(Qt, "_sip").unwrapinstance(object)
+    raise AttributeError("'module' has no attribute 'getCppPointer'")
+
+
+def _wrapinstance(ptr, base=None):
+    """Enable implicit cast of pointer to most suitable class
+
+    This behaviour is available in sip per default.
+
+    Based on http://nathanhorne.com/pyqtpyside-wrap-instance
+
+    Usage:
+        This mechanism kicks in under these circumstances.
+        1. Qt.py is using PySide 1 or 2.
+        2. A `base` argument is not provided.
+
+        See :func:`QtCompat.wrapInstance()`
+
+    Arguments:
+        ptr (long): Pointer to QObject in memory
+        base (QObject, optional): Base class to wrap with. Defaults to QObject,
+            which should handle anything.
+
+    """
+
+    assert isinstance(ptr, long), "Argument 'ptr' must be of type <long>"
+    assert (base is None) or issubclass(base, Qt.QtCore.QObject), (
+        "Argument 'base' must be of type <QObject>")
+
+    if Qt.IsPyQt4 or Qt.IsPyQt5:
+        func = getattr(Qt, "_sip").wrapinstance
+    elif Qt.IsPySide2:
+        func = getattr(Qt, "_shiboken2").wrapInstance
+    elif Qt.IsPySide:
+        func = getattr(Qt, "_shiboken").wrapInstance
+    else:
+        raise AttributeError("'module' has no attribute 'wrapInstance'")
+
+    if base is None:
+        if Qt.IsPyQt4 or Qt.IsPyQt5:
+            base = Qt.QtCore.QObject
+        else:
+            q_object = func(long(ptr), Qt.QtCore.QObject)
+            meta_object = q_object.metaObject()
+
+            while True:
+                class_name = meta_object.className()
+
+                try:
+                    base = getattr(Qt.QtWidgets, class_name)
+                except AttributeError:
+                    try:
+                        base = getattr(Qt.QtCore, class_name)
+                    except AttributeError:
+                        meta_object = meta_object.superClass()
+                        continue
+
+                break
+
+    return func(long(ptr), base)
+
+
+def _isvalid(object):
+    """Check if the object is valid to use in Python runtime.
+
+    Usage:
+        See :func:`QtCompat.isValid()`
+
+    Arguments:
+        object (QObject): QObject to check the validity of.
+
+    """
+
+    assert isinstance(object, Qt.QtCore.QObject)
+
+    if hasattr(Qt, "_shiboken2"):
+        return getattr(Qt, "_shiboken2").isValid(object)
+
+    elif hasattr(Qt, "_shiboken"):
+        return getattr(Qt, "_shiboken").isValid(object)
+
+    elif hasattr(Qt, "_sip"):
+        return not getattr(Qt, "_sip").isdeleted(object)
+
+    else:
+        raise AttributeError("'module' has no attribute isValid")
+
+
+def _translate(context, sourceText, *args):
+    # In Qt4 bindings, translate can be passed 2 or 3 arguments
+    # In Qt5 bindings, translate can be passed 2 arguments
+    # The first argument is disambiguation[str]
+    # The last argument is n[int]
+    # The middle argument can be encoding[QtCore.QCoreApplication.Encoding]
+    if len(args) == 3:
+        disambiguation, encoding, n = args
+    elif len(args) == 2:
+        disambiguation, n = args
+        encoding = None
+    else:
+        raise TypeError(
+            "Expected 4 or 5 arguments, got {0}.".format(len(args) + 2))
+
+    if hasattr(Qt.QtCore, "QCoreApplication"):
+        app = getattr(Qt.QtCore, "QCoreApplication")
+    else:
+        raise NotImplementedError(
+            "Missing QCoreApplication implementation for {binding}".format(
+                binding=Qt.__binding__,
+            )
+        )
+    if Qt.__binding__ in ("PySide2", "PyQt5"):
+        sanitized_args = [context, sourceText, disambiguation, n]
+    else:
+        sanitized_args = [
+            context,
+            sourceText,
+            disambiguation,
+            encoding or app.CodecForTr,
+            n
+        ]
+    return app.translate(*sanitized_args)
+
+
+def _loadUi(uifile, baseinstance=None):
+    """Dynamically load a user interface from the given `uifile`
+
+    This function calls `uic.loadUi` if using PyQt bindings,
+    else it implements a comparable binding for PySide.
+
+    Documentation:
+        http://pyqt.sourceforge.net/Docs/PyQt5/designer.html#PyQt5.uic.loadUi
+
+    Arguments:
+        uifile (str): Absolute path to Qt Designer file.
+        baseinstance (QWidget): Instantiated QWidget or subclass thereof
+
+    Return:
+        baseinstance if `baseinstance` is not `None`. Otherwise
+        return the newly created instance of the user interface.
+
+    """
+    if hasattr(Qt, "_uic"):
+        return Qt._uic.loadUi(uifile, baseinstance)
+
+    elif hasattr(Qt, "_QtUiTools"):
+        # Implement `PyQt5.uic.loadUi` for PySide(2)
+
+        class _UiLoader(Qt._QtUiTools.QUiLoader):
+            """Create the user interface in a base instance.
+
+            Unlike `Qt._QtUiTools.QUiLoader` itself this class does not
+            create a new instance of the top-level widget, but creates the user
+            interface in an existing instance of the top-level class if needed.
+
+            This mimics the behaviour of `PyQt5.uic.loadUi`.
+
+            """
+
+            def __init__(self, baseinstance):
+                super(_UiLoader, self).__init__(baseinstance)
+                self.baseinstance = baseinstance
+                self.custom_widgets = {}
+
+            def _loadCustomWidgets(self, etree):
+                """
+                Workaround to pyside-77 bug.
+
+                From QUiLoader doc we should use registerCustomWidget method.
+                But this causes a segfault on some platforms.
+
+                Instead we fetch from customwidgets DOM node the python class
+                objects. Then we can directly use them in createWidget method.
+                """
+
+                def headerToModule(header):
+                    """
+                    Translate a header file to python module path
+                    foo/bar.h => foo.bar
+                    """
+                    # Remove header extension
+                    module = os.path.splitext(header)[0]
+
+                    # Replace os separator by python module separator
+                    return module.replace("/", ".").replace("\\", ".")
+
+                custom_widgets = etree.find("customwidgets")
+
+                if custom_widgets is None:
+                    return
+
+                for custom_widget in custom_widgets:
+                    class_name = custom_widget.find("class").text
+                    header = custom_widget.find("header").text
+                    module = importlib.import_module(headerToModule(header))
+                    self.custom_widgets[class_name] = getattr(module,
+                                                              class_name)
+
+            def load(self, uifile, *args, **kwargs):
+                from xml.etree.ElementTree import ElementTree
+
+                # For whatever reason, if this doesn't happen then
+                # reading an invalid or non-existing .ui file throws
+                # a RuntimeError.
+                etree = ElementTree()
+                etree.parse(uifile)
+                self._loadCustomWidgets(etree)
+
+                widget = Qt._QtUiTools.QUiLoader.load(
+                    self, uifile, *args, **kwargs)
+
+                # Workaround for PySide 1.0.9, see issue #208
+                widget.parentWidget()
+
+                return widget
+
+            def createWidget(self, class_name, parent=None, name=""):
+                """Called for each widget defined in ui file
+
+                Overridden here to populate `baseinstance` instead.
+
+                """
+
+                if parent is None and self.baseinstance:
+                    # Supposed to create the top-level widget,
+                    # return the base instance instead
+                    return self.baseinstance
+
+                # For some reason, Line is not in the list of available
+                # widgets, but works fine, so we have to special case it here.
+                if class_name in self.availableWidgets() + ["Line"]:
+                    # Create a new widget for child widgets
+                    widget = Qt._QtUiTools.QUiLoader.createWidget(self,
+                                                                  class_name,
+                                                                  parent,
+                                                                  name)
+                elif class_name in self.custom_widgets:
+                    widget = self.custom_widgets[class_name](parent=parent)
+                else:
+                    raise Exception("Custom widget '%s' not supported"
+                                    % class_name)
+
+                if self.baseinstance:
+                    # Set an attribute for the new child widget on the base
+                    # instance, just like PyQt5.uic.loadUi does.
+                    setattr(self.baseinstance, name, widget)
+
+                return widget
+
+        widget = _UiLoader(baseinstance).load(uifile)
+        Qt.QtCore.QMetaObject.connectSlotsByName(widget)
+
+        return widget
+
+    else:
+        raise NotImplementedError("No implementation available for loadUi")
+
 
 """Misplaced members
 
@@ -685,6 +1005,7 @@
 """
 _misplaced_members = {
     "PySide2": {
+        "QtCore.QStringListModel": "QtCore.QStringListModel",
         "QtGui.QStringListModel": "QtCore.QStringListModel",
         "QtCore.Property": "QtCore.Property",
         "QtCore.Signal": "QtCore.Signal",
@@ -694,6 +1015,21 @@
         "QtCore.QItemSelection": "QtCore.QItemSelection",
         "QtCore.QItemSelectionModel": "QtCore.QItemSelectionModel",
         "QtCore.QItemSelectionRange": "QtCore.QItemSelectionRange",
+        "QtUiTools.QUiLoader": ["QtCompat.loadUi", _loadUi],
+        "shiboken2.wrapInstance": ["QtCompat.wrapInstance", _wrapinstance],
+        "shiboken2.getCppPointer": ["QtCompat.getCppPointer", _getcpppointer],
+        "shiboken2.isValid": ["QtCompat.isValid", _isvalid],
+        "QtWidgets.qApp": "QtWidgets.QApplication.instance()",
+        "QtCore.QCoreApplication.translate": [
+            "QtCompat.translate", _translate
+        ],
+        "QtWidgets.QApplication.translate": [
+            "QtCompat.translate", _translate
+        ],
+        "QtCore.qInstallMessageHandler": [
+            "QtCompat.qInstallMessageHandler", _qInstallMessageHandler
+        ],
+        "QtWidgets.QStyleOptionViewItem": "QtCompat.QStyleOptionViewItemV4",
     },
     "PyQt5": {
         "QtCore.pyqtProperty": "QtCore.Property",
@@ -705,6 +1041,21 @@
         "QtCore.QItemSelection": "QtCore.QItemSelection",
         "QtCore.QItemSelectionModel": "QtCore.QItemSelectionModel",
         "QtCore.QItemSelectionRange": "QtCore.QItemSelectionRange",
+        "uic.loadUi": ["QtCompat.loadUi", _loadUi],
+        "sip.wrapinstance": ["QtCompat.wrapInstance", _wrapinstance],
+        "sip.unwrapinstance": ["QtCompat.getCppPointer", _getcpppointer],
+        "sip.isdeleted": ["QtCompat.isValid", _isvalid],
+        "QtWidgets.qApp": "QtWidgets.QApplication.instance()",
+        "QtCore.QCoreApplication.translate": [
+            "QtCompat.translate", _translate
+        ],
+        "QtWidgets.QApplication.translate": [
+            "QtCompat.translate", _translate
+        ],
+        "QtCore.qInstallMessageHandler": [
+            "QtCompat.qInstallMessageHandler", _qInstallMessageHandler
+        ],
+        "QtWidgets.QStyleOptionViewItem": "QtCompat.QStyleOptionViewItemV4",
     },
     "PySide": {
         "QtGui.QAbstractProxyModel": "QtCore.QAbstractProxyModel",
@@ -724,6 +1075,21 @@
         "QtGui.QPrintPreviewWidget": "QtPrintSupport.QPrintPreviewWidget",
         "QtGui.QPrinter": "QtPrintSupport.QPrinter",
         "QtGui.QPrinterInfo": "QtPrintSupport.QPrinterInfo",
+        "QtUiTools.QUiLoader": ["QtCompat.loadUi", _loadUi],
+        "shiboken.wrapInstance": ["QtCompat.wrapInstance", _wrapinstance],
+        "shiboken.unwrapInstance": ["QtCompat.getCppPointer", _getcpppointer],
+        "shiboken.isValid": ["QtCompat.isValid", _isvalid],
+        "QtGui.qApp": "QtWidgets.QApplication.instance()",
+        "QtCore.QCoreApplication.translate": [
+            "QtCompat.translate", _translate
+        ],
+        "QtGui.QApplication.translate": [
+            "QtCompat.translate", _translate
+        ],
+        "QtCore.qInstallMsgHandler": [
+            "QtCompat.qInstallMessageHandler", _qInstallMessageHandler
+        ],
+        "QtGui.QStyleOptionViewItemV4": "QtCompat.QStyleOptionViewItemV4",
     },
     "PyQt4": {
         "QtGui.QAbstractProxyModel": "QtCore.QAbstractProxyModel",
@@ -743,6 +1109,23 @@
         "QtGui.QPrintPreviewWidget": "QtPrintSupport.QPrintPreviewWidget",
         "QtGui.QPrinter": "QtPrintSupport.QPrinter",
         "QtGui.QPrinterInfo": "QtPrintSupport.QPrinterInfo",
+        # "QtCore.pyqtSignature": "QtCore.Slot",
+        "uic.loadUi": ["QtCompat.loadUi", _loadUi],
+        "sip.wrapinstance": ["QtCompat.wrapInstance", _wrapinstance],
+        "sip.unwrapinstance": ["QtCompat.getCppPointer", _getcpppointer],
+        "sip.isdeleted": ["QtCompat.isValid", _isvalid],
+        "QtCore.QString": "str",
+        "QtGui.qApp": "QtWidgets.QApplication.instance()",
+        "QtCore.QCoreApplication.translate": [
+            "QtCompat.translate", _translate
+        ],
+        "QtGui.QApplication.translate": [
+            "QtCompat.translate", _translate
+        ],
+        "QtCore.qInstallMsgHandler": [
+            "QtCompat.qInstallMessageHandler", _qInstallMessageHandler
+        ],
+        "QtGui.QStyleOptionViewItemV4": "QtCompat.QStyleOptionViewItemV4",
     }
 }
 
@@ -761,6 +1144,9 @@
 """
 _compatibility_members = {
     "PySide2": {
+        "QWidget": {
+            "grab": "QtWidgets.QWidget.grab",
+        },
         "QHeaderView": {
             "sectionsClickable": "QtWidgets.QHeaderView.sectionsClickable",
             "setSectionsClickable":
@@ -778,6 +1164,9 @@
         },
     },
     "PyQt5": {
+        "QWidget": {
+            "grab": "QtWidgets.QWidget.grab",
+        },
         "QHeaderView": {
             "sectionsClickable": "QtWidgets.QHeaderView.sectionsClickable",
             "setSectionsClickable":
@@ -795,6 +1184,9 @@
         },
     },
     "PySide": {
+        "QWidget": {
+            "grab": "QtWidgets.QPixmap.grabWidget",
+        },
         "QHeaderView": {
             "sectionsClickable": "QtWidgets.QHeaderView.isClickable",
             "setSectionsClickable": "QtWidgets.QHeaderView.setClickable",
@@ -810,6 +1202,9 @@
         },
     },
     "PyQt4": {
+        "QWidget": {
+            "grab": "QtWidgets.QPixmap.grabWidget",
+        },
         "QHeaderView": {
             "sectionsClickable": "QtWidgets.QHeaderView.isClickable",
             "setSectionsClickable": "QtWidgets.QHeaderView.setClickable",
@@ -864,12 +1259,25 @@
 
     Qt.__binding__ = module.__name__
 
+    def _warn_import_error(exc):
+        msg = str(exc)
+        if "No module named" in msg:
+            return
+        _warn("ImportError: %s" % msg)
+
     for name in list(_common_members) + extras:
         try:
             submodule = _import_sub_module(
                 module, name)
-        except ImportError:
-            continue
+        except ImportError as e:
+            try:
+                # For extra modules like sip and shiboken that may not be
+                # children of the binding.
+                submodule = __import__(name)
+            except ImportError as e2:
+                _warn_import_error(e)
+                _warn_import_error(e2)
+                continue
 
         setattr(Qt, "_" + name, submodule)
 
@@ -880,50 +1288,6 @@
             setattr(Qt, name, _new_module(name))
 
 
-def _wrapinstance(func, ptr, base=None):
-    """Enable implicit cast of pointer to most suitable class
-
-    This behaviour is available in sip per default.
-
-    Based on http://nathanhorne.com/pyqtpyside-wrap-instance
-
-    Usage:
-        This mechanism kicks in under these circumstances.
-        1. Qt.py is using PySide 1 or 2.
-        2. A `base` argument is not provided.
-
-        See :func:`QtCompat.wrapInstance()`
-
-    Arguments:
-        func (function): Original function
-        ptr (long): Pointer to QObject in memory
-        base (QObject, optional): Base class to wrap with. Defaults to QObject,
-            which should handle anything.
-
-    """
-
-    assert isinstance(ptr, long), "Argument 'ptr' must be of type <long>"
-    assert (base is None) or issubclass(base, Qt.QtCore.QObject), (
-        "Argument 'base' must be of type <QObject>")
-
-    if base is None:
-        q_object = func(long(ptr), Qt.QtCore.QObject)
-        meta_object = q_object.metaObject()
-        class_name = meta_object.className()
-        super_class_name = meta_object.superClass().className()
-
-        if hasattr(Qt.QtWidgets, class_name):
-            base = getattr(Qt.QtWidgets, class_name)
-
-        elif hasattr(Qt.QtWidgets, super_class_name):
-            base = getattr(Qt.QtWidgets, super_class_name)
-
-        else:
-            base = Qt.QtCore.QObject
-
-    return func(long(ptr), base)
-
-
 def _reassign_misplaced_members(binding):
     """Apply misplaced members from `binding` to Qt.py
 
@@ -933,19 +1297,38 @@
     """
 
     for src, dst in _misplaced_members[binding].items():
-        src_module, src_member = src.split(".")
-        dst_module, dst_member = dst.split(".")
+        dst_value = None
+
+        src_parts = src.split(".")
+        src_module = src_parts[0]
+        src_member = None
+        if len(src_parts) > 1:
+            src_member = src_parts[1:]
+
+        if isinstance(dst, (list, tuple)):
+            dst, dst_value = dst
+
+        dst_parts = dst.split(".")
+        dst_module = dst_parts[0]
+        dst_member = None
+        if len(dst_parts) > 1:
+            dst_member = dst_parts[1]
 
         # Get the member we want to store in the namesapce.
-        try:
-            dst_value = getattr(getattr(Qt, "_" + src_module), src_member)
-        except AttributeError:
-            # If the member we want to store in the namespace does not exist,
-            # there is no need to continue. This can happen if a request was
-            # made to rename a member that didn't exist, for example
-            # if QtWidgets isn't available on the target platform.
-            _log("Misplaced member has no source: {}".format(src))
-            continue
+        if not dst_value:
+            try:
+                _part = getattr(Qt, "_" + src_module)
+                while src_member:
+                    member = src_member.pop(0)
+                    _part = getattr(_part, member)
+                dst_value = _part
+            except AttributeError:
+                # If the member we want to store in the namespace does not
+                # exist, there is no need to continue. This can happen if a
+                # request was made to rename a member that didn't exist, for
+                # example if QtWidgets isn't available on the target platform.
+                _log("Misplaced member has no source: {0}".format(src))
+                continue
 
         try:
             src_object = getattr(Qt, dst_module)
@@ -965,9 +1348,14 @@
             # Enable direct import of the new module
             sys.modules[__name__ + "." + dst_module] = src_object
 
+        if not dst_value:
+            dst_value = getattr(Qt, "_" + src_module)
+            if src_member:
+                dst_value = getattr(dst_value, src_member)
+
         setattr(
             src_object,
-            dst_member,
+            dst_member or dst_module,
             dst_value
         )
 
@@ -1044,10 +1432,7 @@
     """
 
     import PySide2 as module
-    _setup(module, ["QtUiTools"])
-
-    Qt.__binding_version__ = module.__version__
-
+    extras = ["QtUiTools"]
     try:
         try:
             # Before merge of PySide and shiboken
@@ -1055,24 +1440,27 @@
         except ImportError:
             # After merge of PySide and shiboken, May 2017
             from PySide2 import shiboken2
+        extras.append("shiboken2")
+    except ImportError:
+        pass
 
-        Qt.QtCompat.wrapInstance = (
-            lambda ptr, base=None: _wrapinstance(
-                shiboken2.wrapInstance, ptr, base)
-        )
-        Qt.QtCompat.getCppPointer = lambda object: \
-            shiboken2.getCppPointer(object)[0]
+    _setup(module, extras)
+    Qt.__binding_version__ = module.__version__
 
-    except ImportError:
-        pass  # Optional
+    if hasattr(Qt, "_shiboken2"):
+        Qt.QtCompat.wrapInstance = _wrapinstance
+        Qt.QtCompat.getCppPointer = _getcpppointer
+        Qt.QtCompat.delete = shiboken2.delete
 
     if hasattr(Qt, "_QtUiTools"):
         Qt.QtCompat.loadUi = _loadUi
 
     if hasattr(Qt, "_QtCore"):
         Qt.__qt_version__ = Qt._QtCore.qVersion()
-        Qt.QtCompat.qInstallMessageHandler = _qInstallMessageHandler
-        Qt.QtCompat.translate = Qt._QtCore.QCoreApplication.translate
+        Qt.QtCompat.dataChanged = (
+            lambda self, topleft, bottomright, roles=None:
+            self.dataChanged.emit(topleft, bottomright, roles or [])
+        )
 
     if hasattr(Qt, "_QtWidgets"):
         Qt.QtCompat.setSectionResizeMode = \
@@ -1086,10 +1474,7 @@
     """Initialise PySide"""
 
     import PySide as module
-    _setup(module, ["QtUiTools"])
-
-    Qt.__binding_version__ = module.__version__
-
+    extras = ["QtUiTools"]
     try:
         try:
             # Before merge of PySide and shiboken
@@ -1097,16 +1482,17 @@
         except ImportError:
             # After merge of PySide and shiboken, May 2017
             from PySide import shiboken
+        extras.append("shiboken")
+    except ImportError:
+        pass
 
-        Qt.QtCompat.wrapInstance = (
-            lambda ptr, base=None: _wrapinstance(
-                shiboken.wrapInstance, ptr, base)
-        )
-        Qt.QtCompat.getCppPointer = lambda object: \
-            shiboken.getCppPointer(object)[0]
+    _setup(module, extras)
+    Qt.__binding_version__ = module.__version__
 
-    except ImportError:
-        pass  # Optional
+    if hasattr(Qt, "_shiboken"):
+        Qt.QtCompat.wrapInstance = _wrapinstance
+        Qt.QtCompat.getCppPointer = _getcpppointer
+        Qt.QtCompat.delete = shiboken.delete
 
     if hasattr(Qt, "_QtUiTools"):
         Qt.QtCompat.loadUi = _loadUi
@@ -1122,17 +1508,9 @@
 
     if hasattr(Qt, "_QtCore"):
         Qt.__qt_version__ = Qt._QtCore.qVersion()
-        QCoreApplication = Qt._QtCore.QCoreApplication
-        Qt.QtCompat.qInstallMessageHandler = _qInstallMessageHandler
-        Qt.QtCompat.translate = (
-            lambda context, sourceText, disambiguation, n:
-            QCoreApplication.translate(
-                context,
-                sourceText,
-                disambiguation,
-                QCoreApplication.CodecForTr,
-                n
-            )
+        Qt.QtCompat.dataChanged = (
+            lambda self, topleft, bottomright, roles=None:
+            self.dataChanged.emit(topleft, bottomright)
         )
 
     _reassign_misplaced_members("PySide")
@@ -1143,19 +1521,25 @@
     """Initialise PyQt5"""
 
     import PyQt5 as module
-    _setup(module, ["uic"])
+    extras = ["uic"]
 
     try:
-        import sip
-        Qt.QtCompat.wrapInstance = (
-            lambda ptr, base=None: _wrapinstance(
-                sip.wrapinstance, ptr, base)
-        )
-        Qt.QtCompat.getCppPointer = lambda object: \
-            sip.unwrapinstance(object)
-
+        # Relevant to PyQt5 5.11 and above
+        from PyQt5 import sip
+        extras += ["sip"]
     except ImportError:
-        pass  # Optional
+
+        try:
+            import sip
+            extras += ["sip"]
+        except ImportError:
+            sip = None
+
+    _setup(module, extras)
+    if hasattr(Qt, "_sip"):
+        Qt.QtCompat.wrapInstance = _wrapinstance
+        Qt.QtCompat.getCppPointer = _getcpppointer
+        Qt.QtCompat.delete = sip.delete
 
     if hasattr(Qt, "_uic"):
         Qt.QtCompat.loadUi = _loadUi
@@ -1163,8 +1547,10 @@
     if hasattr(Qt, "_QtCore"):
         Qt.__binding_version__ = Qt._QtCore.PYQT_VERSION_STR
         Qt.__qt_version__ = Qt._QtCore.QT_VERSION_STR
-        Qt.QtCompat.qInstallMessageHandler = _qInstallMessageHandler
-        Qt.QtCompat.translate = Qt._QtCore.QCoreApplication.translate
+        Qt.QtCompat.dataChanged = (
+            lambda self, topleft, bottomright, roles=None:
+            self.dataChanged.emit(topleft, bottomright, roles or [])
+        )
 
     if hasattr(Qt, "_QtWidgets"):
         Qt.QtCompat.setSectionResizeMode = \
@@ -1212,19 +1598,18 @@
                 )
 
     import PyQt4 as module
-    _setup(module, ["uic"])
-
+    extras = ["uic"]
     try:
         import sip
-        Qt.QtCompat.wrapInstance = (
-            lambda ptr, base=None: _wrapinstance(
-                sip.wrapinstance, ptr, base)
-        )
-        Qt.QtCompat.getCppPointer = lambda object: \
-            sip.unwrapinstance(object)
-
+        extras.append(sip.__name__)
     except ImportError:
-        pass  # Optional
+        sip = None
+
+    _setup(module, extras)
+    if hasattr(Qt, "_sip"):
+        Qt.QtCompat.wrapInstance = _wrapinstance
+        Qt.QtCompat.getCppPointer = _getcpppointer
+        Qt.QtCompat.delete = sip.delete
 
     if hasattr(Qt, "_uic"):
         Qt.QtCompat.loadUi = _loadUi
@@ -1242,16 +1627,9 @@
     if hasattr(Qt, "_QtCore"):
         Qt.__binding_version__ = Qt._QtCore.PYQT_VERSION_STR
         Qt.__qt_version__ = Qt._QtCore.QT_VERSION_STR
-        QCoreApplication = Qt._QtCore.QCoreApplication
-        Qt.QtCompat.qInstallMessageHandler = _qInstallMessageHandler
-        Qt.QtCompat.translate = (
-            lambda context, sourceText, disambiguation, n:
-            QCoreApplication.translate(
-                context,
-                sourceText,
-                disambiguation,
-                QCoreApplication.CodecForTr,
-                n)
+        Qt.QtCompat.dataChanged = (
+            lambda self, topleft, bottomright, roles=None:
+            self.dataChanged.emit(topleft, bottomright)
         )
 
     _reassign_misplaced_members("PyQt4")
@@ -1300,142 +1678,11 @@
 
 def _log(text):
     if QT_VERBOSE:
-        sys.stdout.write(text + "\n")
-
-
-def _loadUi(uifile, baseinstance=None):
-    """Dynamically load a user interface from the given `uifile`
-
-    This function calls `uic.loadUi` if using PyQt bindings,
-    else it implements a comparable binding for PySide.
-
-    Documentation:
-        http://pyqt.sourceforge.net/Docs/PyQt5/designer.html#PyQt5.uic.loadUi
-
-    Arguments:
-        uifile (str): Absolute path to Qt Designer file.
-        baseinstance (QWidget): Instantiated QWidget or subclass thereof
-
-    Return:
-        baseinstance if `baseinstance` is not `None`. Otherwise
-        return the newly created instance of the user interface.
-
-    """
-
-    if hasattr(Qt, "_uic"):
-        return Qt._uic.loadUi(uifile, baseinstance)
-
-    elif hasattr(Qt, "_QtUiTools"):
-        # Implement `PyQt5.uic.loadUi` for PySide(2)
-
-        class _UiLoader(Qt._QtUiTools.QUiLoader):
-            """Create the user interface in a base instance.
-
-            Unlike `Qt._QtUiTools.QUiLoader` itself this class does not
-            create a new instance of the top-level widget, but creates the user
-            interface in an existing instance of the top-level class if needed.
-
-            This mimics the behaviour of `PyQt5.uic.loadUi`.
-
-            """
-
-            def __init__(self, baseinstance):
-                super(_UiLoader, self).__init__(baseinstance)
-                self.baseinstance = baseinstance
-
-            def load(self, uifile, *args, **kwargs):
-                from xml.etree.ElementTree import ElementTree
+        sys.stdout.write("Qt.py [info]: %s\n" % text)
 
-                # For whatever reason, if this doesn't happen then
-                # reading an invalid or non-existing .ui file throws
-                # a RuntimeError.
-                etree = ElementTree()
-                etree.parse(uifile)
-
-                widget = Qt._QtUiTools.QUiLoader.load(
-                    self, uifile, *args, **kwargs)
-
-                # Workaround for PySide 1.0.9, see issue #208
-                widget.parentWidget()
-
-                return widget
-
-            def createWidget(self, class_name, parent=None, name=""):
-                """Called for each widget defined in ui file
-
-                Overridden here to populate `baseinstance` instead.
-
-                """
-
-                if parent is None and self.baseinstance:
-                    # Supposed to create the top-level widget,
-                    # return the base instance instead
-                    return self.baseinstance
-
-                # For some reason, Line is not in the list of available
-                # widgets, but works fine, so we have to special case it here.
-                if class_name in self.availableWidgets() + ["Line"]:
-                    # Create a new widget for child widgets
-                    widget = Qt._QtUiTools.QUiLoader.createWidget(self,
-                                                                  class_name,
-                                                                  parent,
-                                                                  name)
-
-                else:
-                    raise Exception("Custom widget '%s' not supported"
-                                    % class_name)
-
-                if self.baseinstance:
-                    # Set an attribute for the new child widget on the base
-                    # instance, just like PyQt5.uic.loadUi does.
-                    setattr(self.baseinstance, name, widget)
-
-                return widget
-
-        widget = _UiLoader(baseinstance).load(uifile)
-        Qt.QtCore.QMetaObject.connectSlotsByName(widget)
-
-        return widget
-
-    else:
-        raise NotImplementedError("No implementation available for loadUi")
-
-
-def _qInstallMessageHandler(handler):
-    """Install a message handler that works in all bindings
-
-    Args:
-        handler: A function that takes 3 arguments, or None
-    """
-    def messageOutputHandler(*args):
-        # In Qt4 bindings, message handlers are passed 2 arguments
-        # In Qt5 bindings, message handlers are passed 3 arguments
-        # The first argument is a QtMsgType
-        # The last argument is the message to be printed
-        # The Middle argument (if passed) is a QMessageLogContext
-        if len(args) == 3:
-            msgType, logContext, msg = args
-        elif len(args) == 2:
-            msgType, msg = args
-            logContext = None
-        else:
-            raise TypeError(
-                "handler expected 2 or 3 arguments, got {0}".format(len(args)))
-
-        if isinstance(msg, bytes):
-            # In python 3, some bindings pass a bytestring, which cannot be
-            # used elsewhere. Decoding a python 2 or 3 bytestring object will
-            # consistently return a unicode object.
-            msg = msg.decode()
-
-        handler(msgType, logContext, msg)
-
-    passObject = messageOutputHandler if handler else handler
-    if Qt.IsPySide or Qt.IsPyQt4:
-        return Qt._QtCore.qInstallMsgHandler(passObject)
-    elif Qt.IsPySide2 or Qt.IsPyQt5:
-        return Qt._QtCore.qInstallMessageHandler(passObject)
 
+def _warn(text):
+    sys.stderr.write("Qt.py [warning]: %s\n" % text)
 
 
 def _convert(lines):
@@ -1523,12 +1770,67 @@
         sys.stdout.write("Successfully converted \"%s\"\n" % args.convert)
 
 
+class MissingMember(object):
+    """
+    A placeholder type for a missing Qt object not
+    included in Qt.py
+
+    Args:
+        name (str): The name of the missing type
+        details (str): An optional custom error message
+    """
+    ERR_TMPL = ("{} is not a common object across PySide2 "
+                "and the other Qt bindings. It is not included "
+                "as a common member in the Qt.py layer")
+
+    def __init__(self, name, details=''):
+        self.__name = name
+        self.__err = self.ERR_TMPL.format(name)
+
+        if details:
+            self.__err = "{}: {}".format(self.__err, details)
+
+    def __repr__(self):
+        return "<{}: {}>".format(self.__class__.__name__, self.__name)
+
+    def __getattr__(self, name):
+        raise NotImplementedError(self.__err)
+
+    def __call__(self, *a, **kw):
+        raise NotImplementedError(self.__err)
+
+
 def _install():
-    # Default order (customise order and content via QT_PREFERRED_BINDING)
+    # Default order (customize order and content via QT_PREFERRED_BINDING)
     default_order = ("PySide2", "PyQt5", "PySide", "PyQt4")
-    preferred_order = list(
-        b for b in QT_PREFERRED_BINDING.split(os.pathsep) if b
-    )
+    preferred_order = None
+    if QT_PREFERRED_BINDING_JSON:
+        # A per-vendor preferred binding customization was defined
+        # This should be a dictionary of the full Qt.py module namespace to
+        # apply binding settings to. The "default" key can be used to apply
+        # custom bindings to all modules not explicitly defined. If the json
+        # data is invalid this will raise a exception.
+        # Example:
+        #   {"mylibrary.vendor.Qt": ["PySide2"], "default":["PyQt5","PyQt4"]}
+        try:
+            preferred_bindings = json.loads(QT_PREFERRED_BINDING_JSON)
+        except ValueError:
+            # Python 2 raises ValueError, Python 3 raises json.JSONDecodeError
+            # a subclass of ValueError
+            _warn("Failed to parse QT_PREFERRED_BINDING_JSON='%s'"
+                  % QT_PREFERRED_BINDING_JSON)
+            _warn("Falling back to default preferred order")
+        else:
+            preferred_order = preferred_bindings.get(__name__)
+            # If no matching binding was used, optionally apply a default.
+            if preferred_order is None:
+                preferred_order = preferred_bindings.get("default", None)
+    if preferred_order is None:
+        # If a json preferred binding was not used use, respect the
+        # QT_PREFERRED_BINDING environment variable if defined.
+        preferred_order = list(
+            b for b in QT_PREFERRED_BINDING.split(os.pathsep) if b
+        )
 
     order = preferred_order or default_order
 
@@ -1590,6 +1892,22 @@
 
             setattr(our_submodule, member, their_member)
 
+    # Install missing member placeholders
+    for name, members in _missing_members.items():
+        our_submodule = getattr(Qt, name)
+
+        for member in members:
+
+            # If the submodule already has this member installed,
+            # either by the common members, or the site config,
+            # then skip installing this one over it.
+            if hasattr(our_submodule, member):
+                continue
+
+            placeholder = MissingMember("{}.{}".format(name, member),
+                                        details=members[member])
+            setattr(our_submodule, member, placeholder)
+
     # Enable direct import of QtCompat
     sys.modules['Qt.QtCompat'] = Qt.QtCompat
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Qt.py-1.1.0/Qt.py.egg-info/PKG-INFO 
new/Qt.py-1.3.1/Qt.py.egg-info/PKG-INFO
--- old/Qt.py-1.1.0/Qt.py.egg-info/PKG-INFO     2018-01-25 11:56:43.000000000 
+0100
+++ new/Qt.py-1.3.1/Qt.py.egg-info/PKG-INFO     2020-09-20 16:00:45.000000000 
+0200
@@ -1,12 +1,11 @@
 Metadata-Version: 1.1
 Name: Qt.py
-Version: 1.1.0
+Version: 1.3.1
 Summary: Python 2 & 3 compatibility wrapper around all Qt bindings - PySide, 
PySide2, PyQt4 and PyQt5.
 Home-page: https://github.com/mottosso/Qt
 Author: Marcus Ottosson
 Author-email: [email protected]
 License: MIT
-Description-Content-Type: UNKNOWN
 Description: UNKNOWN
 Platform: UNKNOWN
 Classifier: Development Status :: 4 - Beta
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Qt.py-1.1.0/README.md new/Qt.py-1.3.1/README.md
--- old/Qt.py-1.1.0/README.md   2018-01-25 11:53:46.000000000 +0100
+++ new/Qt.py-1.3.1/README.md   2020-09-20 15:58:17.000000000 +0200
@@ -1,7 +1,8 @@
-[![Build 
Status](https://travis-ci.org/mottosso/Qt.py.svg?branch=master)](https://travis-ci.org/mottosso/Qt.py)
 [![PyPI 
version](https://badge.fury.io/py/Qt.py.svg)](https://pypi.python.org/pypi/Qt.py)
-[![Anaconda-Server 
Badge](https://anaconda.org/conda-forge/qt.py/badges/version.svg)](https://anaconda.org/conda-forge/qt.py)
+<img width=260 src=logo.svg>
 
-### Qt.py
+[![Downloads](https://pepy.tech/badge/qt-py)](https://pepy.tech/project/qt-py) 
[![Build 
Status](https://travis-ci.org/mottosso/Qt.py.svg?branch=master)](https://travis-ci.org/mottosso/Qt.py)
 [![PyPI 
version](https://badge.fury.io/py/Qt.py.svg)](https://pypi.python.org/pypi/Qt.py)
+[![Anaconda-Server 
Badge](https://anaconda.org/conda-forge/qt.py/badges/version.svg)](https://anaconda.org/conda-forge/qt.py)
 
[![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/Qt-py/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
+[![Reviewed by 
Hound](https://img.shields.io/badge/Reviewed_by-Hound-8E64B0.svg)](https://houndci.com)
 
 Qt.py enables you to write software that runs on any of the 4 supported 
bindings - PySide2, PyQt5, PySide and PyQt4.
 
@@ -11,7 +12,9 @@
 
 | Date     | Version   | Event
 |:---------|:----------|:----------
-| Dec 2017 | [1.1.0][] | Adds new test suite, new members
+| Sep 2020 | [1.3.0][] | Stability improvements and greater ability for 
`QtCompat.wrapInstance` to do its job
+| Jun 2019 | [1.2.1][] | Bugfixes and [additional 
members](https://github.com/mottosso/Qt.py/releases/tag/1.2.0)
+| Jan 2018 | [1.1.0][] | Adds new test suite, new members
 | Mar 2017 | [1.0.0][] | Increased safety, **backwards incompatible**
 | Sep 2016 | [0.6.9][] | Stable release
 | Sep 2016 | [0.5.0][] | Alpha release of `--convert`
@@ -24,6 +27,8 @@
 [0.6.9]: https://github.com/mottosso/Qt.py/releases/tag/0.6.9
 [1.0.0]: https://github.com/mottosso/Qt.py/releases/tag/1.0.0
 [1.1.0]: https://github.com/mottosso/Qt.py/releases/tag/1.1.0
+[1.2.1]: https://github.com/mottosso/Qt.py/releases/tag/1.2.1
+[1.3.0]: https://github.com/mottosso/Qt.py/releases/tag/1.3.0
 
 ##### Guides
 
@@ -31,6 +36,7 @@
 - [Dealing with Maya 2017 and 
PySide2](https://fredrikaverpil.github.io/2016/07/25/dealing-with-maya-2017-and-pyside2/)
 - [Vendoring 
Qt.py](https://fredrikaverpil.github.io/2017/05/04/vendoring-qt-py/)
 - [Udemy 
Course](https://www.udemy.com/python-for-maya/learn/v4/t/lecture/6027394)
+- [PythonBytes 
#77](https://pythonbytes.fm/episodes/show/77/you-don-t-have-to-be-a-workaholic-to-win)
 (Starts at 5:00)
 
 ##### Table of contents
 
@@ -149,6 +155,8 @@
 | `translate(...)`                                             | `function`  | 
Compatibility wrapper around [QCoreApplication.translate][]
 | `wrapInstance(addr=long, type=QObject)`   | `QObject`   | Wrapper around 
`shiboken2.wrapInstance` and PyQt equivalent
 | `getCppPointer(object=QObject)`           | `long`      | Wrapper around 
`shiboken2.getCppPointer` and PyQt equivalent
+| `isValid(object=QObject)`                 | `bool`      | Wrapper around 
`shiboken2.isValid` and PyQt equivalent
+| `dataChanged(topLeft=QModelIndex, bottomRight=QModelIndex, roles=[])` | 
`None` | Wrapper around `QtCore.QAbstractItemModel.dataChanged.emit`
 
 [QCoreApplication.translate]: 
https://doc.qt.io/qt-5/qcoreapplication.html#translate
 
@@ -178,11 +186,12 @@
 
 These are the publicly facing environment variables that in one way or another 
affect the way Qt.py is run.
 
-| Variable             | Type  | Description
-|:---------------------|:------|:----------
-| QT_PREFERRED_BINDING | str   | Override order and content of binding to try.
-| QT_VERBOSE           | bool  | Be a little more chatty about what's going on 
with Qt.py
-| QT_SIP_API_HINT      | int   | Sets the preferred SIP api version that will 
be attempted to set.
+| Variable                  | Type  | Description
+|:--------------------------|:------|:----------
+| QT_PREFERRED_BINDING_JSON | str   | Override order and content of binding to 
try. This can apply per Qt.py namespace.
+| QT_PREFERRED_BINDING      | str   | Override order and content of binding to 
try. Used if QT_PREFERRED_BINDING_JSON does not apply.
+| QT_VERBOSE                | bool  | Be a little more chatty about what's 
going on with Qt.py
+| QT_SIP_API_HINT           | int   | Sets the preferred SIP api version that 
will be attempted to set.
 
 <br>
 
@@ -221,12 +230,31 @@
 Constrain available choices and order of discovery by supplying multiple 
values.
 
 ```bash
-# Try PyQt first and then PySide, but nothing else.
-$ export QT_PREFERRED_BINDING=PyQt:PySide
+# Try PyQt4 first and then PySide, but nothing else.
+$ export QT_PREFERRED_BINDING=PyQt4:PySide
 ```
 
 Using the OS path separator (`os.pathsep`) which is `:` on Unix systems and 
`;` on Windows.
 
+If you need to control the preferred choice of a specific vendored Qt.py you 
can use the `QT_PREFERRED_BINDING_JSON` environment variable instead.
+
+```json
+{
+    "Qt":["PyQt5"],
+    "myproject.vendor.Qt":["PyQt5"],
+    "default":["PySide2"]
+}
+```
+
+This json data forces any code that uses `import Qt` or `import 
myproject.vendor.Qt` to use PyQt5(`from x import Qt` etc works too, this is 
based on `__name__` of the Qt.py being imported). Any other imports of a Qt 
module will use the "default" PySide2 only. If `"default"` is not provided or a 
Qt.py being used does not support `QT_PREFERRED_BINDING_JSON`, 
`QT_PREFERRED_BINDING` will be respected.
+
+```bash
+# Try PyQt5 first and then PyQt4 for the Qt module name space.
+$ export QT_PREFERRED_BINDING_JSON="{"Qt":["PyQt5","PyQt4"]}"
+# Use PyQt4 for any other Qt module name spaces.
+$ export QT_PREFERRED_BINDING=PySide2
+```
+
 <br>
 
 ##### QtSiteConfig.py
@@ -381,25 +409,33 @@
 Send us a pull-request with your studio here.
 
 - [Atomic Fiction](http://www.atomicfiction.com/)
-- [Industrial Brothers](http://industrialbrothers.com/)
-- [Moonbot Studios](http://moonbotstudios.com/)
-- [Sony Pictures Imageworks](http://www.imageworks.com/)
+- [Bläck](http://www.blackstudios.se/)
+- [Blur Studio](http://www.blur.com)
+- [CGRU](http://cgru.info/)
 - [Colorbleed](http://www.colorbleed.nl/)
-- [Method Studios](http://www.methodstudios.com/)
-- [Framestore](https://framestore.com)
-- [Weta Digital](https://www.wetafx.co.nz/)
+- [Digital Domain](https://www.digitaldomain.com/)
 - [Disney Animation](https://www.disneyanimation.com/)
-- [Industriromantik](http://www.industriromantik.se/)
-- [Psyop](http://www.psyop.com/)
-- [ftrack](https://www.ftrack.com/)
+- [Dreamworks Animation](https://github.com/dreamworksanimation)
+- [Epic Games](https://www.epicgames.com/)
 - [Fido](http://fido.se/)
-- [Bläck](http://www.blackstudios.se/)
-- [CGRU](http://cgru.info/)
+- [Framestore](https://framestore.com)
+- [ftrack](https://www.ftrack.com/)
+- [Futureworks](http://futureworks.in/)
+- [Industrial Brothers](http://industrialbrothers.com/)
+- [Industriromantik](http://www.industriromantik.se/)
+- [Mackevision](http://www.mackevision.com/)
+- [Method Studios](http://www.methodstudios.com/)
+- [Mikros Image](http://www.mikrosimage.com/)
+- [Moonbot Studios](http://moonbotstudios.com/)
 - [MPC](http://www.moving-picture.com)
+- [Overmind Studios](https://www.overmind-studios.de/)
+- [Psyop](http://www.psyop.com/)
+- [Raynault VFX](https://www.raynault.com/)
 - [Rising Sun Pictures](https://rsp.com.au)
-- [Blur Studio](http://www.blur.com)
-- [Mikros Image](http://www.mikrosimage.com/)
-- [Mackevision](http://www.mackevision.com/)
+- [Rodeo FX](https://www.rodeofx.com/en/)
+- [Sony Pictures Imageworks](http://www.imageworks.com/)
+- [Spin VFX](http://www.spinvfx.com/)
+- [Weta Digital](https://www.wetafx.co.nz/)
 
 Presented at Siggraph 2016, BOF!
 
@@ -413,6 +449,7 @@
 
 Send us a pull-request with your project here.
 
+- [USD Manager](http://www.usdmanager.org)
 - [Cosmos](http://cosmos.toolsfrom.space/)
 - [maya-capture-gui](https://github.com/BigRoy/maya-capture-gui)
 - [pyblish-lite](https://github.com/pyblish/pyblish-lite)
@@ -423,6 +460,9 @@
 - [Kraken](https://github.com/fabric-engine/Kraken)
 - [AFANASY](http://cgru.info/afanasy/afanasy)
 - [Syncplay](https://github.com/Syncplay/syncplay)
+- [BlenderUpdater](https://github.com/overmindstudios/BlenderUpdater)
+- [QtPyConvert](https://github.com/DigitalDomain/QtPyConvert)
+- [Pyper](https://gitlab.com/brunoebe/pyper.git)
 
 <br>
 <br>
@@ -439,6 +479,7 @@
 | [QtPy][]      | Scientific    | N/A               | MIT       |      | X     
    | X      |
 | [pyqode.qt][] | Scientific    | PyQt5             | MIT       | X    |       
    | X      |
 | [QtExt][]     | Film          | N/A               | N/A       |      | X     
    |        |
+| [python_qt_binding][] | Robotics | N/A            | BSD       | X    | X     
   | X       | X
 
 Also worth mentioning, 
[pyqt4topyqt5](https://github.com/rferrazz/pyqt4topyqt5); a good starting point 
for transitioning to Qt.py.
 
@@ -448,6 +489,7 @@
 [jupyter]: 
https://github.com/jupyter/qtconsole/blob/master/qtconsole/qt_loaders.py
 [pyqode.qt]: https://github.com/pyQode/pyqode.qt
 [QtExt]: https://bitbucket.org/ftrack/qtext
+[python_qt_binding]: https://github.com/ros-visualization/python_qt_binding
 
 <br>
 <br>
@@ -455,6 +497,8 @@
 
 ### Developer Guide
 
+- [Chat with 
us](https://gitter.im/Qt-py/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
+
 Tests are performed on each aspect of the shim.
 
 - [Functional](tests.py)


Reply via email to