
[[\1.                 @   sq   d  Z  d d l Z d d l m Z Gd d   d e j  Z Gd d   d  Z Gd 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 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   s8   d |  _  g  |  _ t   |  _ t j j |  | |  d  S)N    )ac_in_bufferincomingr   producer_fifoasyncore
dispatcher__init__)selfZsockmap r   /usr/lib/python3.4/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  j |  d  S)N)r   append)r   r   r   r   r   _collect_incoming_dataT   s    z!async_chat._collect_incoming_datac             C   s&   d j  |  j  } |  j d  d   =| S)Nr   )joinr   )r   dr   r   r   	_get_dataW   s    zasync_chat._get_datac             C   s   t  d   d  S)Nzmust be implemented in subclass)r   )r   r   r   r   found_terminator\   s    zasync_chat.found_terminatorc             C   sd   t  | t  r- |  j r- t | |  j  } n* t  | t  rW | d k  rW t d   n  | |  _ 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)N)r   )r   r   r   r   get_terminatorj   s    zasync_chat.get_terminatorc             C   sr  y |  j  |  j  } WnH t k
 r. d  SYn3 t k
 r` } z |  j   d  SWYd  d  } ~ Xn Xt | t  r |  j r t t |  j	  } n  |  j
 | |  _
 x|  j
 rmt |  j
  } |  j   } | s |  j |  j
  d |  _
 q t | t  rz| } | | k  r4|  j |  j
  d |  _
 |  j | |  _ qj|  j |  j
 d  |   |  j
 | d   |  _
 d |  _ |  j   q t |  } |  j
 j |  } | d k r| d k r|  j |  j
 d  |   n  |  j
 | | d   |  _
 |  j   q t |  j
 |  } | rQ| | k rM|  j |  j
 d  |   |  j
 | d   |  _
 n  Pq |  j |  j
  d |  _
 q Wd  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   |  j    d  S)N)initiate_send)r   r   r   r   handle_write   s    zasync_chat.handle_writec             C   s   |  j    d  S)N)close)r   r   r   r   handle_close   s    zasync_chat.handle_closec             C   s   t  | t t t f  s0 t d t |    n  |  j } t |  | k r xQ t d t |  |  D]$ } |  j	 j
 | | | |   qd Wn |  j	 j
 |  |  j   d  S)Nz#data argument must be byte-ish (%r)r   )r   r   	bytearray
memoryview	TypeErrortypeac_out_buffer_sizer(   ranger   r   r.   )r   r   Zsabsir   r   r   push   s    	%zasync_chat.pushc             C   s   |  j  j |  |  j   d  S)N)r   r   r.   )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   r   readable   s    zasync_chat.readablec             C   s   |  j  p |  j S)z4predicate for inclusion in the writable for select())r   	connected)r   r   r   r   writable   s    zasync_chat.writablec             C   s   |  j  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   sp  xi|  j  rk|  j rk|  j  d } | sO |  j  d =| d  k rO |  j   d  Sn  |  j } y | d  |  } WnD t k
 r | j   } | r |  j  j |  n
 |  j  d =w Yn Xt | t  r |  j	 r t
 | |  j  } n  y |  j |  } Wn  t k
 r|  j   d  SYn X| rg| t |  k  s@| t |  k  rZ| | d   |  j  d <qg|  j  d =n  d  SWd  S)Nr   )r   r<   r1   r6   r4   more
appendleftr   r   r   r   r   sendr&   r'   r(   )r   firstZobsr   Znum_sentr   r   r   r.      s8    

	

	$zasync_chat.initiate_sendc             C   s*   d |  _  |  j d  d   =|  j j   d  S)Nr   )r   r   r   clear)r   r   r   r   discard_buffers  s    	zasync_chat.discard_buffers)__name__
__module____qualname____doc__r$   r6   r   r   r
   r   r   r   r   r    r!   r-   r/   r1   r9   r:   r;   r=   r>   r.   rD   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_produceri   c             C   s   | |  _  | |  _ d  S)N)r   buffer_size)r   r   rJ   r   r   r   r
     s    	zsimple_producer.__init__c             C   se   t  |  j  |  j k rK |  j d  |  j  } |  j |  j d   |  _ | S|  j } d |  _ | Sd  S)Nr   )r(   r   rJ   )r   resultr   r   r   r?     s    		zsimple_producer.moreN)rE   rF   rG   r
   r?   r   r   r   r   rI     s   rI   c               @   s[   e  Z d  Z d d d  Z d d   Z d d   Z d d	   Z d
 d   Z d d   Z d S)fifoNc             C   s(   | s t    |  _ n t  |  |  _ d  S)N)r   list)r   rM   r   r   r   r
   !  s    zfifo.__init__c             C   s   t  |  j  S)N)r(   rM   )r   r   r   r   __len__'  s    zfifo.__len__c             C   s   |  j  S)N)rM   )r   r   r   r   is_empty*  s    zfifo.is_emptyc             C   s   |  j  d S)Nr   )rM   )r   r   r   r   rB   -  s    z
fifo.firstc             C   s   |  j  j |  d  S)N)rM   r   )r   r   r   r   r   r9   0  s    z	fifo.pushc             C   s$   |  j  r d |  j  j   f Sd Sd  S)Nr"   r   )r   N)rM   popleft)r   r   r   r   pop3  s    	zfifo.pop)	rE   rF   rG   r
   rN   rO   rB   r9   rQ   r   r   r   r   rL      s   rL   c             C   sE   t  |  d } x. | r@ |  j | d  |   r@ | d 8} q W| S)Nr"   )r(   endswith)ZhaystackZneedlelr   r   r   r*   I  s    #r*   )	rH   r   collectionsr   r	   r   rI   rL   r*   r   r   r   r   <module>/   s   )