o
    i                     @   s^   d Z dZddlmZ ddlZG dd dZG dd deZG d	d
 d
eZdd Zd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                   @   s2   e Zd ZdZdddZdd Zdd Zd	d
 ZdS )
_DecoratorzThe mini decorator factoryNc                 C   s
   || _ d S N_target)selftarget r   I/var/www/edux/Edux_v2/venv/lib/python3.10/site-packages/zmq/decorators.py__init__"   s   
z_Decorator.__init__c                    s,   j  i \  fd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                    s    t   fdd}|S )Nc                     s   j | i |}| i .}r|vr||< nr*|v r*tdj| |f } | i |W  d    S 1 s@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
   r   r   wrapper<   s   


$z7_Decorator.__call__.<locals>.decorator.<locals>.wrapperr   )r   r   r   r   r   r
   )r   r   	decorator;   s   z&_Decorator.__call__.<locals>.decorator)process_decorator_args)r
   r   r   r   r   r   r   __call__%   s   z_Decorator.__call__c                 O   s   | j S )zWReturn the target function

        Allows modifying args/kwargs to be passed.
        r   )r
   r   r   r   r   r   r   R   s   z_Decorator.get_targetc                 O   sX   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   r   r   r   r   Y   s   
z!_Decorator.process_decorator_argsr   )r   
__module____qualname____doc__r   r   r   r   r   r   r   r   r      s    
-r   c                       s    e Zd ZdZ fddZ  ZS )_ContextDecoratorzDecorator subclass for Contextsc                    s   t  tj d S r   )superr   zmqContext)r
   	__class__r   r   r   m   s   z_ContextDecorator.__init__)r   r'   r(   r)   r   __classcell__r   r   r.   r   r*   j   s    r*   c                       s0   e Zd ZdZ fddZdd Zdd Z  ZS )_SocketDecoratorzJDecorator subclass for sockets

    Gets the context from other args.
    c                    s0   t  j|i |\}}}|dd| _|||fS )z$Also grab context_name out of kwargscontext_namer   )r+   r   r$   r2   r&   r.   r   r   r   w   s   
z'_SocketDecorator.process_decorator_argsc                 O   s   | j |i |}|jS )z$Get context, based on call-time args)_get_contextr   )r
   r   r   r   r   r   r   r   }   s   z_SocketDecorator.get_targetc                 O   sL   | j |v r|| j  }t|tjr|S |D ]}t|tjr |  S q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
        )r2   r!   r,   r-   instance)r
   r   r   ctxargr   r   r   r3      s   


z_SocketDecorator._get_context)r   r'   r(   r)   r   r   r3   r0   r   r   r.   r   r1   q   s
    r1   c                  O      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
    )r*   r   r   r   r   r   r      s   r   c                  O   r7   )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
    )r1   r8   r   r   r   r      s   r   )
r)   __all__	functoolsr   r,   r   r*   r1   r   r   r   r   r   r   <module>   s    K,