o
    6	fs                  	   @   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mZmZ ddl	m
Z
 ddlmZmZmZmZmZmZmZmZ ddlmZmZmZmZmZm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% ddl&m'Z' ddl(m)Z) ddl*m+Z+ ddl,m-Z-m.Z.m/Z/ erddl0m1Z1m2Z2 ddl3m4Z4 ddl5m6Z6 ddl7m8Z8 ej9j:Z;ej9j<Z=ej>j:Z:ej>j<Z<ej?j@Z@ej?jAZAejBjCZCdZDdeD ZEdZFG dd dee  ZGG dd deGd ZHG dd deZIG dd  d eIZJG d!d" d"eJZKG d#d$ d$eIZLG d%d& d&eGd' ZMG d(d) d)eZNG d*d+ d+eNZOG d,d- d-eOZPG d.d/ d/eZQG d0d1 d1eQZRG d2d3 d3eQZS	dYd4ee d5e"d6eeT d7eTfd8d9ZU	dYd4ee d5e"d6eeT d7eTfd:d;ZVd<ed5e"d7eed=f fd>d?ZWd<ed5e"d7eed=f fd@dAZXeYdBjZZ[eYdCjZZ\eYdBj]Z^eYdCj]Z_dDZ`dEZadFZbecdGZddHdIdJdKdLdMdNdOZeeefdPeef dQeefeff d7effdRdSZgecdTZhdUdV eei D ZjejfdPeef dQeefeff d7effdWdXZke)re)jlZle)jmZme)jnZne)joZodS eUZleVZmeWZneXZodS )Zz
psycopg copy support
    N)ABCabstractmethod)TracebackType)AnyAsyncIteratorDictGenericIteratorListMatchIO)OptionalSequenceTupleTypeUnionTYPE_CHECKING   )pq)adapt)errors)BufferConnectionTypePQGenTransformer)create_taskSelf)connection_summary)_psycopg)pgconn_encoding)	copy_fromcopy_tocopy_end)
BaseCursorCursor)AsyncCursor)
Connection)AsyncConnectioni      i   c                   @   s   e Zd ZU dZded< dddddee fd	d
ZdefddZ	dddZ
deeeef  ddfddZdee fddZdeeeedf   fddZdee ded fddZdS )BaseCopya  
    Base implementation for the copy user interface.

    Two subclasses expose real methods with the sync/async differences.

    The difference between the text and binary format is managed by two
    different `Formatter` subclasses.

    Writing (the I/O part) is implemented in the subclasses by a `Writer` or
    `AsyncWriter` instance. Normally writing implies sending copy data to a
    database, but a different writer might be chosen, e.g. to stream data into
    a file for later use.
    	Formatter	formatterNbinarycursorzBaseCursor[ConnectionType, Any]r-   c                C   s   || _ |j| _| jj| _|j}|r.|j| _| jtkr-| jtkr-t	
dt| jj dnt| _|d u r<t|o:|j}t|dd pFt|}|rOt|| _n
t|t| jd| _d| _d S )NzAthe cursor should have performed a COPY operation; its status is z instead_tx)encodingF)r.   
connectionpgconn_pgconnpgresultstatus
_directionCOPY_INCOPY_OUTeProgrammingErrorr   
ExecStatusnameboolbinary_tuplesgetattrr   r   BinaryFormatterr+   TextFormatterr   	_finished)selfr.   r-   resulttx rF   E/home/ertert/spirit/venv/lib/python3.10/site-packages/psycopg/copy.py__init__P   s*   

zBaseCopy.__init__returnc                 C   s>   | j j d| j j }t| j}d| d| dt| ddS )N.< z at 0xx>)	__class__
__module____qualname__r   r3   id)rC   clsinforF   rF   rG   __repr__p   s   
zBaseCopy.__repr__c                 C   s   | j rtdd S )Nz!copy blocks can be used only once)rB   	TypeErrorrC   rF   rF   rG   _enteru   s   zBaseCopy._entertypesc                    sV   | j jj  fdd|D }| jtkr| jj|| jj dS | jj	|| jj dS )a  
        Set the types expected in a COPY operation.

        The types must be specified as a sequence of oid or PostgreSQL type
        names (e.g. ``int4``, ``timestamptz[]``).

        This operation overcomes the lack of metadata returned by PostgreSQL
        when a COPY operation begins:

        - On :sql:`COPY TO`, `!set_types()` allows to specify what types the
          operation returns. If `!set_types()` is not used, the data will be
          returned as unparsed strings or bytes instead of Python objects.

        - On :sql:`COPY FROM`, `!set_types()` allows to choose what type the
          database expects. This is especially useful in binary copy, because
          PostgreSQL will apply no cast rule.

        c                    s$   g | ]}t |tr|n |qS rF   )
isinstanceintget_oid).0tregistryrF   rG   
<listcomp>      $ z&BaseCopy.set_types.<locals>.<listcomp>N)
r.   adaptersrY   r6   r7   r+   transformerset_dumper_typesformatset_loader_types)rC   rY   oidsrF   r_   rG   	set_typesy   s
   

zBaseCopy.set_typesc                 c   sV    | j rtdS t| jE d H }t|tr|S d| _ |j}|d ur#|nd| j_tdS )N    T)rB   
memoryviewr    r3   rZ   command_tuplesr.   	_rowcount)rC   resnrowsrF   rF   rG   	_read_gen   s   
zBaseCopy._read_gen.c                 c   sH    |   E d H }|sd S | j|}|d u r"|   E d H  d| _d S |S NT)rq   r+   	parse_rowrB   )rC   datarowrF   rF   rG   _read_row_gen   s   zBaseCopy._read_row_genexcc                 c   sf    |sd S | j jtkrd S | j  z|  E d H r%	 |  E d H sW d S W d S  tjy2   Y d S w N)r3   transaction_statusACTIVEr1   cancelrq   r9   QueryCanceledrC   rw   rF   rF   rG   _end_copy_out_gen   s   
zBaseCopy._end_copy_out_genrI   N)__name__rP   rQ   __doc____annotations__r   r=   rH   strrU   rX   r   r   r[   ri   r   r   rq   r   r   rv   BaseExceptionr~   rF   rF   rF   rG   r)   ?   s   
 
 
r)   c                         e Zd ZU dZdZded< dddddd	ee ded f fd
dZdefddZ	dee
e  dee dee ddfddZdee fddZdefddZdeeedf  fddZdeeedf  fddZdeeef ddfddZd ee ddfd!d"Zd#ee ddfd$d%Z  ZS )&Copya]  Manage a :sql:`COPY` operation.

    :param cursor: the cursor where the operation is performed.
    :param binary: if `!True`, write binary format.
    :param writer: the object to write to destination. If not specified, write
        to the `!cursor` connection.

    Choosing `!binary` is not necessary if the cursor has executed a
    :sql:`COPY` operation, because the operation result describes the format
    too. The parameter is useful when a `!Copy` object is created manually and
    no operation is performed on the cursor, such as when using ``writer=``\
    `~psycopg.copy.FileWriter`.

    psycopgWriterwriterNr-   r   r.   Cursor[Any]r-   c                   .   t  j||d |st|}|| _|j| _d S Nr,   )superrH   LibpqWriterr   write_writerC   r.   r-   r   rO   rF   rG   rH      s
   zCopy.__init__rI   c                 C   s   |    | S rx   rX   rW   rF   rF   rG   	__enter__   s   zCopy.__enter__exc_typeexc_valexc_tbc                 C   s   |  | d S rx   finishrC   r   r   r   rF   rF   rG   __exit__   s   zCopy.__exit__c                 c   s    	 |   }|s
dS |V  q)z5Implement block-by-block iteration on :sql:`COPY TO`.TNreadrC   rt   rF   rF   rG   __iter__   s   zCopy.__iter__c                 C      | j |  S )z
        Read an unparsed row after a :sql:`COPY TO` operation.

        Return an empty string when the data is finished.
        r1   waitrq   rW   rF   rF   rG   r     s   z	Copy.read.c                 c   s     	 |   }|du rdS |V  q)z
        Iterate on the result of a :sql:`COPY TO` operation record by record.

        Note that the records returned will be tuples of unparsed strings or
        bytes, unless data types are specified using `set_types()`.
        TNread_rowrC   recordrF   rF   rG   rows  s   z	Copy.rowsc                 C   r   )a  
        Read a parsed row of data from a table after a :sql:`COPY TO` operation.

        Return `!None` when the data is finished.

        Note that the records returned will be tuples of unparsed strings or
        bytes, unless data types are specified using `set_types()`.
        r1   r   rv   rW   rF   rF   rG   r     s   	zCopy.read_rowbufferc                 C   "   | j |}|r| | dS dS )z
        Write a block of data to a table after a :sql:`COPY FROM` operation.

        If the :sql:`COPY` is in binary format `!buffer` must be `!bytes`. In
        text mode it can be either `!bytes` or `!str`.
        Nr+   r   r   rC   r   rt   rF   rF   rG   r   $  s   z
Copy.writeru   c                 C   r   )z=Write a record to a table after a :sql:`COPY FROM` operation.Nr+   	write_rowr   rC   ru   rt   rF   rF   rG   r   /  s   zCopy.write_rowrw   c                 C   sN   | j tkr| j }|r| | | j| d| _dS | j	| 
| dS )a  Terminate the copy operation and free the resources allocated.

        You shouldn't need to call this function yourself: it is usually called
        by exit. It is available if, despite what is documented, you end up
        using the `Copy` object outside a block.
        TNr6   r7   r+   endr   r   r   rB   r1   r   r~   rC   rw   rt   rF   rF   rG   r   5  s   



zCopy.finish)r   rP   rQ   r   r   r   r=   rH   r   r   r   r   r   r   r	   r   r   r   r   r   r   r   r   r   r   r   r   r   __classcell__rF   rF   r   rG   r      s<   
 


r   zConnection[Any]c                   @   >   e Zd ZdZededdfddZd
dee ddfdd	Z	dS )r   z/
    A class to write copy data somewhere.
    rt   rI   Nc                 C      dS )z1
        Write some data to destination.
        NrF   r   rF   rF   rG   r   K  s   zWriter.writerw   c                 C   r   )z
        Called when write operations are finished.

        If operations finished with an error, it will be passed to ``exc``.
        NrF   r}   rF   rF   rG   r   R  s   zWriter.finishrx   
r   rP   rQ   r   r   r   r   r   r   r   rF   rF   rF   rG   r   F  s
    r   c                   @   D   e Zd ZdZdddZdeddfd	d
Zddee ddfddZ	dS )r   z?
    A `Writer` to write copy data to a Postgres database.
    r.   r   c                 C      || _ |j| _| jj| _d S rx   r.   r1   r2   r3   rC   r.   rF   rF   rG   rH   `     zLibpqWriter.__init__rt   rI   Nc              	   C   s^   t |tkr| jt| j| d S tdt |tD ]}| jt| j|||t   qd S Nr   lenMAX_BUFFER_SIZEr1   r   r!   r3   rangerC   rt   irF   rF   rG   r   e  s   zLibpqWriter.writerw   c                 C   sv   |rdt |j d| }|t| jd}nd }z| jt| j|}W n tj	y3   |s0 Y d S w |g| j
_d S Nzerror from Python: z - replacetyperQ   encoder   r3   r1   r   r"   r9   r|   r.   _resultsrC   rw   msgbmsgro   rF   rF   rG   r   r  s   zLibpqWriter.finishr.   r   rx   
r   rP   rQ   r   rH   r   r   r   r   r   rF   rF   rF   rG   r   [  
    
r   c                       Z   e Zd ZdZd fddZddd	Zd
eddfddZddee	 ddf fddZ
  ZS )QueuedLibpqWritera  
    A writer using a buffer to queue data to write to a Postgres database.

    `write()` returns immediately, so that the main thread can be CPU-bound
    formatting messages, while a worker thread can be IO-bound waiting to write
    on the connection.
    r.   r   c                    s*   t  | tjtd| _d | _d | _d S N)maxsize)r   rH   queueQueue
QUEUE_SIZE_queue_worker_worker_errorr   r   rF   rG   rH     s   
zQueuedLibpqWriter.__init__rI   Nc              
   C   s`   z	 | j jddd}|sW dS | jt| j| q ty/ } z
|| _W Y d}~dS d}~ww )zPush data to the server when available from the copy queue.

        Terminate reading when the queue receives a false-y value, or in case
        of error.

        The function is designed to be run in a separate thread.
        TiQ )blocktimeoutN)r   getr1   r   r!   r3   r   r   )rC   rt   exrF   rF   rG   worker  s   zQueuedLibpqWriter.workerrt   c                 C   s   | j stj| jd| _ d| j _| j   | jr| jt|tkr(| j	
| d S tdt|tD ]}| j	
|||t   q0d S )N)targetTr   )r   	threadingThreadr   daemonstartr   r   r   r   putr   r   rF   rF   rG   r     s   
zQueuedLibpqWriter.writerw   c                    s>   | j d | jr| j  d | _| jr| jt | d S Nrj   )r   r   r   joinr   r   r   r}   r   rF   rG   r     s   
zQueuedLibpqWriter.finishr   r   rx   r   rP   rQ   r   rH   r   r   r   r   r   r   r   rF   rF   r   rG   r     s    
$r   c                   @   s4   e Zd ZdZdee fddZdeddfdd	ZdS )

FileWriterz
    A `Writer` to write copy data to a file-like object.

    :param file: the file where to write copy data. It must be open for writing
        in binary mode.
    filec                 C   s
   || _ d S rx   )r   )rC   r   rF   rF   rG   rH     s   
zFileWriter.__init__rt   rI   Nc                 C   s   | j | d S rx   )r   r   r   rF   rF   rG   r     s   zFileWriter.write)	r   rP   rQ   r   r   bytesrH   r   r   rF   rF   rF   rG   r     s    r   c                       r   )&	AsyncCopyz-Manage an asynchronous :sql:`COPY` operation.r   AsyncWriterr   Nr   r.   AsyncCursor[Any]r-   c                   r   r   )r   rH   AsyncLibpqWriterr   r   r   r   r   rF   rG   rH     s
   zAsyncCopy.__init__rI   c                    s   |    | S rx   r   rW   rF   rF   rG   
__aenter__  s   zAsyncCopy.__aenter__r   r   r   c                    s   |  |I d H  d S rx   r   r   rF   rF   rG   	__aexit__  s   zAsyncCopy.__aexit__c                 C  s"   	 |   I d H }|sd S |V  qrx   r   r   rF   rF   rG   	__aiter__  s   zAsyncCopy.__aiter__c                       | j |  I d H S rx   r   rW   rF   rF   rG   r        zAsyncCopy.read.c                 C  s&   	 |   I d H }|d u rd S |V  qrx   r   r   rF   rF   rG   r     s   zAsyncCopy.rowsc                    r   rx   r   rW   rF   rF   rG   r     r   zAsyncCopy.read_rowr   c                    *   | j |}|r| |I d H  d S d S rx   r   r   rF   rF   rG   r     
   zAsyncCopy.writeru   c                    r   rx   r   r   rF   rF   rG   r     r   zAsyncCopy.write_rowrw   c                    sb   | j tkr#| j }|r| |I d H  | j|I d H  d| _d S | j	| 
|I d H  d S rr   r   r   rF   rF   rG   r     s   


zAsyncCopy.finish)r   rP   rQ   r   r   r   r=   rH   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   rF   rF   r   rG   r     s<   
 

r   zAsyncConnection[Any]c                   @   r   )r   zG
    A class to write copy data somewhere (for async connections).
    rt   rI   Nc                       d S rx   rF   r   rF   rF   rG   r   *     zAsyncWriter.writerw   c                    r   rx   rF   r}   rF   rF   rG   r   -  r   zAsyncWriter.finishrx   r   rF   rF   rF   rG   r   %  s
    r   c                   @   r   )r   zE
    An `AsyncWriter` to write copy data to a Postgres database.
    r.   r   c                 C   r   rx   r   r   rF   rF   rG   rH   6  r   zAsyncLibpqWriter.__init__rt   rI   Nc              	      sl   t |tkr| jt| j|I d H  d S tdt |tD ]}| jt| j|||t  I d H  qd S r   r   r   rF   rF   rG   r   ;  s   zAsyncLibpqWriter.writerw   c                    s~   |rdt |j d| }|t| jd}nd }z| jt| j|I d H }W n tj	y7   |s4 Y d S w |g| j
_d S r   r   r   rF   rF   rG   r   H  s   zAsyncLibpqWriter.finishr.   r   rx   r   rF   rF   rF   rG   r   1  r   r   c                       r   )AsyncQueuedLibpqWriterz
    An `AsyncWriter` using a buffer to queue data to write.

    `write()` returns immediately, so that the main thread can be CPU-bound
    formatting messages, while a worker thread can be IO-bound waiting to write
    on the connection.
    r.   r   c                    s$   t  | tjtd| _d | _d S r   )r   rH   asyncior   r   r   r   r   r   rF   rG   rH   e  s   
zAsyncQueuedLibpqWriter.__init__rI   Nc                    s8   	 | j  I dH }|sdS | jt| j|I dH  q)zPush data to the server when available from the copy queue.

        Terminate reading when the queue receives a false-y value.

        The function is designed to be run in a separate task.
        TN)r   r   r1   r   r!   r3   r   rF   rF   rG   r   k  s   zAsyncQueuedLibpqWriter.workerrt   c                    sp   | j st|  | _ t|tkr| j|I d H  d S tdt|tD ]}| j|||t  I d H  q$d S r   )r   r   r   r   r   r   r   r   r   rF   rF   rG   r   x  s    zAsyncQueuedLibpqWriter.writerw   c                    sH   | j dI d H  | jrt| jI d H  d | _t |I d H  d S r   )r   r   r   r   gatherr   r   r}   r   rF   rG   r     s   zAsyncQueuedLibpqWriter.finishr   r   rx   r   rF   rF   r   rG   r   \  s    
$r   c                   @   s   e Zd ZU dZejed< defddZe	de
deeedf  fd	d
Ze	dee
ef de
fddZe	dee de
fddZe	de
fddZdS )r*   z@
    A class which understand a copy format (text, binary).
    rf   rd   c                 C   s   || _ t | _d| _d S NF)rd   	bytearray_write_buffer	_row_moderC   rd   rF   rF   rG   rH     s   
zFormatter.__init__rt   rI   .c                 C      d S rx   rF   r   rF   rF   rG   rs        zFormatter.parse_rowr   c                 C   r  rx   rF   rC   r   rF   rF   rG   r     r  zFormatter.writeru   c                 C   r  rx   rF   )rC   ru   rF   rF   rG   r     r  zFormatter.write_rowc                 C   r  rx   rF   rW   rF   rF   rG   r     r  zFormatter.endN)r   rP   rQ   r   r   Formatr   r   rH   r   r   r   r   r   rs   r   r   r   r   r   r   rF   rF   rF   rG   r*     s   
 
 r*   c                       s   e Zd ZeZddedef fddZdede	e
edf  fd	d
Zdeeef defddZdee defddZdefddZdeeef defddZ  ZS )rA   utf-8rd   r0   c                    s   t  | || _d S rx   )r   rH   	_encoding)rC   rd   r0   r   rF   rG   rH        
zTextFormatter.__init__rt   rI   .c                 C   s   |rt || jS d S rx   )parse_row_textrd   r   rF   rF   rG   rs     s   zTextFormatter.parse_rowr   c                 C      |  |}d| _|S rr   _ensure_bytes_signature_sentr   rF   rF   rG   r        
zTextFormatter.writeru   c                 C   s<   d| _ t|| j| j t| jtkr| jt }| _|S dS NTrj   )r   format_row_textrd   r   r   BUFFER_SIZEr   rC   ru   r   rF   rF   rG   r     s   zTextFormatter.write_rowc                 C   s   | j t }| _ |S rx   )r   r   r  rF   rF   rG   r     s   zTextFormatter.endc                 C   s   t |tr|| jS |S rx   )rZ   r   r   r  r   rF   rF   rG   r    s   
zTextFormatter._ensure_bytes)r  )r   rP   rQ   TEXTrf   r   r   rH   r   r   r   r   rs   r   r   r   r   r   r  r   rF   rF   r   rG   rA     s    "rA   c                       s   e Zd ZeZdef fddZdedee	e
df  fddZd	eeef defd
dZdee
 defddZdefddZdeeef defddZ  ZS )r@   rd   c                    s   t  | d| _d S r   )r   rH   r  r   r   rF   rG   rH     r  zBinaryFormatter.__init__rt   rI   .c                 C   sT   | j s|d tt tkrtdd| _ |ttd  }n|tkr$d S t|| jS )Nz5binary copy doesn't start with the expected signatureT)r  r   _binary_signaturer9   	DataError_binary_trailerparse_row_binaryrd   r   rF   rF   rG   rs     s   zBinaryFormatter.parse_rowr   c                 C   r	  rr   r
  r   rF   rF   rG   r     r  zBinaryFormatter.writeru   c                 C   sV   d| _ | js|  jt7  _d| _t|| j| j t| jtkr)| jt }| _|S dS r  )	r   r  r   r  format_row_binaryrd   r   r  r   r  rF   rF   rG   r     s   zBinaryFormatter.write_rowc                 C   sL   | j s|  jt7  _|  jt7  _n
| jr|  jt7  _| jt }| _|S rx   )r  r   r  r  r   r   r  rF   rF   rG   r     s   zBinaryFormatter.endc                 C   s   t |tr	td|S )Nz6cannot copy str data in binary mode: use bytes instead)rZ   r   rV   r   rF   rF   rG   r    s   
zBinaryFormatter._ensure_bytes)r   rP   rQ   BINARYrf   r   rH   r   r   r   r   rs   r   r   r   r   r   r   r  r   rF   rF   r   rG   r@     s    "r@   ru   rE   outrI   c                 C   sx   |du rt  }| s|d7 }|S | D ]"}|dur+||t}||}|tt|7 }n|d7 }|d7 }qd|dd< |S )z6Convert a row of objects to the data to send for copy.N   
   \N   	rk   )r   
get_dumperPY_TEXTdump_dump_resub	_dump_sub)ru   rE   r  itemdumperbrF   rF   rG   _format_row_text  s   

r&  c                 C   sl   |du rt  }|tt| 7 }|| tgt|  }|D ]}|dur/|tt|7 }||7 }q|t7 }q|S )z=Convert a row of objects to the data to send for binary copy.N)r   
_pack_int2r   dump_sequence	PY_BINARY
_pack_int4_binary_null)ru   rE   r  adaptedr%  rF   rF   rG   _format_row_binary4  s   

r-  rt   .c                 C   sH   t | ts	t| } | d}|d d d |d< dd |D }||S )Nr  rk   c                 S   s$   g | ]}|d kr
dnt t|qS )r  N)_load_rer!  	_load_sub)r]   frF   rF   rG   ra   L  rb   z#_parse_row_text.<locals>.<listcomp>)rZ   r   splitload_sequence)rt   rE   fieldsru   rF   rF   rG   _parse_row_textG  s   


r4  c                 C   sv   g }t | dd }d}t|D ]&}t| |d }|d7 }|dkr0|| |||   ||7 }q|d  q||S )Nr      r(   )_unpack_int2r   _unpack_int4appendr2  )rt   rE   ru   nfieldsposr   lengthrF   rF   rG   _parse_row_binaryP  s   

r<  z!hz!is   PGCOPY

         s   s   s
   [	
\\]s   \bs   \ts   \ns   \vs   \fs   \rs   \\)   r  r              \m__mapc                 C      ||  d S r   grouprB  rC  rF   rF   rG   r"  y     r"  s   \\[btnvfr\\]c                 C   s   i | ]\}}||qS rF   rF   )r]   kvrF   rF   rG   
<dictcomp>~  s    rK  c                 C   rD  r   rE  rG  rF   rF   rG   r/    rH  r/  rx   )pr   rer   structr   r   abcr   r   rY   r   typingr   r   r   r   r	   r
   r   r   r   r   r   r   r   r    r   r   r   r9   r   r   r   r   _compatr   r   pq.miscr   _cmoduler   
_encodingsr   
generatorsr    r!   r"   r.   r#   r$   cursor_asyncr%   r1   r&   connection_asyncr'   PyFormatr  r  r  r)  r  r;   r7   r8   TransactionStatusrz   r  r   r   r)   r   r   r   r   r   r   r   r   r   r*   rA   r@   r   r&  r-  r4  r<  Structpackr'  r*  unpack_fromr6  r7  r  r  r+  compiler   
_dump_replr   r"  r.  items
_load_replr/  r  r  r  r  rF   rF   rF   rG   <module>   s    (  z+EK+4,H

	
&
&
