1"""
2NOTE: Importing this module will select and commit to a Qt API.
3"""
4
5import os
6import sys
7import warnings
8
9import AnyQt
10
11if sys.version_info < (3,):
12    _intern = intern
13else:
14    _intern = sys.intern
15
16USED_API = None
17
18QT_API_PYQT5 = "pyqt5"
19QT_API_PYQT4 = "pyqt4"
20QT_API_PYSIDE = "pyside"
21QT_API_PYSIDE2 = "pyside2"
22
23def comittoapi(api):
24    """
25    Commit to the use of specified Qt api.
26
27    Raise an error if another Qt api is already loaded in sys.modules
28
29    """
30    global USED_API
31    assert USED_API is None, "committoapi called again!"
32    check = ["PyQt4", "PyQt5", "PySide", "PySide2"]
33    assert api in [QT_API_PYQT5, QT_API_PYQT4, QT_API_PYSIDE, QT_API_PYSIDE2]
34    for name in check:
35        if name.lower() != api and name in sys.modules:
36            raise RuntimeError(
37                "{} was already imported. Cannot commit to {}!"
38                .format(name, api)
39            )
40    else:
41        api = _intern(api)
42        USED_API = api
43        AnyQt.__SELECTED_API = api
44        AnyQt.USED_API = api
45
46if AnyQt.__SELECTED_API is not None:
47    comittoapi(AnyQt.__SELECTED_API)
48elif "QT_API" in os.environ:
49    api = os.environ["QT_API"].lower()
50    if api == "pyqt":
51        # Qt.py allows both pyqt4 and pyqt to specify PyQt4.
52        # When run from anaconda-navigator, pyqt is used.
53        api = "pyqt4"
54    if api in [QT_API_PYQT4, QT_API_PYQT5, QT_API_PYSIDE, QT_API_PYSIDE2]:
55        comittoapi(api)
56    else:
57        warnings.warn(
58            "'QT_API' environment variable names an unknown Qt API ('{}')."
59            .format(os.environ["QT_API"]),
60            RuntimeWarning, stacklevel=3)
61        # pass through
62
63if USED_API is None:
64    # Check sys.modules for existing imports
65    __existing = None
66    if "PyQt5" in sys.modules:
67        __existing = QT_API_PYQT5
68    elif "PyQt4" in sys.modules:
69        __existing = QT_API_PYQT4
70    elif "PySide2" in sys.modules:
71        __existing = QT_API_PYSIDE2
72    elif "PySide" in sys.modules:
73        __existing = QT_API_PYSIDE
74
75    if __existing is not None:
76        comittoapi(__existing)
77    else:
78        available = AnyQt.availableapi()
79        __available = None
80
81        if AnyQt.__PREFERRED_API is not None and \
82                AnyQt.__PREFERRED_API.lower() in [name.lower() for name in available]:
83            __available = AnyQt.__PREFERRED_API.lower()
84        elif "PyQt5" in available:
85            __available = QT_API_PYQT5
86        elif "PyQt4" in available:
87            __available = QT_API_PYQT4
88        elif "PySide" in available:
89            __available = QT_API_PYSIDE
90        elif "PySide2" in available:
91            __available = QT_API_PYSIDE2
92
93        if __available is not None:
94            comittoapi(__available)
95        del __available
96
97    del __existing
98
99if USED_API is None:
100    raise ImportError("PyQt4, PyQt5, PySide or PySide2 are not available for import")
101
102
103if "ANYQT_HOOK_DENY" in os.environ:
104    from AnyQt.importhooks import install_deny_hook
105    for __denyapi in os.environ["ANYQT_HOOK_DENY"].split(","):
106        if __denyapi.lower() != USED_API:
107            install_deny_hook(__denyapi.lower())
108    del install_deny_hook
109
110if "ANYQT_HOOK_BACKPORT" in os.environ:
111    from AnyQt.importhooks import install_backport_hook
112    for __backportapi in os.environ["ANYQT_HOOK_BACKPORT"].split(","):
113        if __backportapi.lower() != USED_API:
114            install_backport_hook(__backportapi.lower())
115    del install_backport_hook
116