U
    Fvfi"                  	   @   s  d Z ddlZddlZddlZddlZddlZddlZddlZddlZddl	m
Z ddlZddlmZ dZdZdZd	Zejd
Zedk	re ZeeeedZejdreZnejdreZnejdreZnejdreZnrej pd dredkree ZndZdZn:edkr.dZn*eekrBee Zneded edd Z!eeeeefkrze!  nedkrere!efe!efgZ"ne!efe!efe!efe!efgZ"e"D ]8\Z#Zz
e#  W n e$k
r   Y qY nX  qqe$dd e% ne&de e't(j)* + Z,e,dk rTe$dt(j)* -  dejdkree. d edkre,dk rej/d d! e0dd"d# Z1d$d% Z2ej3d&d' Z4dS )(a[  
Qt binding and backend selector.

The selection logic is as follows:
- if any of PyQt6, PySide6, PyQt5, or PySide2 have already been
  imported (checked in that order), use it;
- otherwise, if the QT_API environment variable (used by Enthought) is set, use
  it to determine which binding to use;
- otherwise, use whatever the rcParams indicate.
    N)parse   )_QT_FORCE_QT5_BINDINGPyQt6PySide6PyQt5PySide2QT_API)Zpyqt6Zpyside6pyqt5pyside2zPyQt6.QtCorezPySide6.QtCorezPyQt5.QtCorezPySide2.QtCore Zqt5)r
   r   TzTThe environment variable QT_API has the unrecognized value {!r}; valid values are {}z, c                     st  t tkrRddlmamamam}  tjatj	t_
tjt_tjt_| jatdant tkrddlmamamama dd lfddatttdkrtdantant tkrddlmamama dd l} tjatj	t_
tjt_tjt_| jatanrt tkrZddlmamamama zdd	lm  W n tk
rF   dd l Y nX  fd
datantdt  tj j!a"d S )Nr   )QtCoreQtGui	QtWidgetssipvalue)r   r   r   __version__c                    s     |  S NZisValidobj)	shiboken6 A/tmp/pip-unpacked-wheel-7vhvci0g/matplotlib/backends/qt_compat.py
_isdeletedU       r   z6.4)r   r   r   	shiboken2c                    s     |  S r   r   r   r   r   r   r   i   s    Unexpected QT_API: )#r	   QT_API_PYQT6r   r   r   r   r   ZPYQT_VERSION_STRr   Z
pyqtSignalZSignalZpyqtSlotZSlotZpyqtPropertyZPropertyZ	isdeletedr   operator
attrgetterZ_to_intQT_API_PYSIDE6r   r   parse_versionintQT_API_PYQT5r   QT_API_PYSIDE2r   r   ImportErrorAssertionErrorZQFileDialogZgetSaveFileNameZ_getSaveFileName)r   r   )r   r   r   _setup_pyqt5plusF   sD    
r)   z<Failed to import any of the following Qt binding modules: {}r   )   
   zThe Qt version imported is z! but Matplotlib requires Qt>=5.10darwinz10.16)r*         ZQT_MAC_WANTS_LAYER1c                 C   s,   t tdkr| n| dd tjtj S )Nr   .r   )r    r!   r	   
rpartitionsysmodulesr   __package__)namer   r   r   _enum   s
    
r6   c                 C   s   t | dr|  n|   d S )Nexec)hasattrr7   exec_r   r   r   r   _exec   s    r:   c              
   #   s   t t j}d d}|dt jt jfkr,d}ntt \}|d t |	 }t
	 tdj}d |jjfdd} fdd}t  t j| z
dV  W 5 |s|    |d t | t  t j|  dk	r|   X dS )	aN  
    This manager allows to terminate a plot by sending a SIGINT. It is
    necessary because the running Qt backend prevents Python interpreter to
    run and process signals (i.e., to raise KeyboardInterrupt exception). To
    solve this one needs to somehow wake up the interpreter and make it close
    the plot window. We do this by using the signal.set_wakeup_fd() function
    which organizes a write of the signal number into a socketpair connected
    to the QSocketNotifier (since it is part of the Qt backend, it can react
    to that write event). Afterwards, the Qt handler empties the socketpair
    by a recv() command to re-arm it (we need this if a signal different from
    SIGINT was caught by set_wakeup_fd() and we shall continue waiting). If
    the SIGINT was caught indeed, after exiting the on_signal() function the
    interpreter reacts to the SIGINT according to the handle() function which
    had been set up by a signal.signal() call: it causes the qt_object to
    exit by calling its quit() method. Finally, we call the old SIGINT
    handler with the same arguments that were given to our custom handle()
    handler.

    We do this only if the old handler for SIGINT was not None, which means
    that a non-python handler was installed, i.e. in Julia, and not SIG_IGN
    which means we should ignore the interrupts.
    NFTzQtCore.QSocketNotifier.Typec                     s(   z  d W n tk
r"   Y nX d S )Nr   )recvBlockingIOErrorargs)rsockr   r   _may_clear_sock   s    z/_maybe_allow_interrupt.<locals>._may_clear_sockc                     s   |     d S r   )quitr=   )handler_argsqappr   r   handle   s    z&_maybe_allow_interrupt.<locals>.handle)signal	getsignalSIGINTSIG_IGNSIG_DFLsocket
socketpairsetblockingset_wakeup_fdfilenor   ZQSocketNotifierr6   ZReadZ	activatedconnectcloseZ
setEnabled)rC   Zold_sigint_handlerskipZwsockZold_wakeup_fdZsnr@   rD   r   )rB   rC   r?   r   _maybe_allow_interrupt   s6    
 




rR   )5__doc__	functoolsr    osplatformr2   rE   rJ   
contextlibZpackaging.versionr   r#   Z
matplotlibZmplr   r   r   r"   r%   r&   environgetZ
QT_API_ENVlowerZ_ETSr3   r	   ZrcParamsZ_get_backend_or_none
startswithRuntimeErrorformatjoinr)   _candidates_setupr'   valuesr(   tupler   ZQLibraryInfoversionsegmentsZ_version_infotoStringmac_ver
setdefault	lru_cacher6   r:   contextmanagerrR   r   r   r   r   <module>   s     




 +





