U
    ad@,                     @   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__)selfZsockmap r   /usr/lib/python3.8/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 nD tk
r&   Y d S  tk
rT } z|   W Y d S d }~X Y nX t|trr| jrrtt| j	}| j
| | _
| j
rt| j
}|  }|s| | j
 d| _
q~t|tr|}||k r| | j
 d| _
| j| | _n2| | j
d |  | j
|d  | _
d| _|   q~t|}| j
|}|dkrv|dkrX| | j
d |  | j
|| d  | _
|   q~t| j
|}|r||kr| | j
d |   | j
| d  | _
qq~| | j
 d| _
q~d S )Nr   r   )Z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whyZ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   r3   )r   r   Zsabsir   r   r   push   s    zasync_chat.pushc                 C   s   | j | |   d S r   )r   r   r3   )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 kr:|   d S | j}z|d | }W n: tk
r   | }|rz| j | n| j d= Y q Y nX t|tr| j	rt
|| j}z| |}W n tk
r   |   Y d S X |r|t|k s|t|k r
||d  | j d< n| j d= d S d S )Nr   )r   rB   r6   r;   r9   more
appendleftr   r   r    r!   r"   sendr+   r,   r-   )r   firstZobsr   Znum_sentr   r   r   r3      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'   r2   r4   r6   r>   r?   rA   rC   rD   r3   rJ   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   rQ   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   rQ   )r   resultr   r   r   rE     s    zsimple_producer.moreN)rP   )rK   rL   rM   r   rE   r   r   r   r   rO     s   
rO   c                 C   s0   t |d }|r,| |d | s,|d8 }q|S )Nr@   )r-   endswith)ZhaystackZneedlelr   r   r   r/   /  s    
r/   )rN   r	   collectionsr   r
   r   rO   r/   r   r   r   r   <module>   s    \ 