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.

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:
        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)