
    RhR-                     d    d Z ddlmZ ddlmZ  G d dej
                        Z G d d      Zd Zy	)
a  A class supporting chat-style (command/response) protocols.

This class adds support for 'chat' style protocols - where one side
sends a 'command', and the other sends a response (examples would be
the common internet protocols - smtp, nntp, ftp, etc..).

The handle_read() method looks at the input stream for the current
'terminator' (usually '\r\n' for single-line responses, '\r\n.\r\n'
for multi-line output), calling self.found_terminator() on its
receipt.

for example:
Say you build an async nntp client using this class.  At the start
of the connection, you'll have self.terminator set to '\r\n', in
order to process the single-line greeting.  Just before issuing a
'LIST' command you'll set it to '\r\n.\r\n'.  The output of the LIST
command will be accumulated (using your own 'collect_incoming_data'
method) up to the terminator, and then control will be returned to
you - by calling your self.found_terminator() method.
    )deque)asyncorec                       e Zd ZdZdZdZdZdZddZd Z	d Z
d	 Zd
 Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zy)
async_chatzThis is an abstract class.  You must derive from this class, and add
    the two methods collect_incoming_data() and found_terminator()i   r   zlatin-1Nc                     d| _         g | _        t               | _        t        j
                  j                  | ||       y N    )ac_in_bufferincomingr   producer_fifor   
dispatcher__init__)selfsockmaps      ,/usr/lib/python3.12/test/support/asynchat.pyr   zasync_chat.__init__J   s7    
  #W$$T45r	   c                     t        d      Nzmust be implemented in subclassNotImplementedErrorr   datas     r   collect_incoming_dataz async_chat.collect_incoming_dataX       !"CDDr	   c                 :    | j                   j                  |       y N)r   appendr   s     r   _collect_incoming_dataz!async_chat._collect_incoming_data[   s    T"r	   c                 Z    dj                  | j                        }| j                  d d = |S r   )joinr   )r   ds     r   	_get_datazasync_chat._get_data^   s%    HHT]]#MM!r	   c                     t        d      r   r   r   s    r   found_terminatorzasync_chat.found_terminatorc   r   r	   c                     t        |t              r*| j                  rt        || j                        }|| _        yt        |t
              r|dk  rt        d      || _        y)zdSet the input delimiter.

        Can be a fixed string of any length, an integer, or None.
        r   z-the number of received bytes must be positiveN)
isinstancestruse_encodingbytesencodingint
ValueError
terminator)r   terms     r   set_terminatorzasync_chat.set_terminatorf   sT    
 dC T%6%6t}}-D  c"taxLMMr	   c                     | j                   S r   )r.   r$   s    r   get_terminatorzasync_chat.get_terminatorq   s    r	   c                    	 | j                  | j                        }t        |t              r&| j                  rt        t        | j                        }| j                  |z   | _
        | j                  rt        | j                        }| j                         }|s$| j                  | j                         d| _
        nt        |t              r|}||k  r8| j                  | j                         d| _
        | j                  |z
  | _        n4| j                  | j                  d |        | j                  |d  | _
        d| _        | j!                          nt        |      }| j                  j#                  |      }|dk7  rK|dkD  r| j                  | j                  d |        | j                  ||z   d  | _
        | j!                          ntt%        | j                  |      }|r:||k7  r4| j                  | j                  d |         | j                  | d  | _
        y | j                  | j                         d| _
        | j                  ry y # t        $ r Y y t        $ r | j	                          Y y w xY w)Nr	   r   )recvac_in_buffer_sizeBlockingIOErrorOSErrorhandle_errorr'   r(   r)   r*   r+   r
   lenr2   r   r,   r.   r%   findfind_prefix_at_end)r   r   lbr.   nterminator_lenindexs          r   handle_readzasync_chat.handle_ready   s>   	99T334D dC T%6%6dmm,D --4 T&&'B,,.J**4+<+<=$'!J,6..t/@/@A(+D%&*oo&:DO..t/@/@!/DE(,(9(9!"(=D%&'DO))+ "%Z))..z:B;qy 2243D3DVe3LM(,(9(9%:N:O(PD% ))+ /t/@/@*ME B; 66t7H7H5&7QR040A0A5&'0JD- 2243D3DE,/)g   	 		s   I 	I8I87I8c                 $    | j                          y r   )initiate_sendr$   s    r   handle_writezasync_chat.handle_write   s    r	   c                 $    | j                          y r   )closer$   s    r   handle_closezasync_chat.handle_close   s    

r	   c                 h   t        |t        t        t        f      st	        dt        |            | j                  }t        |      |kD  r=t        dt        |      |      D ]#  }| j                  j                  ||||z           % n| j                  j                  |       | j                          y )Nz#data argument must be byte-ish (%r)r   )r'   r*   	bytearray
memoryview	TypeErrortypeac_out_buffer_sizer:   ranger   r   rC   )r   r   sabsis       r   pushzasync_chat.push   s    $	: >?A J( (&&t9t1c$i. :""))$q4.9: %%d+r	   c                 Z    | j                   j                  |       | j                          y r   )r   r   rC   )r   producers     r   push_with_producerzasync_chat.push_with_producer   s"    !!(+r	   c                      y)z4predicate for inclusion in the readable for select()    r$   s    r   readablezasync_chat.readable   s     r	   c                 8    | j                   xs | j                   S )z4predicate for inclusion in the writable for select())r   	connectedr$   s    r   writablezasync_chat.writable   s    !!9$..&89r	   c                 :    | j                   j                  d       y)zAautomatically close this channel once the outgoing queue is emptyN)r   r   r$   s    r   close_when_donezasync_chat.close_when_done   s    !!$'r	   c                    | j                   r| j                  r| j                   d   }|s | j                   d= || j                          y | j                  }	 |d | }t        |t              r"| j                  rt        || j                        }	 | j                  |      }|r<|t        |      k  s|t        |      k  r||d  | j                   d<   y | j                   d= y y y # t        $ r? |j                         }|r| j                   j                  |       n| j                   d= Y 'w xY w# t        $ r | j                          Y y w xY w)Nr   )r   rZ   rG   rM   rK   more
appendleftr'   r(   r)   r*   r+   sendr8   r9   r:   )r   firstobsr   num_sents        r   rC   zasync_chat.initiate_send   sP     T^^&&q)E&&q)=%%' ))CTc{ $$):):T4==199T?
 c$i'3U+;,1(),<D&&q)  **1-K &4   zz|&&11$7**1-  !!#s%   C! D, !AD)(D),EEc                 d    d| _         | j                  d d = | j                  j                          y r   )r
   r   r   clearr$   s    r   discard_bufferszasync_chat.discard_buffers  s(    MM!  "r	   )NN)__name__
__module____qualname____doc__r6   rM   r)   r+   r   r   r   r"   r%   r0   r2   rA   rD   rG   rQ   rT   rX   r[   r]   rC   rg   rW   r	   r   r   r   ;   s|    F
 
 LH6E#
E	F0P
:(&P#r	   r   c                       e Zd ZddZd Zy)simple_producerc                      || _         || _        y r   )r   buffer_size)r   r   ro   s      r   r   zsimple_producer.__init__  s    	&r	   c                     t        | j                        | j                  kD  r9| j                  d | j                   }| j                  | j                  d  | _        |S | j                  }d| _        |S r   )r:   r   ro   )r   results     r   r_   zsimple_producer.more  sb    tyy>D,,,YY0 0 01F		$"2"2"34DIMYYFDIMr	   N)i   )rh   ri   rj   r   r_   rW   r	   r   rm   rm     s    'r	   rm   c                     t        |      dz
  }|r0| j                  |d |       s|dz  }|r| j                  |d |       s|S )NrV   )r:   endswith)haystackneedlels      r   r<   r<   6  sK    FaA
H%%fRaj1	Q H%%fRaj1Hr	   N)	rk   collectionsr   test.supportr   r   r   rm   r<   rW   r	   r   <module>ry      s8   B*  !X#$$ X#v @r	   