U e5d@, � @ sD d Z ddlZddlmZ G dd� dej�ZG dd� d�Zdd � ZdS ) 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 Zd ZdZdZdZdZdZd(dd�Zdd � Z d d� Z dd � Zdd� Zdd� Z dd� Zdd� Zdd� Zdd� Zdd� Zdd� Zdd� Zd d!� Zd"d#� Zd$d%� Zd&d'� ZdS ))� async_chatz�This is an abstract class. You must derive from this class, and add the two methods collect_incoming_data() and found_terminator()i r zlatin-1Nc C s( d| _ g | _t� | _tj�| ||� d S �N� )�ac_in_buffer�incomingr � producer_fifo�asyncore� dispatcher�__init__)�selfZsock�map� r � /usr/lib64/python3.8/asynchat.pyr C s zasync_chat.__init__c C s t d��d S �Nzmust 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�}| jd d �= |S r )�joinr )r �dr r r � _get_dataW s zasync_chat._get_datac C s t d��d S r r �r r r r �found_terminator\ s zasync_chat.found_terminatorc C sB t |t�r| jrt|| j�}nt |t�r8|dk r8td��|| _dS )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 Ztermr r r �set_terminator_ s zasync_chat.set_terminatorc C s | j S r )r% r r r r �get_terminatorj s zasync_chat.get_terminatorc C s� z| � | j�}W nD tk r& Y d S tk rT } z| �� W Y �d S d }~X Y nX t|t�rr| jrrtt| j �}| j | | _ | j �r�t| j �}| �� }|s�| � | j � d| _ q~t|t��r|}||k r�| � | j � d| _ | j| | _n2| � | j d |� � | j |d � | _ d| _| �� q~t|�}| j �|�}|dk�rv|dk�rX| � | j d |� � | j || d � | _ | �� q~t| j |�}|�r�||k�r�| � | j d | � � | j | d � | _ �q�q~| � | j � d| _ q~d S )Nr r �����)Zrecv�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 ZwhyZlbr% �nZterminator_len�indexr r r �handle_readr sR zasync_chat.handle_readc C s | � � d S r )� initiate_sendr r r r �handle_write� s zasync_chat.handle_writec C s | � � d S r )�closer r r r �handle_close� s zasync_chat.handle_closec C sx t |tttf�stdt|���| j}t|�|kr`tdt|�|�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 Zsabs�ir r r �push� s �zasync_chat.pushc C s | j �|� | �� d S r )r r r3 )r Zproducerr r r �push_with_producer� s zasync_chat.push_with_producerc C s dS )z4predicate for inclusion in the readable for select()� r r r r r �readable� s zasync_chat.readablec C s | j p| j S )z4predicate for inclusion in the writable for select())r � connectedr r r r �writable� s zasync_chat.writablec C s | j �d� dS )zAautomatically close this channel once the outgoing queue is emptyN)r r r r r r �close_when_done� s zasync_chat.close_when_donec C s | j �r| j�r| j d }|s:| j d= |d kr:| �� d S | j}z|d |� }W n: tk r� |�� }|rz| j �|� n| j d= Y q Y nX t|t�r�| j r�t || j�}z| �|�}W n t k r� | �� Y d S X |�r|t|�k s�|t|�k �r ||d � | j d<