
    F\hR-                     d    S r SSKJr  SSKJr   " S S\R
                  5      r " S S5      rS rg	)
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                       \ rS rSrSrSrSrSrSrSS jr	S r
S	 rS
 rS rS rS rS rS rS rS rS rS rS rS rS rS rSrg)
async_chat;   zThis 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                 ~    SU l         / U l        [        5       U l        [        R
                  R                  XU5        g N    )ac_in_bufferincomingr   producer_fifor   
dispatcher__init__)selfsockmaps      ,/usr/lib/python3.13/test/support/asynchat.pyr   async_chat.__init__J   s5    
  #W$$T5r
   c                     [        S5      eNzmust be implemented in subclassNotImplementedErrorr   datas     r   collect_incoming_data async_chat.collect_incoming_dataX       !"CDDr
   c                 :    U R                   R                  U5        g N)r   appendr   s     r   _collect_incoming_data!async_chat._collect_incoming_data[   s    T"r
   c                 Z    SR                  U R                  5      nU R                  S S 2	 U$ r	   )joinr   )r   ds     r   	_get_dataasync_chat._get_data^   s%    HHT]]#MM!r
   c                     [        S5      er   r   r   s    r   found_terminatorasync_chat.found_terminatorc   r   r
   c                     [        U[        5      (       a'  U R                  (       a  [        XR                  5      nO&[        U[
        5      (       a  US:  a  [        S5      eXl        g)zTSet 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_terminatorasync_chat.set_terminatorf   sK    
 dC  T%6%6}}-Dc""taxLMMr
   c                     U R                   $ r   )r4   r)   s    r   get_terminatorasync_chat.get_terminatorq   s    r
   c                 D    U R                  U R                  5      n[        U[        5      (       a+  U R                  (       a  [        [        U R                  5      nU R                  U-   U l
        U R                  (       Ga  [        U R                  5      nU R                  5       nU(       d$  U R                  U R                  5        SU l
        GO[        U[        5      (       a  UnX$:  a8  U R                  U R                  5        SU l
        U R                  U-
  U l        GO:U R                  U R                  S U 5        U R                  US  U l
        SU l        U R!                  5         O[        U5      nU R                  R#                  U5      nUS:w  aK  US:  a  U R                  U R                  S U 5        U R                  Xe-   S  U l
        U R!                  5         Oy[%        U R                  U5      nU(       a:  Xb:w  a4  U R                  U R                  S U*  5        U R                  U* S  U l
        g U R                  U R                  5        SU l
        U R                  (       a  GM  g g ! [         a     g [         a    U R	                  5          g f = f)Nr
   r   )recvac_in_buffer_sizeBlockingIOErrorOSErrorhandle_errorr-   r.   r/   r0   r1   r   lenr9   r   r2   r4   r*   findfind_prefix_at_end)r   r   lbr4   nterminator_lenindexs          r   handle_readasync_chat.handle_ready   sD   	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 ; 66t7H7H5&7QR040A0A5&'0JD- 2243D3DE,/)g   	 		s   I7 7
JJJc                 $    U R                  5         g r   )initiate_sendr)   s    r   handle_writeasync_chat.handle_write   s    r
   c                 $    U R                  5         g r   )closer)   s    r   handle_closeasync_chat.handle_close   s    

r
   c                 t   [        U[        [        [        45      (       d  [	        S[        U5      5      eU R                  n[        U5      U:  a=  [        S[        U5      U5       H"  nU R                  R                  XX2-    5        M$     OU R                  R                  U5        U R                  5         g )Nz#data argument must be byte-ish (%r)r   )r-   r0   	bytearray
memoryview	TypeErrortypeac_out_buffer_sizerB   ranger   r    rL   )r   r   sabsis       r   pushasync_chat.push   s    $	: >??A J( (&&t9t1c$i.""))$.9 / %%d+r
   c                 Z    U R                   R                  U5        U R                  5         g r   )r   r    rL   )r   producers     r   push_with_producerasync_chat.push_with_producer   s"    !!(+r
   c                     g)z4predicate for inclusion in the readable for select()    r)   s    r   readableasync_chat.readable   s     r
   c                 J    U R                   =(       d    U R                  (       + $ )z4predicate for inclusion in the writable for select())r   	connectedr)   s    r   writableasync_chat.writable   s    !!9$..&89r
   c                 :    U R                   R                  S5        g)zAautomatically close this channel once the outgoing queue is emptyN)r   r    r)   s    r   close_when_doneasync_chat.close_when_done   s    !!$'r
   c                    U R                   (       a  U R                  (       a  U R                   S   nU(       d!  U R                   S	 Uc  U R                  5         g U R                  n US U n[        U[        5      (       a&  U R                  (       a  [        X0R                  5      n U R                  U5      nU(       a=  U[        U5      :  d  U[        U5      :  a  XS  U R                   S'   g U R                   S	 g g g ! [         aE    UR                  5       nU(       a  U R                   R                  U5        OU R                   S	  GMM  f = f! [         a    U R                  5          g f = f)Nr   )r   rh   rQ   rX   rV   more
appendleftr-   r.   r/   r0   r1   sendr@   rA   rB   )r   firstobsr   num_sents        r   rL   async_chat.initiate_send   sO     T^^&&q)E&&q)=%%' ))CTc{ $$$):):T==199T?
 c$i'3U+;,1),<D&&q)  **1-K &4   zz|&&11$7**1-  !!#s%   'D  (E  A
EEE/.E/c                 d    SU l         U R                  S S 2	 U R                  R                  5         g r	   )r   r   r   clearr)   s    r   discard_buffersasync_chat.discard_buffers  s(    MM!  "r
   )r   r   r   r4   )NN)__name__
__module____qualname____firstlineno____doc__r>   rX   r/   r1   r   r   r!   r&   r*   r6   r9   rI   rM   rQ   r\   r`   re   ri   rl   rL   rx   __static_attributes__rd   r
   r   r   r   ;   s|    F
 
 LH6E#
E	F0P
:(&P#r
   r   c                   $    \ rS rSrSS jrS rSrg)simple_produceri  c                     Xl         X l        g r   )r   buffer_size)r   r   r   s      r   r   simple_producer.__init__  s    	&r
   c                     [        U R                  5      U R                  :  a9  U R                  S U R                   nU R                  U R                  S  U l        U$ U R                  nSU l        U$ r	   )rB   r   r   )r   results     r   ro   simple_producer.more  sb    tyy>D,,,YY0 0 01F		$"2"2"34DIMYYFDIMr
   )r   r   N)i   )rz   r{   r|   r}   r   ro   r   rd   r
   r   r   r     s    'r
   r   c                     [        U5      S-
  nU(       a@  U R                  US U 5      (       d'  US-  nU(       a  U R                  US U 5      (       d  M'  U$ )Nrc   )rB   endswith)haystackneedlels      r   rD   rD   6  sQ    FaA
H%%fRaj11	Q H%%fRaj11Hr
   N)	r~   collectionsr   test.supportr   r   r   r   rD   rd   r
   r   <module>r      s8   B*  !X#$$ X#v @r
   