o
    DDi6                     @  s  U d Z ddlm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	m
Z
mZmZ ddlmZ ddlmZ ddlmZmZmZmZ dd	lmZ dd
lmZ ddlmZ ejZejZejZ ej!Z"ejZ#ejZ$ejZ%e&e'Z(ej)dkrxd4ddZ*nd4ddZ*d5d6ddZ+d5d7ddZ,d5d6dd Z-d5d7d!d"Z.d5d6d#d$Z/e0ed%reej1ej2B eej1ej3B e ej1ej2B ej3B iZ4ni Z4d5d6d&d'Z5e0ed(reej6eej7e ej6ej7B iZ8ej6ej7B  Z9ni Z8d5d6d)d*Z:d8d,d-Z;erej<Z<d.e=d/< d0ej>v rej>d0 Z?e?@d1re?eA vreBd2e?eA e? ZCdS er'ej)dkr'e; s'e<ZCdS ejeDed3du r5e/ZCdS e0ed(r?e:ZCdS e+ZCdS )9z
Code concerned with waiting in different contexts (blocking, async, etc).

These functions are designed to consume the generators returned by the
`generators` module function and to return their final value.

    )annotationsN)EventTimeoutErrorget_event_loopwait_for)DefaultSelector   )errors)RVPQGen	PQGenConnWaitFunc)Ready)Wait)_psycopgwin32filenointreturnNonec              
   C  s6   zt |  W dS  ty } ztd|d}~ww )zC
        Raise OperationalError if the connection is lost.
        connection socket closedN)osfstat	ExceptioneOperationalError)r   ex r   H/var/www/Datamplify/venv/lib/python3.10/site-packages/psycopg/waiting.py_check_fd_closed(   s   r   c                 C  s   d S Nr   )r   r   r   r   r   4   s           gen	PQGen[RV]intervalfloatr
   c           	   
   C  s   |du rt dz>t| }t ,}||| 	 |j|d }s*t| | t q|d d }| |}||| q1 s?w   Y  W dS  ty] } z|j	}|W  Y d}~S d}~ww )a  
    Wait for a generator using the best strategy available.

    :param gen: a generator performing database operations and yielding
        `Ready` values when it would block.
    :param fileno: the file descriptor to wait on.
    :param interval: interval (in seconds) to check for other interrupt, e.g.
        to allow Ctrl-C.
    :return: whatever `!gen` returns on completion.

    Consume `!gen`, scheduling `fileno` for completion when it is reported to
    block. Once ready again send the ready state back to `!gen`.
    N%indefinite wait not supported anymoreTtimeoutr   r   )

ValueErrornextr   registerselectr   send
READY_NONEStopIterationvalue)	r"   r   r$   sselrlistreadyr   rvr   r   r   wait_selector8   s*   

r6   PQGenConn[RV]c           	   
   C  s   |du rt dzCt| \}}t /}||| 	 |j|d }s(| t q|| |d d }| |\}}||| q1 sDw   Y  W dS  tyb } z|j	}|W  Y d}~S d}~ww )a  
    Wait for a connection generator using the best strategy available.

    :param gen: a generator performing database operations and yielding
        (fd, `Ready`) pairs when it would block.
    :param interval: interval (in seconds) to check for other interrupt, e.g.
        to allow Ctrl-C.
    :return: whatever `!gen` returns on completion.

    Behave like in `wait()`, but take the fileno to wait from the generator
    itself, which might change during processing.
    Nr&   Tr'   r   r   )
r)   r*   r   r+   r,   r-   r.   
unregisterr/   r0   )	r"   r$   r   r1   r2   r3   r4   r   r5   r   r   r   	wait_conn\   s*   

r9   c           
   
     s\  |du r	t dt  t }d fdd}znt| }	 |t@ }|t@ }|s1|s1td
|    d|r@|	||t
 |rI|||t z&zt  |I dH  W n	 ty_   Y nw W |rh|| |ro|| n|rw|| |r|| w w | }q ty } ztd|d}~w ty } z|j}	|	W  Y d}~S d}~ww )a  
    Coroutine waiting for a generator to complete.

    :param gen: a generator performing database operations and yielding
        `Ready` values when it would block.
    :param fileno: the file descriptor to wait on.
    :param interval: interval (in seconds) to check for other interrupt, e.g.
        to allow Ctrl-C.
    :return: whatever `!gen` returns on completion.

    Behave like in `wait()`, but exposing an `asyncio` interface.
    Nr&   stater   r   r   c                   s   | O     d S r    setr:   evr4   r   r   wakeup   s   zwait_async.<locals>.wakeupTbad poll status: r   r   r:   r   r   r   )r)   r   r   r*   WAIT_RWAIT_Wr   InternalErrorclear
add_readerREADY_R
add_writerREADY_Wr   waitr   remove_readerremove_writerr-   OSErrorr   r/   r0   )
r"   r   r$   loopr@   r1   readerwriterr   r5   r   r>   r   
wait_async~   s\   



rR   c           
   
     sT  |du r	t dt  t }d fdd}z{t| \}}	 |t@ }|t@ }|s3|s3td
|    d|rB|	||t
 |rK|||t z/|rdzt  |I dH  W n tyc   Y nw   I dH  W |rs|| |rz|| n|r|| |r|| w w | \}}q ty } z|j}	|	W  Y d}~S d}~ww )a  
    Coroutine waiting for a connection generator to complete.

    :param gen: a generator performing database operations and yielding
        (fd, `Ready`) pairs when it would block.
    :param interval: interval (in seconds) to check for other interrupt, e.g.
        to allow Ctrl-C.
    :return: whatever `!gen` returns on completion.

    Behave like in `wait()`, but take the fileno to wait from the generator
    itself, which might change during processing.
    Nr&   r:   r   r   r   c                   s   |     d S r    r;   r=   r>   r   r   r@      s   zwait_conn_async.<locals>.wakeupTrA   r   rB   )r)   r   r   r*   rC   rD   r   rE   rF   rG   rH   rI   rJ   r   rK   r   rL   rM   r-   r/   r0   )
r"   r$   rO   r@   r   r1   rP   rQ   r   r5   r   r>   r   wait_conn_async   sZ   


rS   c              
   C  s   |du rt dz>t| }d}|f}	 t|t@ r|n||t@ r"|n|||\}}}|r5t| tdd}	|r;t}	|rA|	t	O }	| 
|	}q tyX }
 ztd|
d}
~
w tyn }
 z|
j}|W  Y d}
~
S d}
~
ww )z
    Wait for a generator using select where supported.

    BUG: on Linux, can't select on FD >= 1024. On Windows it's fine.
    Nr&   r   Tr   r   )r)   r*   r,   rC   rD   r   r   r   rH   rJ   r-   rN   r/   r0   )r"   r   r$   r1   emptyfnlistrlwlxlr4   r   r5   r   r   r   wait_select   s>   


rY   EpollSelectorc              
   C  s   |du rt dz^t| }|dk rd}t E}t| }||| 	 || }s4t| | t	 q"|d d }d}|tj
@ rCt}|tj@ rL|tO }| |}t| }||| q#1 s_w   Y  W dS  ty} }	 z|	j}
|
W  Y d}	~	S d}	~	ww )a$  
    Wait for a generator using epoll where supported.

    Parameters are like for `wait()`. If it is detected that the best selector
    strategy is `epoll` then this function will be used instead of `wait`.

    See also: https://linux.die.net/man/2/epoll_ctl

    BUG: if the connection FD is closed, `epoll.poll()` hangs. Same for
    EpollSelector. For this reason, wait_poll() is currently preferable.
    To reproduce the bug:

        export PSYCOPG_WAIT_FUNC=wait_epoll
        pytest tests/test_concurrency.py::test_concurrent_close
    Nr&   r   r!   Tr   )r)   r*   r,   epoll_epoll_evmasksr+   pollr   r-   r.   EPOLLINrH   EPOLLOUTrJ   modifyr/   r0   )r"   r   r$   r1   r[   evmaskfileevsr?   r4   r   r5   r   r   r   
wait_epoll-  s<   




rc   PollSelectorc              
   C  s  |du rt dzdt| }|dk rd}nt|d }t }t| }||| 	 || }s6| t q(|d d }d}|tj	@ rEt
}|tj@ rN|tO }|s]|t@ r]t| td| |}t| }||| q) ty }	 z|	j}
|
W  Y d}	~	S d}	~	ww )za
    Wait for a generator using poll where supported.

    Parameters are like for `wait()`.
    Nr&   r   g     @@Tr   r   )r)   r*   r   r,   r]   _poll_evmasksr+   r-   r.   POLLINrH   POLLOUTrJ   POLL_BADr   r   r   r`   r/   r0   )r"   r   r$   r1   r]   ra   rb   r?   r4   r   r5   r   r   r   	wait_pollg  s@   




ri   boolc               
   C  s^   t jd } r-z| drW dS W dS  ty, } ztd| W Y d}~dS d}~ww dS )z
    Detect if some greenlet library has patched the select library.

    If this is the case, avoid to use the wait_c function as it doesn't behave
    in a collaborative way.

    Currently supported: gevent.
    zgevent.monkeyr,   Tz+failed to detect gevent monkey-patching: %sNF)sysmodulesgetis_module_patchedr   loggerwarning)mr   r   r   r   _is_select_patched  s   

rr   r   rK   PSYCOPG_WAIT_FUNCwait_zHPSYCOPG_WAIT_FUNC should be the name of an available wait function; got SelectSelector)r   r   r   r   )r!   )r"   r#   r   r   r$   r%   r   r
   )r"   r7   r$   r%   r   r
   )r   rj   )E__doc__
__future__r   r   rk   r,   logging	selectorsasyncior   r   r   r   r    r	   r   abcr
   r   r   r   _enumsr   r   _cmoduler   RrC   WrD   RWWAIT_RWNONEr.   rH   rJ   READY_RW	getLogger__name__ro   platformr   r6   r9   rR   rS   rY   hasattrEPOLLONESHOTr^   r_   r\   rc   rf   rg   re   rh   ri   rr   wait_c__annotations__environfname
startswithglobalsImportErrorrK   getattrr   r   r   r   <module>   s    



$"=@
(
/
.
