o
    b                     @   s   d Z ddlmZ ddlmZmZ ddlmZ ddlm	Z	 ddl
mZ G dd dZG d	d
 d
ZG dd dZG dd dZG dd deZeejG dd deZG dd dejZdd ZdS )z
Utility classes for spread.
    )implementer)defer
interfaces)basic)Failure)pbc                   @   s   e Zd Zdd Zdd ZdS )LocalMethodc                 C   s   || _ || _d S N)localname)selfr
   r    r   5/usr/lib/python3/dist-packages/twisted/spread/util.py__init__      
zLocalMethod.__init__c                 O   s   | j j| jg|R i |S r	   )r
   
callRemoter   )r   argskwr   r   r   __call__   s   zLocalMethod.__call__N)__name__
__module____qualname__r   r   r   r   r   r   r      s    r   c                   @   s$   e Zd ZdZdZdd Zdd ZdS )LocalAsRemotezN
    A class useful for emulating the effects of remote behavior locally.
       c                 O   s|   t | d| rt| d| |i |S zt| d| }t||i |W S  ty=   t }| jr6|  t| Y S w )ax  
        Call a specially-designated local method.

        self.callRemote('x') will first try to invoke a method named
        sync_x and return its result (which should probably be a
        Deferred).  Second, it will look for a method called async_x,
        which will be called and then have its result (or Failure)
        automatically wrapped in a Deferred.
        sync_async_)	hasattrgetattrr   succeedBaseExceptionr   reportAllTracebacksprintTracebackfail)r   r   r   r   methodfr   r   r   r   #   s   
zLocalAsRemote.callRemotec                 C   s
   t | |S r	   )r   )r   r   r   r   r   remoteMethod8      
zLocalAsRemote.remoteMethodN)r   r   r   __doc__r    r   r%   r   r   r   r   r      s
    r   c                   @   s*   e Zd ZdZd
ddZdd Zdd Zd	S )LocalAsyncForwarderzD
    A class useful for forwarding a locally-defined interface.
    r   c                 C   s$   | |sJ || _|| _|| _d S r	   )
providedBy	forwardedinterfaceClassfailWhenNotImplemented)r   r*   r+   r,   r   r   r   r   A   s   
zLocalAsyncForwarder.__init__c                 O   s   t | j||i |S r	   )r   r*   )r   r#   r   r   r   r   r   _callMethodG   s   zLocalAsyncForwarder._callMethodc                 O   sP   | j |rtj| j|g|R i |}|S | jr#tttd| S t	d S )NzNo Such Method in Interface: %s)
r+   queryDescriptionForr   maybeDeferredr-   r,   r"   r   NotImplementedErrorr   )r   r#   r   r   resultr   r   r   r   J   s   
zLocalAsyncForwarder.callRemoteN)r   )r   r   r   r'   r   r-   r   r   r   r   r   r(   <   s
    
r(   c                   @   s:   e Zd ZdZdddZdd Zdd Zd	d
 Zdd ZdS )Pagerz5
    I am an object which pages out information.
    Nc                 O   s>   t |r|| _|| _|| _nd| _d| _|| _|j|  dS )z
        Create a pager with a Reference to a remote collector and
        an optional callable to invoke upon completion.
        Nr   )callablecallbackcallbackArgscallbackKeyword_stillPaging	collectorbrokerregisterPageProducer)r   r8   r4   r   r   r   r   r   r   [   s   zPager.__init__c                 C   s:   | j s| jjddd | jdur| j| ji | j | j S )5
        (internal) Method called by Broker.
        endedPagingFpbanswerN)r7   r8   r   r4   r5   r6   r   r   r   r   stillPagingj   s
   
zPager.stillPagingc                 C   s   | j jd|  dd dS )r;   gotPageFr=   N)r8   r   nextPager?   r   r   r   sendNextPaget   s   zPager.sendNextPagec                 C   s   t  )zO
        Override this to return an object to be sent to my collector.
        )r0   r?   r   r   r   rB   z   s   zPager.nextPagec                 C   s
   d| _ dS )z4
        Call this when you're done paging.
        r   N)r7   r?   r   r   r   
stopPaging   s   
zPager.stopPagingr	   )	r   r   r   r'   r   r@   rC   rB   rD   r   r   r   r   r2   V   s    

r2   c                   @   s"   e Zd ZdZdddZdd ZdS )	StringPagerz:
    A simple pager that splits a string into chunks.
        Nc                 O   s2   || _ d| _|| _tj| ||g|R i | d S )Nr   )stringpointer	chunkSizer2   r   )r   r8   strI   r4   r   r   r   r   r   r      s    zStringPager.__init__c                 C   sD   | j | j| j| j  }|  j| j7  _| jt| j kr |   |S r	   )rG   rH   rI   lenrD   r   valr   r   r   rB      s
   zStringPager.nextPage)rF   N)r   r   r   r'   r   rB   r   r   r   r   rE      s    
rE   c                   @   sB   e 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S )	FilePagerzC
    Reads a file in chunks and sends the chunks as they come.
    Nc                 O   s0   g | _ tj| ||g|R i | | | d S r	   )chunksr2   r   startProducing)r   r8   fdr4   r   r   r   r   r   r      s   zFilePager.__init__c                    s*   t  |  _ j fdd d S )Nc                    s      S r	   )rD   )xr?   r   r   <lambda>   s    z*FilePager.startProducing.<locals>.<lambda>)r   
FileSenderbeginFileTransferdeferredaddBoth)r   rQ   r   r?   r   rP      s   zFilePager.startProducingc                 C   s   || _ |s| j   d S d S r	   )producerresumeProducing)r   rX   	streamingr   r   r   registerProducer   s   zFilePager.registerProducerc                 C   s
   d | _ d S r	   )rX   r?   r   r   r   unregisterProducer   r&   zFilePager.unregisterProducerc                 C      | j | d S r	   )rO   append)r   chunkr   r   r   write      zFilePager.writec                 C   s6   | j sdS | j d}| j  | jjd|dd dS )zD
        Get the first chunk read and send it to collector.
        Nr   rA   Fr=   )rO   poprX   rY   r8   r   rL   r   r   r   rC      s
   
zFilePager.sendNextPager	   )
r   r   r   r'   r   rP   r[   r\   r`   rC   r   r   r   r   rN      s    
rN   c                   @   s(   e Zd ZdZdd Zdd Zdd ZdS )	CallbackPageCollectorz
    I receive pages from the peer. You may instantiate a Pager with a
    remote reference to me. I will call the callback with a list of pages
    once they are all received.
    c                 C   s   g | _ || _d S r	   )pagesr4   )r   r4   r   r   r   r      r   zCallbackPageCollector.__init__c                 C   r]   r	   )rd   r^   )r   pager   r   r   remote_gotPage   ra   z$CallbackPageCollector.remote_gotPagec                 C   s   |  | j d S r	   )r4   rd   r?   r   r   r   remote_endedPaging   ra   z(CallbackPageCollector.remote_endedPagingN)r   r   r   r'   r   rf   rg   r   r   r   r   rc      s
    rc   c                 O   s,   t  }| j|t|jg|R i | |S )zr
    A utility method that will call a remote method which expects a
    PageCollector as the first argument.
    )r   Deferredr   rc   r4   )referenceable
methodNamer   r   dr   r   r   getAllPages   s    rl   N)r'   zope.interfacer   twisted.internetr   r   twisted.protocolsr   twisted.python.failurer   twisted.spreadr   r   r   r(   r2   rE   	IConsumerrN   Referenceablerc   rl   r   r   r   r   <module>   s   	 1%