B
    b
,c/                 @   s   d Z ddlZddlZddlmZ ddlmZmZmZm	Z	m
Z
mZmZ ddlmZ ddlmZ ddlmZ ddlmZmZmZ dd	lmZ d
dlmZmZ d
dlmZ daddddZ e!e  edddZ"eddddZ#G dd deeee# ZdgZ$dS )zPython bindings for 0MQ.    N)Lock)AnyDictGenericListOptionalTypeTypeVar)warn)WeakSet)Context)ContextOptionErrnoSocketOption)ZMQError   )AttributeSetterOptValT)SocketF)returnc               C   s   da d S )NT)_exiting r   r   0lib/python3.7/site-packages/zmq/sugar/context.py_notice_atexit   s    r   Tr   )boundSTr   T)r   Z	covariantc                   s  e Zd ZU dZeeef ed< dZeed< e	 Z
dZee ed< dZdZeed< eZee ed< dDd
eedd fddZddddZdZedddZeedddZeeeddddZdEeeedddZeZeee eedddZeee eed d!d"Z edFee eed#d$d%Z!dd fd&d'Z"e#e dd(d)Z$edd*d+d,Z%edd*d-d.Z&dGee dd/d0d1Z'eeeed2d3d4Z(eedd5d6d7Z)ee*d8d9d:Z+eee*dd;d<d=Z,eee*d>d?d@Z-eddAdBdCZ.  Z/S )Hr   au  Create a zmq Context

    A zmq Context creates sockets via its ``ctx.socket`` method.

    .. versionchanged:: 24

        When using a Context as a context manager (``with zmq.Context()``),
        or deleting a context without closing it first,
        ``ctx.destroy()`` is called,
        closing any leftover sockets,
        instead of `ctx.term()` which requires sockets to be closed first.

        This prevents hangs caused by `ctx.term()` if sockets are left open,
        but means that unclean destruction of contexts
        (with sockets left open) is not safe
        if sockets are managed in other threads.
    sockoptsN	_instance_instance_pidF_sockets_socket_classr   zContext[Socket])self
io_threadskwargsr   c                sB   t  jf d|i| |ddr*d| _nd| _i | _t | _d S )Nr#   shadowFT)super__init__get_shadowr   r   r    )r"   r#   r$   )	__class__r   r   r'   @   s    zContext.__init__)r   c             C   sR   t   | jsNtsN| jsNd| _trFt| dddk	rFtd|  td| d |   dS )a)  Deleting a Context without closing it destroys it and all sockets.

        .. versionchanged:: 24
            Switch from threadsafe `term()` which hangs in the event of open sockets
            to less safe `destroy()` which
            warns about any leftover sockets and closes them.
        Tr    NzUnclosed context    )
stacklevelsource)	localsr)   r   closed_warn_destroy_closer
   getattrResourceWarningdestroy)r"   r   r   r   __del__I   s    
zContext.__del__zzmq.Contextc             C   s   | j }|jdd }|d kr.|j d|j }| jr8dnd}t| dd rrt| j}|dkr^dnd}| d| }nd}d	| d
| dt	t
|  | dS )N	_repr_cls.z closed r    r   sz socket<(z) at >)r*   __dict__r(   
__module____name__r/   r1   lenr    hexid)r"   clsr5   r/   Z	n_socketsr8   socketsr   r   r   __repr__c   s    
zContext.__repr__)r"   r   c             C   s   | S )Nr   )r"   r   r   r   	__enter__s   s    zContext.__enter__)exc_type	exc_value	tracebackr   c             C   s   d| _ |   d S )NT)r0   r3   )r"   rF   rG   rH   r   r   r   __exit__v   s    zContext.__exit__)r"   memor   c             C   s   | j | jS )z'Copying a Context creates a shadow copy)r*   r%   
underlying)r"   rJ   r   r   r   __copy__{   s    zContext.__copy__)rB   addressr   c             C   s   ddl m} ||}| |dS )zShadow an existing libzmq context

        address is the integer address of the libzmq context
        or an FFI pointer to it.

        .. versionadded:: 14.1
        r   )cast_int_addr)r%   )zmq.utils.interoprN   )rB   rM   rN   r   r   r   r%      s    	zContext.shadow)rB   ctxr   c             C   s4   ddl m} ddlm} ||}||}| |dS )zuShadow an existing pyczmq context

        ctx is the FFI `zctx_t *` pointer

        .. versionadded:: 14.1
        r   )zctx)rN   )r%   )ZpyczmqrQ   rO   rN   rK   )rB   rP   rQ   rN   rK   rM   r   r   r   shadow_pyczmq   s
    
zContext.shadow_pyczmq)rB   r#   r   c          	   C   sn   | j dks | jt ks | j jrh| j< | j dksH| jt ksH| j jr^| |d| _ t | _W dQ R X | j S )a  Returns a global Context instance.

        Most single-threaded applications have a single, global Context.
        Use this method instead of passing around Context instances
        throughout your code.

        A common pattern for classes that depend on Contexts is to use
        a default argument to enable programs with multiple Contexts
        but not require the argument for simpler applications::

            class MyClass(object):
                def __init__(self, context=None):
                    self.context = context or Context.instance()

        .. versionchanged:: 18.1

            When called in a subprocess after forking,
            a new global instance is created instead of inheriting
            a Context that won't work from the parent process.
        N)r#   )r   r   osgetpidr/   _instance_lock)rB   r#   r   r   r   instance   s    

zContext.instancec                s   t    dS )aL  Close or terminate the context.

        Context termination is performed in the following steps:

        - Any blocking operations currently in progress on sockets open within context shall
          raise :class:`zmq.ContextTerminated`.
          With the exception of socket.close(), any further operations on sockets open within this context
          shall raise :class:`zmq.ContextTerminated`.
        - After interrupting all blocking calls, term shall block until the following conditions are satisfied:
            - All sockets open within context have been closed.
            - For each socket within context, all messages sent on the socket have either been
              physically transferred to a network peer,
              or the socket's linger period set with the zmq.LINGER socket option has expired.

        For further details regarding socket linger behaviour refer to libzmq documentation for ZMQ_LINGER.

        This can be called to close the context by hand. If this is not called,
        the context will automatically be closed when it is garbage collected.
        N)r&   term)r"   )r*   r   r   rW      s    zContext.termc             C   s   t | j}|tj |S )N)dirr*   extendr   __members__)r"   keysr   r   r   __dir__   s    
zContext.__dir__)socketr   c             C   s   | j | dS )zBAdd a weakref to a socket for Context.destroy / reference countingN)r    add)r"   r]   r   r   r   _add_socket   s    zContext._add_socketc             C   s    t | dddk	r| j| dS )z8Remove a socket for Context.destroy / reference countingr    N)r1   r    discard)r"   r]   r   r   r   
_rm_socket   s    zContext._rm_socket)lingerr   c             C   s   | j r
dS tt| ddpg }xT|D ]L}|r$|j s$| jrRtrRtd| td|d |dk	rh|tj| |	  q$W | 
  dS )a  Close all sockets associated with this context and then terminate
        the context.

        .. warning::

            destroy involves calling ``zmq_close()``, which is **NOT** threadsafe.
            If there are active sockets in other threads, this must not be called.

        Parameters
        ----------

        linger : int, optional
            If specified, set LINGER on sockets prior to closing them.
        Nr    z(Destroying context with unclosed socket    )r,   r-   )r/   listr1   r0   r
   r2   
setsockoptr   ZLINGERcloserW   )r"   rb   rC   r8   r   r   r   r3      s    


zContext.destroy)r"   socket_typer$   r   c          	   K   sl   | j rttj| j| |f|}x<| j D ].\}}y||| W q, tk
rX   Y q,X q,W | | |S )a]  Create a Socket associated with this Context.

        Parameters
        ----------
        socket_type : int
            The socket type, which can be any of the 0MQ socket types:
            REQ, REP, PUB, SUB, PAIR, DEALER, ROUTER, PULL, PUSH, etc.

        kwargs:
            will be passed to the __init__ method of the socket class.
        )	r/   r   r   ZENOTSUPr!   r   itemsre   r_   )r"   rg   r$   r8   optvaluer   r   r   r]     s    


zContext.socket)ri   rj   r   c             C   s   || j |< dS )zkset default socket options for new sockets created by this Context

        .. versionadded:: 13.0
        N)r   )r"   ri   rj   r   r   r   re   1  s    zContext.setsockopt)ri   r   c             C   s
   | j | S )zkget default socket options for new sockets created by this Context

        .. versionadded:: 13.0
        )r   )r"   ri   r   r   r   
getsockopt8  s    zContext.getsockopt)nameri   rj   r   c             C   s>   |t jkr| ||S |tjkr,|| j|< ntd| dS )z"set default sockopts as attributesz"No such context or socket option: N)r   rZ   setr   r   AttributeError)r"   rl   ri   rj   r   r   r   _set_attr_opt?  s
    

zContext._set_attr_opt)rl   ri   r   c             C   s6   |t jkr| |S || jkr(t|n
| j| S dS )z"get default sockopts as attributesN)r   rZ   r(   r   rn   )r"   rl   ri   r   r   r   _get_attr_optH  s
    



zContext._get_attr_opt)keyr   c             C   sZ   |  }ytt|}W n" tk
r8   td|Y nX || jkrNt|n| j|= dS )z%delete default sockopts as attributeszNo such socket option: N)upperr1   r   rn   r   )r"   rq   ri   r   r   r   __delattr__R  s    

zContext.__delattr__)r   )N)r   )N)0r>   r=   __qualname____doc__r   intr   __annotations__r   r   rU   r   r   r)   r0   r   r   r!   r   r   r'   r4   r5   strrD   r   rE   rI   rL   __deepcopy__classmethodr%   rR   rV   rW   r   r\   r_   ra   r3   r]   re   r   rk   ro   rp   rs   __classcell__r   r   )r*   r   r   #   sD   
	$	#	
)%ru   atexitrS   Z	threadingr   typingr   r   r   r   r   r   r	   warningsr
   weakrefr   Zzmq.backendr   ZContextBaseZzmq.constantsr   r   r   Z	zmq.errorr   Z	attrsettrr   r   r]   r   r   r   registerr   r   __all__r   r   r   r   <module>   s(   $
  ?