U
    ڲg0                     @  sN  d Z ddlmZ ddlZddl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mZ dd
lmZmZ ddlmZ ddlmZ ddlmZ ejjZejjZejjZ ejj!Z"ejj#Z$ejj%Z&ej'j(Z(ej'j)Z)ej'j*Z*ej'j+Z+ej'j,Z,ej-Z.ej/Z0ej1Z2ej-Z3ej/Z4ej1Z5e6e7Z8ddddddddZ9ddddddddZ:dddddZ;dd dd!d"Z<dddd#d$Z=dd%dd&d'Z>dd(d)d*d+d,Z?dd-dd.d/Z@dd0dd1d2ZAdd3dd4d5ZBdAdd7d8d d9d:d;ZCdd<d=d>d?d@ZDer.ejEZEejFZFejGZGejHZHejIZIejJZJejKZKne9ZEe:ZFe;ZGe<ZHe=ZIe>ZJe?ZKdS )Ba  
Generators implementing communication protocols with the libpq

Certain operations (connection, querying) are an interleave of libpq calls and
waiting for the socket to be ready. This module contains the code to execute
the operations, yielding a polling state whenever there is to wait. The
functions in the `waiting` module are the ones who wait more or less
cooperatively for the socket to be ready and make these generators continue.

These generators yield `Wait` objects whenever an operation would block. These
generators assume the connection fileno will not change. In case of the
connection function, where the fileno may change, the generators yield pairs
(fileno, `Wait`).

The generator can be restarted sending the appropriate `Ready` state when the
file descriptor is ready. If a None value is sent, it means that the wait
function timed out without any file descriptor becoming ready; in this case the
generator should probably yield the same value again in order to wait more.
    )annotationsN)	monotonic   )pq)errors)BufferPipelineCommandPQGen	PQGenConn)PGcancelConnPGconnPGresult)WaitReady)Deque)_psycopg)conninfo_encoding        )timeoutstrfloatzPQGenConn[PGconn])conninfor   returnc                c  s  |rt  | nd}tj|  }|jtkrNt| }tj	d|
| |d| }|tksf|tkr|tkrrtnt}|j|fV }|rt  |krtd|rvqqvq"|tkrqq"|tkrt| }tj	d|
| t|dq"tjd| t|dq"d|_|S )zE
    Generator to create a database connection without blocking.
    r   zconnection is bad: )pgconnzconnection timeout expiredzconnection failed: unexpected poll status: r   )r   r   r   Zconnect_startencodestatusBADr   eOperationalErrorget_error_messageZconnect_pollPOLL_READINGPOLL_WRITINGWAIT_RWAIT_WsocketZConnectionTimeoutPOLL_OKPOLL_FAILEDZfinish_pgconnInternalErrorZnonblocking)r   r   deadlineconnencodingr   waitready r.   6/tmp/pip-unpacked-wheel-b_ea6rx_/psycopg/generators.py_connect=   s<    

 r0   r   zPQGenConn[None])cancel_connr   r   c                c  s   |rt  | nd}|r*t  |kr*td|  }|tkr>qq|tkrT| jtfV  q|tkrj| jt	fV  q|t
krtd|   qtd| qd S )Nr   zcancellation timeout expiredzcancellation failed: r   )r   r   ZCancellationTimeoutpollr&   r!   r%   r#   r"   r$   r'   r   r    r(   )r1   r   r)   r   r.   r.   r/   _cancelh   s    
r3   r   zPQGen[list[PGresult]])r   r   c                 c  s    t | E dH  t| E dH }|S )aG  
    Generator sending a query and returning results without blocking.

    The query must have already been sent using `pgconn.send_query()` or
    similar. Flush the query and then return the result using nonblocking
    functions.

    Return the list of results returned by the database (whether success
    or error).
    N)_send_fetch_many)r   rvr.   r.   r/   _execute|   s    r7   zPQGen[None]c                 c  s6   |   }|dkrq2tV }|rq q|t@ r |   q dS )aZ  
    Generator to send a query to the server without blocking.

    The query must have already been sent using `pgconn.send_query()` or
    similar. Flush the query and then return the result using nonblocking
    functions.

    After this generator has finished you may want to cycle using `fetch()`
    to retrieve the results available.
    r   N)flushWAIT_RWREADY_Rconsume_input)r   fr-   r.   r.   r/   r4      s    r4   c                 c  sf   g }t | E dH }|sqb|| |j}|tksb|tksb|tkrBqb|tkrt|dksbt|qbq|S )a  
    Generator retrieving results from the database without blocking.

    The query must have already been sent to the server, so pgconn.flush() has
    already returned 0.

    Return the list of results returned by the database (whether success
    or error).
    Nr   )	_fetchappendr   COPY_INCOPY_OUT	COPY_BOTHPIPELINE_SYNClenAssertionError)r   resultsresr   r.   r.   r/   r5      s    

r5   zPQGen[PGresult | None]c                 c  sH   |   r8tV }|rqq|   |   s(q8tV }|r(qq(qt|  |  S )z
    Generator retrieving a single result from the database without blocking.

    The query must have already been sent to the server, so pgconn.flush() has
    already returned 0.

    Return a result from the database (whether success or error).
    )is_busyr#   r;   _consume_notifies
get_result)r   r-   r.   r.   r/   r=      s    	r=   zDeque[PipelineCommand]zPQGen[list[list[PGresult]]])r   commandsr   c                 c  s   g }t V }|rqq|t@ r|   t|  g }|  s|  }|dkr\|sLq|| g }q.|j}|tkr|rrt	||g q.|t
ks|tks|tkrtdq.|| q.|t@ r|   |sq|   q|S )zGenerator to send queries from a connection in pipeline mode while also
    receiving results.

    Return a list results, including single PIPELINE_SYNC elements.
    Nz$COPY cannot be used in pipeline mode)r9   r:   r;   rH   rG   rI   r>   r   rB   rD   r?   r@   rA   r   ZNotSupportedErrorREADY_Wr8   popleft)r   rJ   rE   r-   rF   rr   r.   r.   r/   _pipeline_communicate   s<    
rN   Nonec                 C  s$   |   }|sq | jr | | q d S N)notifiesZnotify_handler)r   nr.   r.   r/   rH     s
    rH   zPQGen[list[pq.PGnotify]]c                 c  s2   t V  |   g }|  }|r.|| qq.q|S rP   )r#   r;   rQ   r>   )r   nsrR   r.   r.   r/   rQ   $  s    rQ   zPQGen[memoryview | PGresult]c                 c  s   |  d\}}|dkrq0tV }|rq&q|   q |dkr<|S t| E d H }t|dkr`td|d }|jtkrtj	|| j
d|S )Nr   r   z)you cannot mix COPY with other operationsr+   )Zget_copy_datar#   r;   r5   rC   r   ZProgrammingErrorr   
COMMAND_OKerror_from_result	_encoding)r   nbytesdatar-   rE   resultr.   r.   r/   	copy_from3  s     


r[   Tr   bool)r   bufferr8   r   c                 c  sH   |  |dkrtV }|rq qq |rDtV }|r"q0q"|  }|dkr"qDq"d S )Nr   )Zput_copy_datar$   r8   )r   r]   r8   r-   r<   r.   r.   r/   copy_toP  s    r^   zbytes | NonezPQGen[PGresult])r   errorr   c                 c  sn   |  |dkrtV }|rq qq tV }|rq,q|  }|dkrq@qt| E d H \}|jtkrjtj|| jd|S )Nr   rT   )	Zput_copy_endr$   r8   r5   r   rU   r   rV   rW   )r   r_   r-   r<   rZ   r.   r.   r/   copy_endl  s    
r`   )T)L__doc__
__future__r   loggingtimer    r   r   r   abcr   r   r	   r
   Zpq.abcr   r   r   Zwaitingr   r   _compatr   Z_cmoduler   Z
_encodingsr   Z
ConnStatusOKr   ZPollingStatusr&   ZREADINGr!   ZWRITINGr"   ZFAILEDr'   Z
ExecStatusrU   r@   r?   rA   rB   Rr#   Wr$   ZRWr9   r:   rK   ZREADY_RW	getLogger__name__loggerr0   r3   r7   r4   r5   r=   rN   rH   rQ   r[   r^   r`   connectcancelexecutesendZ
fetch_manyfetchZpipeline_communicater.   r.   r.   r/   <module>   sp   
+ 6
