
    Ef                     l    d Z dZddlmZ ddlZ G d d      Z G d de      Z G d	 d
e      Zd Zd Z	y)ai  Decorators for running functions with context/sockets.

.. versionadded:: 15.3

Like using Contexts and Sockets as context managers, but with decorator syntax.
Context and sockets are closed at the end of the function.

For example::

    from zmq.decorators import context, socket
    
    @context()
    @socket(zmq.PUSH)
    def work(ctx, push):
        ...
)contextsocket    wrapsNc                   *    e Zd ZdZddZd Zd Zd Zy)
_DecoratorzThe mini decorator factoryNc                     || _         y N_target)selftargets     0/usr/lib/python3/dist-packages/zmq/decorators.py__init__z_Decorator.__init__"   s	        c                 J       j                   i \   fd}|S )a  
        The main logic of decorator

        Here is how those arguments works::

            @out_decorator(*dec_args, *dec_kwargs)
            def func(*wrap_args, **wrap_kwargs):
                ...

        And in the ``wrapper``, we simply create ``self.target`` instance via
        ``with``::

            target = self.get_target(*args, **kwargs)
            with target(*dec_args, **dec_kwargs) as obj:
                ...

        c                 8     t                fd       }|S )Nc                       j                   | i |} |i 5 }r
|vr||<   n1r)|v r%t        dj                  j                              | |fz   }  | i |cd d d        S # 1 sw Y   y xY w)Nz*{}() got multiple values for argument '{}')
get_target	TypeErrorformat__name__)	argskwargsr   objdec_args
dec_kwargsfunckw_namer   s	       r   wrapperz7_Decorator.__call__.<locals>.decorator.<locals>.wrapper<   s    ($9&9X44 17&#8*-w W%6'--3VDMM7-K 
  $sf}001 1 1s   AA++A4r   )r   r    r   r   r   r   s   ` r   	decoratorz&_Decorator.__call__.<locals>.decorator;   s     4[1 1" Nr   )process_decorator_args)r   r   r   r!   r   s   ``` @r   __call__z_Decorator.__call__%   s7    $ )D(C(C)
#)
%:	* r   c                     | j                   S )zWReturn the target function

        Allows modifying args/kwargs to be passed.
        r   )r   r   r   s      r   r   z_Decorator.get_targetR   s    
 ||r   c                     d}t        |j                  d      t              r|j                  d      }n+t	        |      dk\  rt        |d   t              r
|d   }|dd }|||fS )zProcess args passed to the decorator.

        args not consumed by the decorator will be passed to the target factory
        (Context/Socket constructor).
        Nname   r   )
isinstancegetstrpoplen)r   r   r   r   s       r   r"   z!_Decorator.process_decorator_argsY   sc     fjj(#.jj(GY!^
47C 81gG8Df$$r   r
   )r   
__module____qualname____doc__r   r#   r   r"    r   r   r   r      s    $+Z%r   r   c                   "     e Zd ZdZ fdZ xZS )_ContextDecoratorzDecorator subclass for Contextsc                 @    t         |   t        j                         y r
   )superr   zmqContext)r   	__class__s    r   r   z_ContextDecorator.__init__m   s    %r   )r   r-   r.   r/   r   __classcell__r7   s   @r   r2   r2   j   s    )& &r   r2   c                   .     e Zd ZdZ fdZd Zd Z xZS )_SocketDecoratorzJDecorator subclass for sockets

    Gets the context from other args.
    c                 b    t        |   |i |\  }}}|j                  dd      | _        |||fS )z$Also grab context_name out of kwargscontext_namer   )r4   r"   r+   r=   )r   r   r   r   r7   s       r   r"   z'_SocketDecorator.process_decorator_argsw   s>     % > O Ov"JJ~yAf$$r   c                 >     | j                   |i |}|j                  S )z$Get context, based on call-time args)_get_contextr   )r   r   r   r   s       r   r   z_SocketDecorator.get_target}   s#    #$##T4V4~~r   c                     | j                   |v r+|| j                      }t        |t        j                        r|S |D ]   }t        |t        j                        s|c S  t        j                  j	                         S )a  
        Find the ``zmq.Context`` from ``args`` and ``kwargs`` at call time.

        First, if there is an keyword argument named ``context`` and it is a
        ``zmq.Context`` instance , we will take it.

        Second, we check all the ``args``, take the first ``zmq.Context``
        instance.

        Finally, we will provide default Context -- ``zmq.Context.instance``

        :return: a ``zmq.Context`` instance
        )r=   r(   r5   r6   instance)r   r   r   ctxargs        r   r?   z_SocketDecorator._get_context   sl     &**+C#s{{+
 	C#s{{+
	 {{##%%r   )r   r-   r.   r/   r"   r   r?   r8   r9   s   @r   r;   r;   q   s    
%
&r   r;   c                  "     t               | i |S )zDecorator for adding a Context to a function.

    Usage::

        @context()
        def foo(ctx):
            ...

    .. versionadded:: 15.3

    :param str name: the keyword argument passed to decorated function
    )r2   r   r   s     r   r   r      s     ///r   c                  "     t               | i |S )aS  Decorator for adding a socket to a function.

    Usage::

        @socket(zmq.PUSH)
        def foo(push):
            ...

    .. versionadded:: 15.3

    :param str name: the keyword argument passed to decorated function
    :param str context_name: the keyword only argument to identify context
                             object
    )r;   rE   s     r   r   r      s     t.v..r   )
r/   __all__	functoolsr   r5   r   r2   r;   r   r   r0   r   r   <module>rI      sI   (
  
H% H%V&
 &)&z )&X0 /r   