a
    ze9,                     @   sD   d Z ddlZddlmZ G dd dejZG dd dZdd	 ZdS )
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.
    N)dequec                   @   s   e Zd ZdZdZdZdZdZd(ddZdd	 Z	d
d Z
dd Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zd d! Zd"d# Zd$d% Zd&d' ZdS ))
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                 C   s(   d| _ g | _t | _tj| || d S N    )ac_in_bufferincomingr   producer_fifoasyncore
dispatcher__init__)selfsockmap r   /usr/lib/python3.9/asynchat.pyr   C   s    zasync_chat.__init__c                 C   s   t dd S Nzmust be implemented in subclassNotImplementedErrorr   datar   r   r   collect_incoming_dataQ   s    z async_chat.collect_incoming_datac                 C   s   | j | d S N)r   appendr   r   r   r   _collect_incoming_dataT   s    z!async_chat._collect_incoming_datac                 C   s   d | j}| jd d = |S r   )joinr   )r   dr   r   r   	_get_dataW   s    zasync_chat._get_datac                 C   s   t dd S r   r   r   r   r   r   found_terminator\   s    zasync_chat.found_terminatorc                 C   sB   t |tr| jrt|| j}nt |tr8|dk r8td|| _dS )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   Ztermr   r   r   set_terminator_   s
    zasync_chat.set_terminatorc                 C   s   | j S r   )r&   r   r   r   r   get_terminatorj   s    zasync_chat.get_terminatorc                 C   s  z|  | j}W n. ty$   Y d S  ty>   |   Y d S 0 t|tr\| jr\tt| j	}| j
| | _
| j
rt| j
}|  }|s| | j
 d| _
qht|tr|}||k r| | j
 d| _
| j| | _n2| | j
d |  | j
|d  | _
d| _|   qht|}| j
|}|dkr`|dkrB| | j
d |  | j
|| d  | _
|   qht| j
|}|r||kr| | j
d |   | j
| d  | _
qqh| | j
 d| _
qhd S )Nr   r   )recvac_in_buffer_sizeBlockingIOErrorOSErrorhandle_errorr   r    r!   r"   r#   r   lenr(   r   r$   r&   r   findfind_prefix_at_end)r   r   Zlbr&   nZterminator_lenindexr   r   r   handle_readr   sR    

	



zasync_chat.handle_readc                 C   s   |    d S r   )initiate_sendr   r   r   r   handle_write   s    zasync_chat.handle_writec                 C   s   |    d S r   )closer   r   r   r   handle_close   s    zasync_chat.handle_closec                 C   sx   t |tttfstdt|| j}t||kr`tdt||D ]}| j	
||||   q@n| j	
| |   d S )Nz#data argument must be byte-ish (%r)r   )r   r"   	bytearray
memoryview	TypeErrortypeac_out_buffer_sizer/   ranger   r   r5   )r   r   Zsabsir   r   r   push   s    zasync_chat.pushc                 C   s   | j | |   d S r   )r   r   r5   )r   Zproducerr   r   r   push_with_producer   s    zasync_chat.push_with_producerc                 C   s   dS )z4predicate for inclusion in the readable for select()   r   r   r   r   r   readable   s    zasync_chat.readablec                 C   s   | j p| j S )z4predicate for inclusion in the writable for select())r   	connectedr   r   r   r   writable   s    zasync_chat.writablec                 C   s   | j d dS )zAautomatically close this channel once the outgoing queue is emptyN)r   r   r   r   r   r   close_when_done   s    zasync_chat.close_when_donec                 C   s  | j r| jr| j d }|s:| j d= |d u r:|   d S | j}z|d | }W n8 ty   | }|rx| j | n| j d= Y q Y n0 t|tr| j	rt
|| j}z| |}W n ty   |   Y d S 0 |r|t|k s|t|k r||d  | j d< n| j d= d S d S )Nr   )r   rD   r8   r=   r;   more
appendleftr   r    r!   r"   r#   sendr-   r.   r/   )r   firstZobsr   Znum_sentr   r   r   r5      s8    

zasync_chat.initiate_sendc                 C   s    d| _ | jd d = | j  d S r   )r   r   r   clearr   r   r   r   discard_buffers  s    zasync_chat.discard_buffers)NN)__name__
__module____qualname____doc__r+   r=   r!   r#   r   r   r   r   r   r'   r(   r4   r6   r8   r@   rA   rC   rE   rF   r5   rL   r   r   r   r   r   4   s,   
H(r   c                   @   s   e Zd ZdddZdd ZdS )simple_producer   c                 C   s   || _ || _d S r   )r   buffer_size)r   r   rS   r   r   r   r     s    zsimple_producer.__init__c                 C   sJ   t | j| jkr6| jd | j }| j| jd  | _|S | j}d| _|S d S r   )r/   r   rS   )r   resultr   r   r   rG     s    zsimple_producer.moreN)rR   )rM   rN   rO   r   rG   r   r   r   r   rQ     s   
rQ   c                 C   s0   t |d }|r,| |d | s,|d8 }q|S )NrB   )r/   endswith)ZhaystackZneedlelr   r   r   r1   /  s    
r1   )rP   r	   collectionsr   r
   r   rQ   r1   r   r   r   r   <module>   s    \ 