
    ye                         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	dS )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dS )
_DecoratorzThe mini decorator factoryNc                     || _         d S N_target)selftargets     .lib/python3.11/site-packages/zmq/decorators.py__init__z_Decorator.__init__"   s        c                 @       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                 F     t                      fd            }|S )Nc                       j         | i |} |i 5 }r
|vr||<   n4r,|v r(t          d                    j                            | |fz   }  | i |cd d d            S # 1 swxY w Y   d S )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9VX444 1 -7&#8#8*-w  -W%6%6'--3VDM7-K-K  
  $sf}40001 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1s   AA,,A03A0r   )r   r    r   r   r   r   s   ` r   	decoratorz&_Decorator.__call__.<locals>.decorator;   sH    4[[1 1 1 1 1 1 1 1 [1" Nr   )process_decorator_args)r   r   r   r!   r   s   ``` @r   __call__z_Decorator.__call__%   s_    $ )D(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          |                    d          t                    r|                    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   s~     fjj((#.. 	jj((GGYY!^^
47C 8 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                   d S 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                 ~     t                      j        |i |\  }}}|                    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   sH     > > O O Ov"JJ~yA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4~r   c                     | j         |v r)|| j                  }t          |t          j                  r|S |D ] }t          |t          j                  r|c S !t          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   s     &&*+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      s    (
       



H% H% H% H% H% H% H% H%V& & & & &
 & & &)& )& )& )& )&z )& )& )&X0 0 0 / / / / /r   