o
    Zh                     @  sj   d Z ddlm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 )ae  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):
        ...
    )annotations)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   E/var/www/html/lang_env/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 0}r|vr||< nr,|v r,tj d d| |f } | i |W  d    S 1 sBw   Y  d S )Nz%() got multiple values for argument '')
get_target	TypeError__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   T   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   [   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   o   s   z_ContextDecorator.__init__)r   r(   r)   r*   r   __classcell__r   r   r/   r   r+   l   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%   r3   r'   r/   r   r   r   y   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
        )r3   r"   r-   r.   instance)r   r   r   ctxargr   r   r   r4      s   


z_SocketDecorator._get_context)r   r(   r)   r*   r   r   r4   r1   r   r   r/   r   r2   s   s
    r2   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  r8   )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
    )r2   r9   r   r   r   r      s   r   )r*   
__future__r   __all__	functoolsr   r-   r   r+   r2   r   r   r   r   r   r   <module>   s    K,