U
    W[                     @   s   d Z ddlmZ ddlmZ ddl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.
    )defer)Failure)pb)basic)
interfaces)implementerc                   @   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__   s    zLocalMethod.__init__c                 O   s   | j j| jf||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   sr   t | d| r"t| d| ||S z t| d| }t|||W S    t }| jr^|  t| Y S X dS )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.
        Zsync_Zasync_N)hasattrgetattrr   succeedr   reportAllTracebacksZ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   s    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t|| _|| _|| _d S r	   )Z
providedByAssertionError	forwardedinterfaceClassfailWhenNotImplemented)r   r$   r%   r&   r   r   r   r   A   s    zLocalAsyncForwarder.__init__c                 O   s   t | j|||S r	   )r   r$   )r   r   r   r   r   r   r   _callMethodG   s    zLocalAsyncForwarder._callMethodc                 O   sN   | j |r&tj| j|f||}|S | jr@tttd| S t	d S d S )NzNo Such Method in Interface: %s)
r%   ZqueryDescriptionForr   Z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	collectorZbrokerZregisterPageProducer)r   r0   r,   r   r   r   r   r   r   Z   s    zPager.__init__c                 C   s6   | j s0| jjddd | jdk	r0| j| j| j | j S )5
        (internal) Method called by Broker.
        ZendedPagingFZpbanswerN)r/   r0   r   r,   r-   r.   r   r   r   r   stillPagingi   s
    
zPager.stillPagingc                 C   s   | j jd|  dd dS )r1   gotPageFr2   N)r0   r   nextPager3   r   r   r   sendNextPages   s    zPager.sendNextPagec                 C   s
   t  dS )zO
        Override this to return an object to be sent to my collector.
        N)r(   r3   r   r   r   r6   y   s    zPager.nextPagec                 C   s
   d| _ dS )z4
        Call this when you're done paging.
        r   N)r/   r3   r   r   r   
stopPaging   s    zPager.stopPaging)N)	r   r   r   r!   r   r4   r7   r6   r8   r   r   r   r   r*   V   s   

r*   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   s,   || _ d| _|| _tj| ||f|| d S )Nr   )stringpointer	chunkSizer*   r   )r   r0   str=   r,   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	   )r;   r<   r=   lenr8   r   valr   r   r   r6      s
    zStringPager.nextPage)r:   N)r   r   r   r!   r   r6   r   r   r   r   r9      s   
r9   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   s*   g | _ tj| ||f|| | | d S r	   )chunksr*   r   startProducing)r   r0   fdr,   r   r   r   r   r   r      s    zFilePager.__init__c                    s*   t  |  _ j fdd d S )Nc                    s      S r	   )r8   )xr3   r   r   <lambda>       z*FilePager.startProducing.<locals>.<lambda>)r   Z
FileSenderZbeginFileTransferZdeferredZaddBoth)r   rE   r   r3   r   rD      s    zFilePager.startProducingc                 C   s   || _ |s| j   d S r	   )producerresumeProducing)r   rI   Z	streamingr   r   r   registerProducer   s    zFilePager.registerProducerc                 C   s
   d | _ d S r	   )rI   r3   r   r   r   unregisterProducer   s    zFilePager.unregisterProducerc                 C   s   | j | d S r	   )rC   append)r   chunkr   r   r   write   s    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   r5   Fr2   )rC   poprI   rJ   r0   r   r@   r   r   r   r7      s
    
zFilePager.sendNextPage)N)
r   r   r   r!   r   rD   rK   rL   rO   r7   r   r   r   r   rB      s   
rB   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	   )pagesr,   )r   r,   r   r   r   r      s    zCallbackPageCollector.__init__c                 C   s   | j | d S r	   )rR   rM   )r   Zpager   r   r   remote_gotPage   s    z$CallbackPageCollector.remote_gotPagec                 C   s   |  | j d S r	   )r,   rR   r3   r   r   r   remote_endedPaging   s    z(CallbackPageCollector.remote_endedPagingN)r   r   r   r!   r   rS   rT   r   r   r   r   rQ      s   rQ   c                 O   s&   t  }| j|t|jf|| |S )zr
    A utility method that will call a remote method which expects a
    PageCollector as the first argument.
    )r   ZDeferredr   rQ   r,   )ZreferenceableZ
methodNamer   r   dr   r   r   getAllPages   s    rV   N)r!   Ztwisted.internetr   Ztwisted.python.failurer   Ztwisted.spreadr   Ztwisted.protocolsr   r   Zzope.interfacer   r   r   r"   r*   r9   Z	IConsumerrB   ZReferenceablerQ   rV   r   r   r   r   <module>   s   	0%