î
&GäRBE  ã               @   so  d  Z  d d l Z d d l Z d d l Z d d l Z d d l Z d d l Z d d l Z d d l m	 Z	 e j
 d d k Z e rÑ e Z e e e ƒ s¤ e j Z n  e d Z e d Z e d Z e Z e Z n e Z e e Z Z e Z e Z d d	 „  Z d
 d „  Z d d „  Z d d „  Z d d „  Z Gd d „  d ƒ Z Gd d „  d e ƒ Z Gd d „  d e ƒ Z  d S)z¸ Module yoton.misc

Defines a few basic constants, classes and functions.

Most importantly, it defines a couple of specific buffer classes that
are used for the low-level messaging.

é    N)Údequeé   ÚstrZunicodeÚxrangec             C   s‹   d } |  ƒ  } t  | t ƒ s- t d ƒ ‚ n  i |  j d 6} xA | j ƒ  D]3 } | | k rm | | | | <qJ t d | ƒ ‚ qJ Wt | �  S)a6   Property(function)
    
    A property decorator which allows to define fget, fset and fdel
    inside the function.
    
    Note that the class to which this is applied must inherit from object!
    Code based on an example posted by Walker Hale:
    http://code.activestate.com/recipes/410698/#c6
    
    ÚfgetÚfsetÚfdelÚdocz+Property function should "return locals()".zInvalid Property element: %s)zfgetzfsetzfdelr	   )Ú
isinstanceÚdictÚRuntimeErrorÚ__doc__ÚkeysÚproperty)ZfunctionZ
known_keysZfunc_localsÚDÚkey© r   úE/Applications/pyzo2014a/lib/python3.4/site-packages/iep/yoton/misc.pyÚProperty*   s    	r   c              C   s£   t  j ƒ  \ }  } } |  t  _ | t  _ | t  _ d } zT t | t t t f ƒ s‰ x5 | r… d | j	 j
 | j	 j j f } | j } qT Wn  Wd ~ Xt | ƒ d | S)z· getErrorMsg()
    Return a string containing the error message. This is usefull, because
    there is no uniform way to catch exception objects in Python 2.x and
    Python 3.x.
    Ú zline %i of %s.NÚ
)ÚsysÚexc_infoZ	last_typeZ
last_valueZlast_tracebackr
   ÚOverflowErrorÚSyntaxErrorÚ
ValueErrorÚtb_frameÚf_linenoÚf_codeÚco_filenameÚtb_nextr   )ÚtypeÚvalueÚtbÚerrr   r   r   ÚgetErrorMsgL   s    				r%   c             C   sk   d } d } d } x* |  D]" } | | d ?t  | ƒ | 7} q W| | d ?t |  ƒ | 7} | | d | S)zñ slot_hash(name)
    
    Given a string (the slot name) returns a number between 8 and 2**64-1
    (just small enough to fit in a 64 bit unsigned integer). The number
    is used as a slot id.
    
    Slots 0-7 are reseved slots.
    
    l   aJ°% r   é   é   r   é@   l            )ÚordÚlen)ÚnameÚfacÚvalÚoffsetÚcr   r   r   Ú	slot_hashi   s    
 r0   c             C   sa   d } d } x* |  D]" } | | d ?t  | ƒ | 7} q W| | d ?t |  ƒ | 7} d | d S)aT   port_hash(name)
    
    Given a string, returns a port number between 49152 and 65535. 
    (2**14 (16384) different posibilities)
    This range is the range for dynamic and/or private ports 
    (ephemeral ports) specified by iana.org.
    The algorithm is deterministic, thus providing a way to map names
    to port numbers.
    
    l   aJ°% r   r'   i À  r   é   i @  )r)   r*   )r+   r,   r-   r/   r   r   r   Ú	port_hash|   s     r2   c             C   s@  t  |  t ƒ s t d ƒ ‚ n  d |  k r9 t d ƒ ‚ n  d } d |  k rz |  j d d ƒ } | d j ƒ  } | d }  n  | s‰ d } n  |  j d d ƒ } t | ƒ \ } } | j ƒ  d	 k rÈ d
 } n  | j ƒ  d k rã d } n  | j ƒ  j d ƒ ry| d d … d k ryt | d d … ƒ } t j	 ƒ  } t j
 | ƒ } y | d | } Wqyt k
 rut d | ƒ ‚ YqyXn  y t | ƒ } WnŒ t k
 rd } d | k r| j d d ƒ } t | ƒ \ } } y t | ƒ } Wqt k
 rÿt d ƒ ‚ YqXn  t | ƒ | } Yn X| d k r3t d ƒ ‚ n  | | | f S)a   split_address(address) -> (protocol, hostname, port)
    
    Split address in protocol, hostname and port. The address has the 
    following format: "protocol://hostname:port". If the protocol is
    omitted, TCP is assumed.
    
    The hostname is the name or ip-address of the computer to connect to. 
    One can use "localhost" for a connection that bypasses some
    network layers (and is not visible from the outside). One can use
    "publichost" for a connection at the current computers IP address
    that is visible from the outside.
    
    The port can be an integer, or a sting. In the latter case the integer
    port number is calculated using a hash. One can also use "portname+offset"
    to specify an integer offset for the port number.
    
    zAddress should be a string.ú:z(Address should be in format 'host:port'.r   z://é   r   ZtcpZ	localhostz	127.0.0.1Z
publichostÚ0é
   NZ
0123456789r   z,Invalid index (%i) in public host addresses.ú+zInvalid offset in addressé   z(The port must be in the range [0, 2^16>.Zpublichost0i   )r
   Ú
basestringr   ÚsplitÚlowerÚtupleÚ
startswithÚintÚsocketZgethostnameZgethostbyname_exÚ
IndexErrorr2   )ZaddressZprotocolÚtmpÚhostZportÚindexZhostnamer.   r   r   r   Úsplit_address�   sP    			+rD   c               @   ss   e  Z d  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 d „  Z d S)ÚUIDzH UID
    
    Represents an 8-byte (64 bit) Unique Identifier.
    
    r   Nc             C   sh   | d  k r7 |  j  ƒ  d >|  _ |  j |  j ƒ  7_ n- t | t t f ƒ rX | |  _ n t d ƒ ‚ d  S)Né    z'The id given to UID() should be an int.)Ú_get_time_intÚ_nrÚ_get_random_intr
   r>   Úlongr   )ÚselfÚidr   r   r   Ú__init__ê   s    zUID.__init__c             C   s.   |  j  ƒ  } d | d  d … | d d  … f S)Nz<UID %s-%s>r&   )Úget_hex)rK   Úhr   r   r   Ú__repr__ô   s    zUID.__repr__c             C   s>   t  |  j ƒ } | d d … j d ƒ } | j d d ƒ } | S)z� get_hex()
        
        Get the hexadecimal representation of this UID. The returned
        string is 16 characters long.
        
        r   NÚLr&   r5   r8   )ÚhexrH   ÚrstripÚljust)rK   rO   r   r   r   rN   ø   s    zUID.get_hexc             C   s   t  j d |  j ƒ S)zE get_bytes()
        
        Get the UID as bytes.
        
        z<Q)ÚstructZpackrH   )rK   r   r   r   Ú	get_bytes  s    zUID.get_bytesc             C   s   |  j  S)zU get_int()
        
        Get the UID as a 64 bit (long) integer.
        
        )rH   )rK   r   r   r   Úget_int  s    zUID.get_intc             C   s   t  j d ƒ S)Nl   ÿÿ )ÚrandomZ	randrange)rK   r   r   r   rI     s    zUID._get_random_intc             C   st   t  t j ƒ  d ƒ } | t j k r5 t j d } n  | t _ | d @} | d k rp | d 7} t j d 7_ n  | S)Niè  r4   l   ÿÿ r   )r>   ÚtimerE   Ú_last_timestamp)rK   Z	timestampr   r   r   rG     s    	

zUID._get_time_int)Ú__name__Ú
__module__Ú__qualname__r   rZ   rM   rP   rN   rV   rW   rI   rG   r   r   r   r   rE   á   s   
rE   c               @   s¡   e  Z d  Z d Z Gd d „  d e ƒ Z d d d „ Z d d „  Z d	 d
 „  Z d d „  Z	 d d „  Z
 d d d „ Z d d d „ Z d d „  Z d d „  Z d S)ÚPackageQueuea]   PackageQueue(N, discard_mode='old')
    
    A queue implementation that can be used in blocking and non-blocking 
    mode and allows peeking. The queue has a limited size. The user
    can specify whether old or new messages should be discarted.
    
    Uses a deque object for the queue and a threading.Condition for
    the blocking.
    
    c               @   s   e  Z d  Z d d „  Z d S)zPackageQueue.Emptyc             C   s   t  j |  d ƒ d  S)Nzpop from an empty PackageQueue)Ú	ExceptionrM   )rK   r   r   r   rM   7  s    zPackageQueue.Empty.__init__N)r[   r\   r]   rM   r   r   r   r   ÚEmpty6  s   r`   Úoldc             C   sv   t  ƒ  |  _ t j ƒ  |  _ t | ƒ |  _ | j ƒ  } | d k rN d |  _ n$ | d k rf d |  _ n t	 d ƒ ‚ d  S)Nra   r4   Únewr   zInvalid discard mode.)
r   Ú_qÚ	threadingZ	ConditionÚ
_conditionr>   Ú_maxlenr;   Ú_discard_moder   )rK   ÚNÚdiscard_moder   r   r   rM   <  s    zPackageQueue.__init__c             C   s   t  |  ƒ |  j k S)zÛ full()
        
        Returns True if the number of elements is at its maximum right now.
        Note that in theory, another thread might pop an element right 
        after this function returns.
        
        )r*   rf   )rK   r   r   r   ÚfullO  s    zPackageQueue.fullc             C   s   t  |  ƒ d k S)zÒ empty()
        
        Returns True if the number of elements is zero right now. Note 
        that in theory, another thread might add an element right
        after this function returns.
        
        r   )r*   )rK   r   r   r   ÚemptyZ  s    zPackageQueue.emptyc          
   C   sœ   |  j  } | j ƒ  zw |  j } t | ƒ |  j k  rN | j | ƒ | j ƒ  n; |  j d k rw | j ƒ  | j | ƒ n |  j d k r‰ n  Wd | j	 ƒ  Xd S)z¤ push(item)
        
        Add an item to the queue. If the queue is full, the oldest
        item in the queue, or the given item is discarted.
        
        r4   r   N)
re   Úacquirerc   r*   rf   ÚappendÚnotifyrg   ÚpopleftÚrelease)rK   ÚxÚ	conditionÚqr   r   r   Úpushe  s    	
	
zPackageQueue.pushc          
   C   sC   |  j  } | j ƒ  z |  j j | ƒ | j ƒ  Wd | j ƒ  Xd S)a   insert(x)
        
        Insert an item at the front of the queue. A call to pop() will
        get this item first. This should be used in rare circumstances
        to give an item priority. This method never causes items to
        be discarted.
        
        N)re   rl   rc   Z
appendleftrn   rp   )rK   rq   rr   r   r   r   Úinsert‚  s    
	
zPackageQueue.insertTc          
   C   sá   |  j  } | j ƒ  z¼ |  j } | sC t | ƒ sÄ |  j ƒ  ‚ qÄ n� | d k ro xr t | ƒ sk | j ƒ  qR WnU t | t ƒ r¸ t | ƒ sÄ | j | ƒ t | ƒ sµ |  j ƒ  ‚ qµ qÄ n t d ƒ ‚ | j	 ƒ  SWd | j
 ƒ  Xd S)a—   pop(block=True)
        
        Pop the oldest item from the queue. If there are no items in the
        queue:
          * the calling thread is blocked until an item is available
            (if block=True, default);
          * an PackageQueue.Empty exception is raised (if block=False);
          * the calling thread is blocked for 'block' seconds (if block
            is a float).
        
        Tz.Invalid value for block in PackageQueue.pop().N)re   rl   rc   r*   r`   Úwaitr
   Úfloatr   ro   rp   )rK   Úblockrr   rs   r   r   r   Úpop•  s$    	
	zPackageQueue.popr   c             C   s   |  j  | S)ac   peek(index=0)
        
        Get an item from the queue without popping it. index=0 gets the
        oldest item, index=-1 gets the newest item. Note that index access
        slows to O(n) time in the middle of the queue (due to the undelying
        deque object).
        
        Raises an IndexError if the index is out of range.
        
        )rc   )rK   rC   r   r   r   Úpeek¿  s    zPackageQueue.peekc             C   s   |  j  j ƒ  S)N)rc   Ú__len__)rK   r   r   r   r{   Í  s    zPackageQueue.__len__c          
   C   s3   |  j  j ƒ  z |  j j ƒ  Wd |  j  j ƒ  Xd S)zL clear()
        
        Remove all items from the queue.
        
        N)re   rl   rc   Úclearrp   )rK   r   r   r   r|   Ñ  s    zPackageQueue.clearN)r[   r\   r]   r   r_   r`   rM   rj   rk   rt   ru   ry   rz   r{   r|   r   r   r   r   r^   *  s   
*r^   c               @   sO   e  Z d  Z d Z d d d d „ Z d d „  Z d d	 d
 „ Z d d „  Z d S)ÚTinyPackageQueueap   TinyPackageQueue(N1, N2, discard_mode='old', timeout=1.0)
    
    A queue implementation that can be used in blocking and non-blocking 
    mode and allows peeking. The queue has a tiny-size (N1). When this size
    is reached, a call to push() blocks for up to timeout seconds. The
    real size (N2) is the same as in the PackageQueue class. 
    
    The tinysize mechanism can be used to semi-synchronize a consumer
    and a producer, while still having a small queue and without having
    the consumer fully block.
    
    Uses a deque object for the queue and a threading.Condition for
    the blocking.
    
    ra   g      ð?c             C   s/   t  j |  | | ƒ t | ƒ |  _ | |  _ d  S)N)r^   rM   r>   Ú_tinylenÚ_timeout)rK   ZN1ZN2ri   Ztimeoutr   r   r   rM   ñ  s    zTinyPackageQueue.__init__c          
   C   sÑ   |  j  } | j ƒ  z¬ |  j } t | ƒ } | |  j k  rT | j | ƒ | j ƒ  nj | |  j k  rƒ | j |  j	 ƒ | j | ƒ n; |  j
 d k r¬ | j ƒ  | j | ƒ n |  j
 d k r¾ n  Wd | j ƒ  Xd S)zÒ push(item)
        
        Add an item to the queue. If the queue has >= n1 values, 
        this function will block timeout seconds, or until an item is
        popped from another thread.
        
        r4   r   N)re   rl   rc   r*   r~   rm   rn   rf   rv   r   rg   ro   rp   )rK   rq   rr   rs   Úlqr   r   r   rt   û  s"    		
	
zTinyPackageQueue.pushTc          
   C   s  |  j  } | j ƒ  zÞ |  j } | sC t | ƒ sÄ |  j ƒ  ‚ qÄ n� | d k ro xr t | ƒ sk | j ƒ  qR WnU t | t ƒ r¸ t | ƒ sÄ | j | ƒ t | ƒ sµ |  j ƒ  ‚ qµ qÄ n t d ƒ ‚ t | ƒ |  j	 k ræ | j
 ƒ  n  | j ƒ  SWd | j ƒ  Xd S)a–   pop(block=True)
        
        Pop the oldest item from the queue. If there are no items in the
        queue:
          * the calling thread is blocked until an item is available
            (if block=True, default);
          * a PackageQueue.Empty exception is raised (if block=False);
          * the calling thread is blocked for 'block' seconds (if block
            is a float).
        
        Tz.Invalid value for block in PackageQueue.pop().N)re   rl   rc   r*   r`   rv   r
   rw   r   r~   Z	notifyAllro   rp   )rK   rx   rr   rs   r   r   r   ry     s(    	
	zTinyPackageQueue.popc          
   C   sa   |  j  j ƒ  z? t |  j ƒ } |  j j ƒ  | |  j k rK |  j  j ƒ  n  Wd |  j  j ƒ  Xd S)zL clear()
        
        Remove all items from the queue.
        
        N)re   rl   r*   rc   r|   r~   rn   rp   )rK   r€   r   r   r   r|   M  s    zTinyPackageQueue.clearN)r[   r\   r]   r   rM   rt   ry   r|   r   r   r   r   r}   à  s
   
#/r}   )!r   Úosr   rY   rU   r?   rd   rX   Zcollectionsr   Úversion_infoZV2Ú__builtins__r   r
   r   Ú__dict__Úbytesr   r   r9   rJ   r>   Úranger   r%   r0   r2   rD   rE   Úobjectr^   r}   r   r   r   r   Ú<module>   s8   $


	"RI¶