U if@, @ sD d Z ddlZddlmZ G dd dejZG dd dZdd 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(ddZdd 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_chatzThis 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_bufferincomingr producer_fifoasyncore dispatcher__init__)selfZsockmap r -/opt/alt/python38/lib64/python3.8/asynchat.pyr C s zasync_chat.__init__c C s t dd S Nzmust be implemented in subclassNotImplementedErrorr 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 dd S r r r r r r found_terminator\ s zasync_chat.found_terminatorc C sB t |tr| jrt|| j}nt |tr8|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) isinstancestruse_encodingbytesencodingint 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|trr| jrrtt| j }| j | | _ | j rt| j }| }|s| | j d| _ q~t|tr|}||k r| | j d| _ | j| | _n2| | j d | | j |d | _ d| _| q~t|}| j |}|dkrv|dkrX| | j d | | j || d | _ | q~t| j |}|r||kr| | j d | | j | d | _ qq~| | j d| _ q~d S )Nr r )Zrecvac_in_buffer_sizeBlockingIOErrorOSErrorhandle_errorr r r r! r" r lenr' r r# r% r findfind_prefix_at_end)r r ZwhyZlbr% nZterminator_lenindexr 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 |tttfstdt|| j}t||kr`tdt||D ]}| j |||| q@n| j | | d S )Nz#data argument must be byte-ish (%r)r )r r! bytearray memoryview TypeErrortypeac_out_buffer_sizer- ranger r r3 )r r Zsabsir 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| jr| 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|tr| j rt || j}z| |}W n t k r | Y d S X |r|t|k s|t|k r ||d | j d<