o
    6	f1                  	   @   s  U 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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mZmZmZ dd	lmZ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$e%Z&d'dee de'dee( defddZ)d'dee dee( defddZ*	d'dee de'dee( defddZ+d'dee dee( defddZ,d'dee de'dee( defddZ-e.edreej/ej0B ej1B eej/ej2B ej1B e ej/ej0ej2B ej1B B iZ3ni Z3d'dee de'dee( defddZ4e.edreej5eej6e ej5ej6B iZ7ni Z7d'dee de'dee( defddZ8de9fdd Z:er-ej;Z;ee<d!< d"ej=v rVej=d" Z>e>?d#rHe>e@ vrOeAd$e>e@ e> ZBdS ergejCd%krge: sge;ZBdS ejeDed&du rue-ZBdS e.edre8ZBdS e)ZBdS )(z
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.

    N)Optional)get_event_loopwait_forEventTimeoutError)DefaultSelector   )errors)RVPQGen	PQGenConnWaitFunc)WaitReady)_psycopggenfilenotimeoutreturnc           	   
   C   s   z=t | }t +}	 ||| d}|s|j|d}|r|| |d d }||@ s-J | |}q
1 s6w   Y  W dS  ty[ } z|jrM|jd nd}|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 timeout: timeout (in seconds) to check for other interrupt, e.g.
        to allow Ctrl-C.
    :type timeout: float
    :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`.
    TNr   r   r   )nextr   registerselect
unregistersendStopIterationargs)	r   r   r   sselrlistreadyexrv r#   H/home/ertert/spirit/venv/lib/python3.10/site-packages/psycopg/waiting.pywait_selector$   s(   

r%   c           	   
   C   s   z@t | \}}|sd}t (}	 ||| |j|d}|| |s(td|d d }| |\}}q1 s9w   Y  W dS  ty^ } z|j	rP|j	d nd}|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 timeout: timeout (in seconds) to check for other interrupt, e.g.
        to allow Ctrl-C. If zero or None, wait indefinitely.
    :type timeout: float
    :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.
    NTr   connection timeout expiredr   r   )
r   r   r   r   r   eConnectionTimeoutr   r   r   )	r   r   r   r   r   r   r    r!   r"   r#   r#   r$   	wait_connF   s(   


r)   c           
   
      sX  t   t }dtddf fdd}zzt| }	 |t@ }|t@ }|s-|s-td|    d|r<|	||t
 |rE|||t z2|du rR  I dH  nzt  |I dH  W n	 tyg   Y nw W |rp|| |rw|| n|r|| |r|| w w | }q ty } z|jr|jd nd}	|	W  Y d}~S d}~ww )	aW  
    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.
    :return: whatever `!gen` returns on completion.

    Behave like in `wait()`, but exposing an `asyncio` interface.
    stater   Nc                    s   | O     d S Nsetr*   evr    r#   r$   wakeup{   s   zwait_async.<locals>.wakeupTbad poll status: r   )r   r   r   r   WAIT_RWAIT_Wr'   InternalErrorclear
add_readerREADY_R
add_writerREADY_Wwaitr   r   remove_readerremove_writerr   r   r   )
r   r   r   loopr1   r   readerwriterr!   r"   r#   r/   r$   
wait_asyncg   sV   



rA   c           
   
      sN  t   t }dtddf fdd}zjt| \}}|sd}	 |t@ }|t@ }|s3|s3td|    d|rB|	||t
 |rK|||t zt  |I dH  W |r^|| |re|| n|rm|| |ru|| w w | \}}q ty   td	 ty } z|jr|jd nd}	|	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 timeout: timeout (in seconds) to check for other interrupt, e.g.
        to allow Ctrl-C. If zero or None, wait indefinitely.
    :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.
    r*   r   Nc                    s   |     d S r+   r,   r.   r/   r#   r$   r1      s   zwait_conn_async.<locals>.wakeupTr2   r   r&   )r   r   r   r   r3   r4   r'   r5   r6   r7   r8   r9   r:   r   r;   r<   r=   r   r   r(   r   r   )
r   r   r>   r1   r   r   r?   r@   r!   r"   r#   r/   r$   wait_conn_async   sP   



rB   c              
   C   s   z6t | }d}|f}	 t|t@ r|n||t@ r|n|||\}}}d}	|r(t}	|r.|	tO }	|	s1q
| |	}q tyT }
 z|
jrF|
jd nd}|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.
    r#   Tr   N)	r   r   r3   r4   r8   r:   r   r   r   )r   r   r   r   emptyfnlistrlwlxlr    r!   r"   r#   r#   r$   wait_select   s2   

rH   EpollSelectorc              
   C   s  zet | }|du s|dk rd}nt|d }t A}t| }||| 	 d}|s1||}|r*|d d }d}|tj @ rAt}|tj	 @ rK|t
O }| |}t| }||| q&1 s^w   Y  W dS  ty }	 z|	jru|	jd nd}
|
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        @@Tr   )r   intr   epoll_epoll_evmasksr   pollEPOLLOUTr8   EPOLLINr:   r   modifyr   r   )r   r   r   r   rL   evmaskfileevsr0   r    r!   r"   r#   r#   r$   
wait_epoll	  s:   


rT   PollSelectorc              
   C   s   zYt | }|du s|dk rd}nt|d }t }t| }||| 	 d}|s0||}|r)|d d }d}|tj @ r@t}|tj @ rJ|t	O }| 
|}t| }||| q% tyw }	 z|	jri|	jd nd}
|
W  Y d}	~	S d}	~	ww )za
    Wait for a generator using poll where supported.

    Parameters are like for `wait()`.
    Nr   rJ   Tr   )r   rK   r   rN   _poll_evmasksr   POLLOUTr8   POLLINr:   r   rQ   r   r   )r   r   r   r   rN   rR   rS   r0   r    r!   r"   r#   r#   r$   	wait_pollB  s8   

rY   c               
   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_patched	Exceptionloggerwarning)mr!   r#   r#   r$   _is_select_patchedg  s   

rb   r;   PSYCOPG_WAIT_FUNCwait_zHPSYCOPG_WAIT_FUNC should be the name of an available wait function; got win32SelectSelectorr+   )E__doc__osrZ   r   logging	selectorstypingr   asyncior   r   r   r   r    r	   r'   abcr
   r   r   r   _enumsr   r   _cmoduler   Rr3   Wr4   RWWAIT_RWr8   r:   READY_RW	getLogger__name__r_   rK   floatr%   r)   rA   rB   rH   hasattrEPOLLONESHOTrP   EPOLLERRrO   rM   rT   rX   rW   rV   rY   boolrb   wait_c__annotations__environfname
startswithglobalsImportErrorr;   platformgetattrr#   r#   r#   r$   <module>   s    
$ ""
 :$<
!$/$%
