1import importlib 
    2import os 
    3from typing import Tuple, Callable 
    4 
    5aliases = { 
    6    'qt4': 'qt', 
    7    'gtk2': 'gtk', 
    8} 
    9 
    10backends = [ 
    11    "qt", 
    12    "qt5", 
    13    "qt6", 
    14    "gtk", 
    15    "gtk2", 
    16    "gtk3", 
    17    "gtk4", 
    18    "tk", 
    19    "wx", 
    20    "pyglet", 
    21    "glut", 
    22    "osx", 
    23    "asyncio", 
    24] 
    25 
    26registered = {} 
    27 
    28def register(name, inputhook): 
    29    """Register the function *inputhook* as an event loop integration.""" 
    30    registered[name] = inputhook 
    31 
    32 
    33class UnknownBackend(KeyError): 
    34    def __init__(self, name): 
    35        self.name = name 
    36 
    37    def __str__(self): 
    38        return ("No event loop integration for {!r}. " 
    39                "Supported event loops are: {}").format(self.name, 
    40                                    ', '.join(backends + sorted(registered))) 
    41 
    42 
    43def set_qt_api(gui): 
    44    """Sets the `QT_API` environment variable if it isn't already set.""" 
    45 
    46    qt_api = os.environ.get("QT_API", None) 
    47 
    48    from IPython.external.qt_loaders import ( 
    49        QT_API_PYQT, 
    50        QT_API_PYQT5, 
    51        QT_API_PYQT6, 
    52        QT_API_PYSIDE, 
    53        QT_API_PYSIDE2, 
    54        QT_API_PYSIDE6, 
    55        QT_API_PYQTv1, 
    56        loaded_api, 
    57    ) 
    58 
    59    loaded = loaded_api() 
    60 
    61    qt_env2gui = { 
    62        QT_API_PYSIDE: "qt4", 
    63        QT_API_PYQTv1: "qt4", 
    64        QT_API_PYQT: "qt4", 
    65        QT_API_PYSIDE2: "qt5", 
    66        QT_API_PYQT5: "qt5", 
    67        QT_API_PYSIDE6: "qt6", 
    68        QT_API_PYQT6: "qt6", 
    69    } 
    70    if loaded is not None and gui != "qt": 
    71        if qt_env2gui[loaded] != gui: 
    72            print( 
    73                f"Cannot switch Qt versions for this session; will use {qt_env2gui[loaded]}." 
    74            ) 
    75            return qt_env2gui[loaded] 
    76 
    77    if qt_api is not None and gui != "qt": 
    78        if qt_env2gui[qt_api] != gui: 
    79            print( 
    80                f'Request for "{gui}" will be ignored because `QT_API` ' 
    81                f'environment variable is set to "{qt_api}"' 
    82            ) 
    83            return qt_env2gui[qt_api] 
    84    else: 
    85        if gui == "qt5": 
    86            try: 
    87                import PyQt5  # noqa 
    88 
    89                os.environ["QT_API"] = "pyqt5" 
    90            except ImportError: 
    91                try: 
    92                    import PySide2  # noqa 
    93 
    94                    os.environ["QT_API"] = "pyside2" 
    95                except ImportError: 
    96                    os.environ["QT_API"] = "pyqt5" 
    97        elif gui == "qt6": 
    98            try: 
    99                import PyQt6  # noqa 
    100 
    101                os.environ["QT_API"] = "pyqt6" 
    102            except ImportError: 
    103                try: 
    104                    import PySide6  # noqa 
    105 
    106                    os.environ["QT_API"] = "pyside6" 
    107                except ImportError: 
    108                    os.environ["QT_API"] = "pyqt6" 
    109        elif gui == "qt": 
    110            # Don't set QT_API; let IPython logic choose the version. 
    111            if "QT_API" in os.environ.keys(): 
    112                del os.environ["QT_API"] 
    113        else: 
    114            print(f'Unrecognized Qt version: {gui}. Should be "qt5", "qt6", or "qt".') 
    115            return 
    116 
    117        # Import it now so we can figure out which version it is. 
    118        from IPython.external.qt_for_kernel import QT_API 
    119 
    120        return qt_env2gui[QT_API] 
    121 
    122 
    123def get_inputhook_name_and_func(gui: str) -> Tuple[str, Callable]: 
    124    if gui in registered: 
    125        return gui, registered[gui] 
    126 
    127    if gui not in backends: 
    128        raise UnknownBackend(gui) 
    129 
    130    if gui in aliases: 
    131        return get_inputhook_name_and_func(aliases[gui]) 
    132 
    133    gui_mod = gui 
    134    if gui.startswith("qt"): 
    135        gui = set_qt_api(gui) 
    136        gui_mod = "qt" 
    137 
    138    mod = importlib.import_module("IPython.terminal.pt_inputhooks." + gui_mod) 
    139    return gui, mod.inputhook