
    `f@v                       d Z ddlZddlZddlZddlmZmZ ddlmZ ddl	m
Z
 ddlmZ ddlmZ ddlmZ dd	lmZ dd
lmZ ddlmZmZ ddlmZ ddlmZ ddlmZ ddlmZ ddlm Z  ddl!m"Z"m#Z# ddl$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.m/Z/m0Z0 ddl1m2Z2 ddl3m4Z4m5Z5 dZ6d Z7d Z8d Z9d;dZ: G d d e!          Z;e%j<        j=         G d" d#e>                      Z?d$ Z@e?A                    d%&           G d' d(e?                      ZB G d) d%eB          ZC G d* d+e?          ZDe?A                                 G d, d-eD                      ZEe?A                                 G d. d/eD                      ZFe?A                                 G d0 d1e?                      Z*d2 ZGe?A                                 G d3 d4e?                      ZHe?A                    d5&           G d6 d7e?                      ZIeIZJd8 ZKeKZLd<d:ZMeMZNdS )=zmComposing task work-flows.

.. seealso:

    You should import these from :mod:`celery` and not this module.
    N)ABCMetaabstractmethod)deque)MutableSequence)deepcopy)partial)reduce)
itemgetter)GeneratorType)fxrangereprcall)cached_property)uuid)barrier)current_app)CPendingDeprecationWarning)GroupResultallow_join_result)abstractChainMap)_regen)chunks)is_list
maybe_listregenseq_concat_itemseq_concat_seq)getitem_property)remove_repeating_from_tasktruncate)		Signaturechainxmapxstarmapr   groupchord	signaturemaybe_signaturec                 $   	 t          | j                  }|dk    r| j        d         n| S # t          $ rZ 	 | j                                        }|dk    rt	          | j                  d         n| cY S # t
          t          f$ r | cY cY S w xY ww xY w)zUnroll group with only one member.
    This allows treating a group of a single task as if it
    was a single task without pre-knowledge.   r   )lentasks	TypeError__length_hint__listAttributeError)r&   sizes     ?/var/www/html/env/lib/python3.11/site-packages/celery/canvas.pymaybe_unroll_groupr4   *   s    

65; "&u{1~~5  @ @ @	@;..00D ,01994$$Q''%??? 	* 	 	 	LLLLL	@s,   + 
BA3"B3BB
BBc                 $    t          | d|           S )Nname)getattrtasks    r3   task_name_fromr:   <   s    4&&&    c                 $     | j         ||fi | | S )zWhen stamping a sequence of tasks created by a generator,
    we use this function to stamp each task in the generator
    without exhausting it.)stamp)r9   visitorappend_stampsheaderss       r3   _stamp_regen_taskrA   @   s%    
 DJw11111Kr;   Tc                    |sdS |                                  D ]	\  }}||v rt          |t                    rt          | |         ||                    <t          |t          t
          t          f          r
|r|gn|| |<   t          ||         t                    r=t          | |         t                    r"| |                             ||                    |rG| |         g | |<   nt          | |                   | |<   | |         	                    ||                    |                                 D ]\  }}|| vr|| |<   dS )a  Merge two dictionaries recursively into the first one.

    Example:
    >>> d1 = {'dict': {'a': 1}, 'list': [1, 2], 'tuple': (1, 2)}
    >>> d2 = {'dict': {'b': 2}, 'list': [3, 4], 'set': {'a', 'b'}}
    >>> _merge_dictionaries(d1, d2)

    d1 will be modified to: {
        'dict': {'a': 1, 'b': 2},
        'list': [1, 2, 3, 4],
        'tuple': (1, 2),
        'set': {'a', 'b'}
    }

    Arguments:
        d1 (dict): Dictionary to merge into.
        d2 (dict): Dictionary to merge from.
        aggregate_duplicates (bool):
            If True, aggregate duplicated items (by key) into a list of all values in d1 in the same key.
            If False, duplicate keys will be taken from d2 and override the value in d1.
    N)
items
isinstancedict_merge_dictionariesintfloatstrr0   extendappend)d1d2aggregate_duplicateskeyvalues        r3   rF   rF   I   sZ   ,  hhjj , ,
U"99%&& ,#BsGRW5555ec5#%677 I)=Hugg5BsGbgt,, ,BsGT1J1J ,sGNN2c7++++) ,#w"$3"&r#w--3sGNN2c7+++hhjj  
Ub==BsG r;   c                       e Zd ZdZdefdZddZdefdZddZe	defd            Z
defd	Zdd
ZdefdZdefdZdefdZdS )StampingVisitorzStamping API.  A class that provides a stamping API possibility for
    canvas primitives. If you want to implement stamping behavior for
    a canvas primitive override method that represents it.
    returnc                     i S )a  Method that is called on group stamping start.

         Arguments:
             group (group): Group that is stamped.
             headers (Dict): Partial headers that could be merged with existing headers.
         Returns:
             Dict: headers to update.
          selfr&   r@   s      r3   on_group_startzStampingVisitor.on_group_start|   	     	r;   Nc                     dS )zMethod that is called on group stamping end.

         Arguments:
             group (group): Group that is stamped.
             headers (Dict): Partial headers that could be merged with existing headers.
         NrU   rV   s      r3   on_group_endzStampingVisitor.on_group_end   	     	r;   c                     i S )a  Method that is called on chain stamping start.

         Arguments:
             chain (chain): Chain that is stamped.
             headers (Dict): Partial headers that could be merged with existing headers.
         Returns:
             Dict: headers to update.
         rU   rW   r#   r@   s      r3   on_chain_startzStampingVisitor.on_chain_start   rY   r;   c                     dS )zMethod that is called on chain stamping end.

         Arguments:
             chain (chain): Chain that is stamped.
             headers (Dict): Partial headers that could be merged with existing headers.
         NrU   r^   s      r3   on_chain_endzStampingVisitor.on_chain_end   r\   r;   c                     dS )a  Method that is called on signature stamping.

         Arguments:
             sig (Signature): Signature that is stamped.
             headers (Dict): Partial headers that could be merged with existing headers.
         Returns:
             Dict: headers to update.
         NrU   )rW   sigr@   s      r3   on_signaturezStampingVisitor.on_signature   s      r;   c                     t          |j        t                    st          |j                  |_         | j        |j        fi |S )u  Method that is called on сhord header stamping start.

         Arguments:
             sig (chord): chord that is stamped.
             headers (Dict): Partial headers that could be merged with existing headers.
         Returns:
             Dict: headers to update.
         )rD   r-   r&   rX   rW   rc   headers      r3   on_chord_header_startz%StampingVisitor.on_chord_header_start   sF     #)U++ 	)ci((CI"t"3977777r;   c                 ,     | j         |j        fi | dS )u   Method that is called on сhord header stamping end.

           Arguments:
               sig (chord): chord that is stamped.
               headers (Dict): Partial headers that could be merged with existing headers.
        N)r[   r-   rf   s      r3   on_chord_header_endz#StampingVisitor.on_chord_header_end   s'     	#)..v.....r;   c                     i S )a  Method that is called on chord body stamping.

         Arguments:
             sig (chord): chord that is stamped.
             headers (Dict): Partial headers that could be merged with existing headers.
         Returns:
             Dict: headers to update.
        rU   rf   s      r3   on_chord_bodyzStampingVisitor.on_chord_body   rY   r;   c                     i S )a  Method that is called on callback stamping.

         Arguments:
             callback (Signature): callback that is stamped.
             headers (Dict): Partial headers that could be merged with existing headers.
         Returns:
             Dict: headers to update.
         rU   )rW   callbackrg   s      r3   on_callbackzStampingVisitor.on_callback   rY   r;   c                     i S )a  Method that is called on errback stamping.

         Arguments:
             errback (Signature): errback that is stamped.
             headers (Dict): Partial headers that could be merged with existing headers.
         Returns:
             Dict: headers to update.
         rU   )rW   errbackrg   s      r3   
on_errbackzStampingVisitor.on_errback   rY   r;   )rS   N)__name__
__module____qualname____doc__rE   rX   r[   r_   ra   r   rd   rh   rj   rl   ro   rr   rU   r;   r3   rR   rR   v   s#        
	$ 	 	 	 	   	$ 	 	 	 	    d    ^8d 8 8 8 8/ / / /	d 	 	 	 		 	 	 	 		t 	 	 	 	 	 	r;   rR   )	metaclassc                       e Zd ZdZi ZdxZZddhZed?d            Z	ed?d            Z
	 	 	 d@ fd	Zd	 Zd
 ZdAdZdBdZdCdZdAdZeZ	 	 dDdZeZdBdZd?dZd ZdEdZdFdZdGdZd Zd Zd Zd Zd Zd Z d Z!d Z"d Z#d  Z$d! Z%d" Z&d# Z'd$ Z(d% Z)d& Z* fd'Z+e,d(             Z-e.d)             Z/e.d*             Z0e.d+             Z1e.d,             Z2 e3d-d.          Z4 e3d/d0          Z5 e3d1d2          Z6 e3d3d4          Z7 e3d5d6          Z8 e3d7d8          Z9 e3d9d:          Z: e3d;d<          Z; e3d=d>          Z< xZ=S )Hr"   a/  Task Signature.

    Class that wraps the arguments and execution options
    for a single task invocation.

    Used as the parts in a :class:`group` and other constructs,
    or to pass tasks around as callbacks while being compatible
    with serializers with a strict type subset.

    Signatures can also be created from tasks:

    - Using the ``.signature()`` method that has the same signature
      as ``Task.apply_async``:

        .. code-block:: pycon

            >>> add.signature(args=(1,), kwargs={'kw': 2}, options={})

    - or the ``.s()`` shortcut that works for star arguments:

        .. code-block:: pycon

            >>> add.s(1, kw=2)

    - the ``.s()`` shortcut does not allow you to specify execution options
      but there's a chaining `.set` method that returns the signature:

        .. code-block:: pycon

            >>> add.s(2, 2).set(countdown=10).set(expires=30).delay()

    Note:
        You should use :func:`~celery.signature` to create new signatures.
        The ``Signature`` class is the type returned by that function and
        should be used for ``isinstance`` checks for signatures.

    See Also:
        :ref:`guide-canvas` for the complete guide.

    Arguments:
        task (Union[Type[celery.app.task.Task], str]): Either a task
            class/instance, or the name of a task.
        args (Tuple): Positional arguments to apply.
        kwargs (Dict): Keyword arguments to apply.
        options (Dict): Additional options to :meth:`Task.apply_async`.

    Note:
        If the first argument is a :class:`dict`, the other
        arguments will be ignored and the values in the dict will be used
        instead::

            >>> s = signature('tasks.add', args=(2, 2))
            >>> signature(s)
            {'task': 'tasks.add', args=(2, 2), kwargs={}, options={}}
    Ngroup_idstamped_headersc                       fd}|S )zRegister a new type of signature.
        Used as a class decorator, for example:
        >>> @Signature.register_type()
        >>> class mysig(Signature):
        >>>     pass
        c                 *    | j         p| j        <   | S N)TYPESrs   )subclassclsr6   s    r3   _innerz'Signature.register_type.<locals>._inner/  s    3;CId/h/0Or;   rU   )r   r6   r   s   `` r3   register_typezSignature.register_type'  s)    	 	 	 	 	 	 r;   c                     |                     d          }|r(| j        |         }|| ur|                    ||          S t          ||          S )zCreate a new signature from a dict.
        Subclasses can override this method to customize how are
        they created from a dict.
        subtask_typeapp)getr~   	from_dictr"   )r   dr   typ
target_clss        r3   r   zSignature.from_dict5  s_     eeN## 	83J$$!++A3+777$$$$r;   Fc	           
      T   || _         t          |t                    r#t                                          |           d S 	 |j        }
|| _        n# t          $ r |}
Y nw xY wt                                          |
t          |pd          |pi t          |pi fi |	||           d S )NrU   r9   argskwargsoptionsr   	immutable)	_apprD   rE   super__init__r6   _typer1   tuple)rW   r9   r   r   r   typer   r   r   ex	task_name	__class__s              r3   r   zSignature.__init__B  s     	dD!! 	GGT"""""" I	 "

 " ! ! ! 			!
 GGU4:2%6%6|W]11b11)#      s   A A A c                 R    |                      ||d          \  }}} | j        |i |S )z0Call the task directly (in the current process).N)_merger   )rW   partial_argspartial_kwargsr   r   _s         r3   __call__zSignature.__call__Z  s4    ++lNDIIfaty$)&)))r;   c                 .    |                      ||          S )z5Shortcut to :meth:`apply_async` using star arguments.apply_async)rW   r   r   s      r3   delayzSignature.delay_  s    n===r;   c                     |r|nd}|r|ni }d |                                 D             }|                     |||          \  }}} | j        j        ||fi |S )zCall task locally.

        Same as :meth:`apply_async` but executed the task inline instead
        of sending a task message.
        rU   c                     i | ]
\  }}|||S r}   rU   .0kvs      r3   
<dictcomp>z#Signature.apply.<locals>.<dictcomp>l      EEEDAqq}1a}}}r;   )rC   r   r   apply)rW   r   r   r   s       r3   r   zSignature.applyc  su     #tt!)rEEGMMOOEEE $D&' B BfgtytV77w777r;   c                    |r|nd}|r|ni }d |                                 D             }	 | j        }n# t          $ r Y dS w xY w|s|s|r|                     |||          \  }}}n| j        | j        | j        }}} |||fi |S )a  Apply this task asynchronously.

        Arguments:
            args (Tuple): Partial args to be prepended to the existing args.
            kwargs (Dict): Partial kwargs to be merged with existing kwargs.
            options (Dict): Partial options to be merged
                with existing options.

        Returns:
            ~@AsyncResult: promise of future evaluation.

        See also:
            :meth:`~@Task.apply_async` and the :ref:`guide-calling` guide.
        rU   c                     i | ]
\  }}|||S r}   rU   r   s      r3   r   z)Signature.apply_async.<locals>.<dictcomp>  r   r;   N)rC   _apply_async
IndexErrorr   r   r   r   )rW   r   r   
route_namer   _applys         r3   r   zSignature.apply_asyncq  s     #tt!)rEEGMMOOEEE	&FF 	 	 	FF	  	I6 	IW 	I$(KKfg$F$F!D&''$(It{DL'&D vdF..g...s   4 
AAc                     |r|nd}|r|ni }|{ j         d j        v r@ j                             t           j                            dg                               i  j         fd|                                D             }n j        } j        r|s j         j        |fS |r$t          |          t           j                  z   n j        |rt           j        fi |n j        |fS )aG  Merge partial args/kwargs/options with existing ones.

        If the signature is immutable and ``force`` is False, the existing
        args/kwargs will be returned as-is and only the options will be merged.

        Stamped headers are considered immutable and will not be merged regardless.

        Arguments:
            args (Tuple): Partial args to be prepended to the existing args.
            kwargs (Dict): Partial kwargs to be merged with existing kwargs.
            options (Dict): Partial options to be merged with existing options.
            force (bool): If True, the args/kwargs will be merged even if the signature is
                immutable. The stamped headers are not affected by this option and will not
                be merged regardless.

        Returns:
            Tuple: (args, kwargs, options)
        rU   Nrz   c                 6    i | ]\  }}|vs	|j         v||S rU   )r   )r   r   r   immutable_optionsrW   s      r3   r   z$Signature._merge.<locals>.<dictcomp>  sA     . . .A---$,1F1F 11F1F1Fr;   )_IMMUTABLE_OPTIONSr   unionsetr   rC   r   r   r   r   rE   )rW   r   r   r   forcenew_optionsr   s   `     @r3   r   zSignature._merge  s:   & #tt!)r
 !% 7 DL00$($;$A$A#dlFVFVWhjlFmFmBnBn$o$o!T\  . . . . .!(. . . KK
 ,K> 	9% 	9It{K8826EdeDI....DI/5FT[++F+++4; 	r;   c           	      F   |r|nd}|r|ni }|s|s|r|                      |||          \  }}}n| j        | j        | j        }}}t                              | j        t          |          |t          |          | j	        | j
        d| j                  }| j        |_        |S )a7  Create a copy of this signature.

        Arguments:
            args (Tuple): Partial args to be prepended to the existing args.
            kwargs (Dict): Partial kwargs to be merged with existing kwargs.
            options (Dict): Partial options to be merged with
                existing options.
        rU   r   r   )r   r   r   r   r"   r   r9   r   r   r   r   r   r   )rW   r   r   optsr(   s        r3   clonezSignature.clone  s     #tt!)r 	F6 	FT 	F!%T64!@!@D&$$!%DK$&D''16t394<TNN9=9J6:n)F )F -1I ( 7 7	 *	r;   c                    | j         }	 |d         }n%# t          $ r |pt                      x}|d<   Y nw xY w|r||d<   |r||d<   d|vr| j        j        |d<   |r	d|vr||d<   |r||d<   |||d<   |                     |          S )	aC  Finalize the signature by adding a concrete task id.

        The task won't be called and you shouldn't call the signature
        twice after freezing it as that'll result in two task messages
        using the same task id.

        The arguments are used to override the signature's headers during
        freezing.

        Arguments:
            _id (str): Task id to use if it didn't already have one.
                New UUID is generated if not provided.
            group_id (str): Group id to use if it didn't already have one.
            chord (Signature): Chord body when freezing a chord header.
            root_id (str): Root id to use.
            parent_id (str): Parent id to use.
            group_index (int): Group index to use.

        Returns:
            ~@AsyncResult: promise of future evaluation.
        task_idroot_id	parent_idreply_tory   r'   Ngroup_index)r   KeyErrorr   r   
thread_oidAsyncResult)	rW   _idry   r'   r   r   r   r   tids	            r3   freezezSignature.freeze  s    2 |	2y/CC 	2 	2 	2$'M4661C$y///	2  	&%DO 	* )DT!!#x2D 	(
$..'D 	"!DM""-D $$$    44c                 d    |                                  }|||_        |||_        |||_        |S )zReplace the args, kwargs or options set for this signature.

        These are only replaced if the argument for the section is
        not :const:`None`.
        )r   r   r   r   )rW   r   r   r   r(   s        r3   replacezSignature.replace  s@     JJLL	!IN%I 'Ir;   c                 h    ||                      |           | j                            |           | S )u   Set arbitrary execution options (same as ``.options.update(…)``).

        Returns:
            Signature: This is a chaining method call
                (i.e., it will return ``self``).
        )set_immutabler   update)rW   r   r   s      r3   r   zSignature.set  s9      y)))G$$$r;   c                     || _         d S r}   r   )rW   r   s     r3   r   zSignature.set_immutable&  s    "r;   Tc                                                     dvr$t                                                    d<   |c|pi }d|vr$t          |                                          |d<   t          ||           t          t	          d                             d<   |rt	                              dg                     }|                    | j                            dg                      t          |          d<   fd| j                                        D             }t          ||           t          t	          d                             d<   S )a  Collect all stamps from visitor, headers and self,
        and return an idempotent dictionary of stamps.

        .. versionadded:: 5.3

        Arguments:
            visitor_headers (Dict): Stamps from a visitor method.
            append_stamps (bool):
                If True, duplicated stamps will be appended to a list.
                If False, duplicated stamps will be replaced by the last stamp.
            self_headers (bool):
                If True, stamps from self.options will be added.
                If False, stamps from self.options will be ignored.
            headers (Dict): Stamps that should be added to headers.

        Returns:
            Dict: Merged stamps.
        rz   N)rN   c                 0    i | ]\  }}|d          v ||S )rz   rU   )r   r   r   r@   s      r3   r   z,Signature._stamp_headers.<locals>.<dictcomp>]  s/    iiiAgVgNhIhIh1IhIhIhr;   )	copyr0   keysrF   r   r   r   r   rC   )rW   visitor_headersr?   self_headersr@   rz   redacted_optionss       `  r3   _stamp_headerszSignature._stamp_headers)  st   > ,,..G++)-gllnn)=)=G%& &-3O 7759/:N:N:P:P5Q5Q 12  }]]]])-c':K2L.M.M)N)NG%&  		O!'++.?"D"DEEO""4<#3#34Er#J#JKKK)-o)>)>G%&iiii1C1C1E1Eiii  )9P]^^^^)-c':K2L.M.M)N)NG%&r;   c                      | j         ||fi | |                                }d}| |j        | fi |pi } | j        ||fi |} | j        di |S )a  Stamp this signature with additional custom headers.
        Using a visitor will pass on responsibility for the stamping
        to the visitor.

        .. versionadded:: 5.3

        Arguments:
            visitor (StampingVisitor): Visitor API object.
            append_stamps (bool):
                If True, duplicated stamps will be appended to a list.
                If False, duplicated stamps will be replaced by the last stamp.
            headers (Dict): Stamps that should be added to headers.
        NrU   )stamp_linksr   rd   r   r   )rW   r>   r?   r@   r   s        r3   r=   zSignature.stampe  s     	-;;7;;;,,..2g24CC7CCIrO%$%o}PPPPtx""'"""r;   c                 F   |                                 }d}t          |          }t          | j                            d                    pg D ]L}t          || j                  }d}| |j        |fi |pi } | j        d|||d|} |j	        ||fi | Mt          |          }t          | j                            d                    pg D ]L}t          || j                  }d}| |j
        |fi |pi } | j        d|||d|} |j	        ||fi | MdS )a  Stamp this signature links (callbacks and errbacks).
        Using a visitor will pass on responsibility for the stamping
        to the visitor.

        Arguments:
            visitor (StampingVisitor): Visitor API object.
            append_stamps (bool):
                If True, duplicated stamps will be appended to a list.
                If False, duplicated stamps will be replaced by the last stamp.
            headers (Dict): Stamps that should be added to headers.
        Flinkr   N)r   r?   r   
link_errorrU   )r   r   r   r   r   r)   r   ro   r   r=   rr   )rW   r>   r?   r@   non_visitor_headersr   r   r   s           r3   r   zSignature.stamp_links{  s    &llnn
  .//t|//7788>B 	: 	:D"4TX666D"O""5'"5d"F"Fg"F"F"L")d)  /+)  	 G DJw999999 .//t|//==>>D" 	: 	:D"4TX666D"O""4'"4T"E"EW"E"E"K)d)  /+)  	 G DJw999999	: 	:r;   c                     | j                             |g           }t          |t                    s|gx}| j         |<   |S )a  Gets the value at the given self.options[key] as a list.

        If the value is not a list, it will be converted to one and saved in self.options.
        If the key does not exist, an empty list will be set and returned instead.

        Arguments:
            key (str): The key to get the value for.

        Returns:
            List: The value at the given key as a list or an empty list if the key does not exist.
        )r   
setdefaultrD   r   )rW   rO   rC   s      r3   _with_list_optionzSignature._with_list_option  sE     ''R00%11 	0)./EDL%r;   c                 b    |                      |          }||vr|                    |           |S )zEAppends the given value to the list at the given key in self.options.)r   rK   rW   rO   rP   rC   s       r3   append_to_list_optionzSignature.append_to_list_option  s7    &&s++LLr;   c                 t    |                      |          }|                    t          |                     dS )zExtends the list at the given key in self.options with the given value.

        If the value is not a list, it will be converted to one.
        N)r   rJ   r   r   s       r3   extend_list_optionzSignature.extend_list_option  s7    
 &&s++Z&&'''''r;   c                 .    |                      d|          S )zAdd callback task to be applied if this task succeeds.

        Returns:
            Signature: the argument passed, for chaining
                or use with :func:`~functools.reduce`.
        r   r   rW   rn   s     r3   r   zSignature.link  s     ))&(;;;r;   c                 .    |                      d|          S )zAdd callback task to be applied on error in task execution.

        Returns:
            Signature: the argument passed, for chaining
                or use with :func:`~functools.reduce`.
        r   r   rW   rq   s     r3   r   zSignature.link_error  s     )),@@@r;   c                 0    |                      |           | S )a2  Version of :meth:`link_error` that supports chaining.

        on_error chains the original signature, not the errback so::

            >>> add.s(2, 2).on_error(errback.s()).delay()

        calls the ``add`` task, not the ``errback`` task, but the
        reverse is true for :meth:`link_error`.
        )r   r   s     r3   on_errorzSignature.on_error  s     	   r;   c                     t          t          j                            t          j        | ggd t	          | j                            d                    pg D                                           S )zhReturn a recursive list of dependencies.

        "unchain" if you will, but with links intact.
        c              3   >   K   | ]}|                                 V  d S r}   )flatten_links)r   r   s     r3   	<genexpr>z*Signature.flatten_links.<locals>.<genexpr>  sJ       E E !! E E E E E Er;   r   )r0   	itertoolsr#   from_iterabler   r   r   rW   s    r3   r   zSignature.flatten_links  s}    
 IO11)/VHE E#DL$4$4V$<$<==CE E E3
 3
     	r;   c                 v   t          |t                    r7t          t          | f|                                          | j                  S t          |t
                    r&t          |          }t          | || j                  S t          |t                    rt          | || j                  S t          S )zChaining operator.

        Example:
            >>> add.s(2, 2) | add.s(4) | add.s(8)

        Returns:
            chain: Constructs a :class:`~celery.canvas.chain` of the given signatures.
        r   )
rD   _chainr   unchain_tasksr   r&   r4   r   r"   NotImplementedrW   others     r3   __or__zSignature.__or__  s     eV$$ 	6.,,..0 059Y@ @ @ @u%% 	6&u--E$484444y)) 	6$495555r;   c                 ,    |                      |          S r}   )r   r   s     r3   __ior__zSignature.__ior__  s     {{5!!!r;   c           
         | j         }|j        }| j                            d          pt	                      }|                    d           5 }|j                            ||          }|j        	                    |d | j
        dd|i||j                   |                    |          cd d d            S # 1 swxY w Y   d S )Nr   r9   )
connectionrU   )r   r   r   r   r   producer_or_acquirebackendon_task_callcontrolelectionr   r  r   )rW   r   r   r   producerpropss         r3   r  zSignature.election  s   yhly))3TVV$$T** 	)hL--h<<EK  f!+!A!AC!A5!A!A,4,? ! A A A ##C((	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	)s   A B99B= B=c                 j    |                      ||i d          \  }}}t          | d         ||          S )aA  Return a string representation of the signature.

        Merges the given arguments with the signature's arguments
        only for the purpose of generating the string representation.
        The signature itself is not modified.

        Example:
            >>> add.s(2, 2).reprcall()
            'add(2, 2)'
        T)r   r9   )r   r   )rW   r   r   r   s       r3   r   zSignature.reprcall  s9     ++dFBd+CCfaVdF333r;   c                 D    | |t          |           <   t          |           S r}   )idrE   )rW   memos     r3   __deepcopy__zSignature.__deepcopy__-  s    RXXDzzr;   c                 N    |                                                                  S r}   )r   r   r   s    r3   
__invert__zSignature.__invert__1  s     !!%%'''r;   c                 0    t           t          |           ffS r}   )r(   rE   r   s    r3   
__reduce__zSignature.__reduce__4  s     4::-''r;   c                      t          |           S r}   )rE   r   s    r3   __json__zSignature.__json__9  s    Dzzr;   c                 *    |                                  S r}   )r   r   s    r3   __repr__zSignature.__repr__<  s    }}r;   c              #      K   t                                                      D ]4\  }}t          |t                    r|                                n||fV  5d S r}   )r   rC   rD   bytesdecode)rW   r   r   r   s      r3   rC   zSignature.items?  s_      GGMMOO 	? 	?DAq *1e 4 4;!((***!Q>>>>>	? 	?r;   c                     | j         S r}   r8   r   s    r3   r6   zSignature.nameC  s     yr;   c                 @    | j         p| j        j        | d                  S Nr9   )r   r   r-   r   s    r3   r   zSignature.typeH  s    z9TX^DL99r;   c                     | j         pt          S r}   )r   r   r   s    r3   r   zSignature.appL  s    y'K'r;   c                 T    	 | j         j        S # t          $ r | j        j        cY S w xY wr}   )r   r   r   r   r   s    r3   r   zSignature.AsyncResultP  s>    	(9(( 	( 	( 	(8''''	(s    ''c                 |    	 | j         j        S # t          $ r# t          | j        j        | d                   cY S w xY wr  )r   r   r   _partialr   	send_taskr   s    r3   r   zSignature._apply_asyncW  sL    	>9(( 	> 	> 	>DH.V=====	>s    *;;zoptions.task_idz	Task UUIDzoptions.parent_idzTask parent UUID.zoptions.root_idzTask root UUID.r9   zName of task.r   zPositional arguments to task.r   zKeyword arguments to task.r   zTask execution options.r   zType of signaturer   z+Flag set if no longer accepts new argumentsr}   )NNNNNNFNNN)NNN)NNNFNNNNNN)NFTNF)F)>rs   rt   ru   rv   r~   r   r   r   classmethodr   r   r   r   r   r   r   r   r   r   r   _freezer   r   r   r   r=   r   r   r   r   r   r   r   r   r   r   r  r   r  r  r  r  r  rC   propertyr6   r   r   r   r   r   r   r  r   r   r9   r   r   r   r   r   __classcell__r   s   @r3   r"   r"      s       6 6p ED5 %&78   [ 
% 
% 
% [
% CG9>     0* * *
> > >8 8 8 8/ / / /B( ( ( (T   4 G489=/% /% /% /%b G   
 
 
 
# # #: : : :x# # # #,/: /: /: /:b  "  ( ( (< < <A A A  	 	 	  ." " "
) 
) 
)4 4 4  ( ( (( ( (
    ? ? ? ? ?   X : : _: ( ( _( ( ( _( > > _> 
	+[	9	9B  !46IJJI02CDDGFO44DF$CDDDh(DEEFy*CDDG##N4GHHL  BD DIIIIIr;   r"   c                     |rt          dd i|           S d| vrt          d|i|           S |t          d| d         |z   i|           S d S )Nr#   r   )r   r-   use_links      r3   _prepare_chain_from_optionsr+  j  sw    R  !$111			%('222		 ''"2U":;! ! 	! 
	r;   r#   )r6   c            
            e Zd Z edd          Zedd            Z fdZd Zd Z	 fdZ
d	 Zdd
Z	 	 	 	 ddZ	 	 ddZddZddddddddej        df
dZddZed             Zd Z xZS )r   kwargs.taskszTasks in chain.Nc                     |d         d         }|r=t          |t                    rt          |          x}|d         d<   fd|D             } | |fdi|d         S )Nr   r-   c                 2    g | ]}t          |           S r   r)   r   r9   r   s     r3   
<listcomp>z$_chain.from_dict.<locals>.<listcomp>  s&    FFF_Ts333FFFr;   r   r   )rD   r   r0   )r   r   r   r-   s     ` r3   r   z_chain.from_dict  s    (G$ 	G%'' ;/3E{{:(G,FFFFFFFEs522c2Qy\222r;   c                    t          |          dk    r*t          |d                   rt          |d                   n|} t                      j        ddd|ifi | |                    dd           | _        d| _        d | _        d S )Nr+   r   zcelery.chainrU   r-   r*  r#   )	r,   r   r   r   r   pop	_use_linkr   _frozenrW   r-   r   r   s      r3   r   z_chain.__init__  s    $'JJ!OOa8I8IOuQx 	gu-= 	 	 	 	 	 Z66#r;   c                 @    | j         r|                     ||          S d S r}   )r-   r   )rW   r   r   s      r3   r   z_chain.__call__  s,    : 	2##D&111	2 	2r;   c                    t          |t                    rt          |          }|                                 }|s|S t          |d         t                    r:|d         j        |z  |d         _         t          |           || j                  S  t          |           t          ||          | j	                  S t          |t                    rQ t          |           t          |                                 |                                          | j	                  S t          |t                    r| j        r`t          | j        d         t                    r@|                                 }t	          |j        d         || j	                  |j        d<   |S | j        r[t          | j        d         t                    r;|                                 }|j        d         j        |z  |j        d         _        |S  t          |           t          |                                 |          | j	                  S t          S )Nr   )rD   r&   r4   r   r'   bodyr   r   r   r   r   r   r"   r-   r   r   )rW   r   r-   rc   s       r3   r   z_chain.__or__  s2   eU## &	"&u--E&&((E %)U++ 7!&r%!7b	!tDzz%TX66664::ou #'9. . . .v&& 	" 4::n""$$e&9&9&;&;= =BF)M M M My)) 	"z AjB?? Ajjll %IbM5di!9 !9 !9	"
 	A
4:b>5 A A 	Ajjll%(Yr]%7%%?	""
 "tDzz/&&((%#1 #16:iA A A A "!r;   c                      t            t                      j        |i |} fd|j        d         D             |j        d<   |S )Nc                 6    g | ]} |j         d           S )T)r   r   )r   )r   rc   rW   to_signatures     r3   r3  z _chain.clone.<locals>.<listcomp>  s<     %
 %
 %
 L$)4888%
 %
 %
r;   r-   )r)   r   r   r   )rW   r   r   r(   r?  r   s   `   @r3   r   z_chain.clone  si    &!EGGM42622	%
 %
 %
 %
 %
 '0%
 %
 %
	! r;   c                 B   d | j         D             }t          | j                            d                    pg D ]}|d                             |           t          | j                            d                    pg D ]}|D ]}|                    |           |S )a  Return a list of tasks in the chain.

        The tasks list would be cloned from the chain's tasks.
        All of the chain callbacks would be added to the last task in the (cloned) chain.
        All of the tasks would be linked to the same error callback
        as the chain itself, to ensure that the correct error callback is called
        if any of the (cloned) tasks of the chain fail.
        c                 6    g | ]}|                                 S rU   r   r   ts     r3   r3  z(_chain.unchain_tasks.<locals>.<listcomp>  s     ///q///r;   r   r;  r   )r-   r   r   r   r   r   )rW   r-   rc   r9   s       r3   r   z_chain.unchain_tasks  s     0/DJ///dl..v6677=2 	  	 C"INN3dl..|<<==C 	% 	%C % %$$$$%r;   c           	          |r|nd}|r|ng }| j         }|j        j        r5t                      5   | j        ||fi |cd d d            S # 1 swxY w Y    | j        ||fd|i|rt          | j        fi |n| j        S )NrU   r   )r   conftask_always_eagerr   r   runrE   r   )rW   r   r   r   r   s        r3   r   z_chain.apply_async  s   #tt!)rh8% 	;"$$ ; ;!tz$::'::; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;txf I I# I-4FD)))))$,I I 	Is   A

AAc                    |r|nd}|r|ng }|p| j         }| j        }||j        j        dk    rd}|r+| j        s$t          |          t          | j                  z   n| j        }|                     ||| j        |
|||||||          \  }}|r\|r|d         	                    d|           |
                                }t          |||          } |j        di |}|s|S |d         S dS )zExecutes the chain.

        Responsible for executing the chain in the correct order.
        In a case of a chain of a single task, the task is executed directly
        and the result is returned for that task specifically.
        rU   Nr+   T)r   r   r   )r   r6  rF  task_protocolr   r   r   prepare_stepsr-   r   r5  r+  r   )rW   r   r   ry   r'   r   r   r   	publisherr  r   r   r   r   r   r*  r-   results_from_prepare
first_taskresult_from_applys                       r3   rH  z
_chain.run  sF    #tt!)roTX> 6! ; ;H> $>deDI....48I 	 '+&8&8&$*gy*cXu+ '9 '
 '
##   	/ :a++FD999J1'5(KKG 6
 6 A A A A  /((+A..	/ 	/r;   c                     |                      | j        | j        | j        ||d | j        |||d|          x\  }}| _        |d         S )NF)r   r   r   )rK  r   r   r-   r   r7  )	rW   r   ry   r'   r   r   r   r   resultss	            r3   r   z_chain.freeze>  sZ     %)$6$6It{DJDHc8U%# %7 %
 %
 	

7T\
 qzr;   Fc                     d }| |j         | fi |pi } | j        ||fi |} | j        |fi | | j        D ]} |j        ||fi | | |j        | fi | d S d S r}   )r_   r   r   r-   r=   ra   )rW   r>   r?   r@   r   r9   s         r3   r=   z_chain.stampI  s    4g4TEEWEEKO%$%o}PPPP,,G,,,J 	: 	:DDJw999999 G 1111111 r;   Tc                 \   |p| j         }| j        }||j        j        dk    rd}t	          |          }|j        }|j        }d}d}g g }}d}|r[ |            }| | }}t          |t          j	                  s |||          }t          |t                    rt          |          }|r.|r|                    ||          }n@|                                }n+|r)t          |          t          |j                  z   |_        t          |t                    r ||j                   t          |t                    rh|rf|                                 |                                 	 t#          |||j        ||          }n## t&          $ r t#          ||||          }Y nw xY w|r|                    |||	|
|          }n|                    |	          }|dz  }|r'|r|                    |           |r|j        s||_        |r't/          |          D ]}|                    |           |                    |           |                    |           ||}}t          |t"                    r2|j                                         |}|j        r|j        }|j        |}|[||fS )
a  Prepare the chain for execution.

        To execute a chain, we first need to unpack it correctly.
        During the unpacking, we might encounter other chains, groups, or chords
        which we need to unpack as well.

        For example:
        chain(signature1, chain(signature2, signature3)) --> Upgrades to chain(signature1, signature2, signature3)
        chain(group(signature1, signature2), signature3) --> Upgrades to chord([signature1, signature2], signature3)

        The responsibility of this method is to ensure that the chain is
        correctly unpacked, and then the correct callbacks are set up along the way.

        Arguments:
            args (Tuple): Partial args to be prepended to the existing args.
            kwargs (Dict): Partial kwargs to be merged with existing kwargs.
            tasks (List[Signature]): The tasks of the chain.
            root_id (str): The id of the root task.
            parent_id (str): The id of the parent task.
            link_error (Union[List[Signature], Signature]): The error callback.
                will be set for all tasks in the chain.
            app (Celery): The Celery app instance.
            last_task_id (str): The id of the last task in the chain.
            group_id (str): The id of the group that the chain is a part of.
            chord_body (Signature): The body of the chord, used to synchronize with the chain's
                last task and the chord's body when used together.
            clone (bool): Whether to clone the chain's tasks before modifying them.
            from_dict (Callable): A function that takes a dict and returns a Signature.

        Returns:
            Tuple[List[Signature], List[AsyncResult]]: The frozen tasks of the chain, and the async results
        Nr+   Tr   r   )r<  r   r   r   )r<  r   r   )r   ry   r'   r   r   )r   r6  rF  rJ  r   r5  rJ   rD   r   CallableSignaturer&   r4   r   r   r   r   r-   r'   r   r1   r   r   parentr   r   rK   r  ensure_chords_allowed)rW   r   r   r-   r   r   r   r   last_task_idry   
chord_bodyr   r   r   r*  steps	steps_popsteps_extend	prev_taskprev_resrQ  ir9   is_first_taskis_last_taskresrq   nodes                               r3   rK  z_chain.prepare_stepsV  sL   J oTX > 6! ; ;He I	|	Rw  \	 9;;D /4)U<MdH$>?? 0 y3///$&& 0 *$//  ;  (::dF33DD::<<DD ;!$KK%	*:*::	$'' TZ((( $&& 9  		 9 ( 0's  DD &   
 !9 'S  DDD  3 kk #hj + "   kk'k22FA * )IIi((( *HO *&)HO -)*55 - -GOOG,,,,LLNN3"&xI$&&  11333 k ';D k 'y  \	 z g~s   +F F%$F%c           
          |r|nd}|r|ni }d ||fc}\  }}| j         D ]X} |                    ||          j        |o|                                ffi t	          | j        fi |}||dc|_        }\  }}Y|S )NrU   r!  )r-   r   r   r   rE   r   rV  )	rW   r   r   r   lastfargsfkwargsr9   rb  s	            r3   r   z_chain.apply  s    #tt!)r!%f~ugJ 	I 	ID2$**UG,,2&$((**I I*.t|*G*Gw*G*GI IC15sL.CJ.uggr;   c                 n    | j         }|$	 | j        d         j         }n# t          $ r Y nw xY w|pt          S Nr   )r   r-   LookupErrorr   rW   r   s     r3   r   z
_chain.app  sN    i;jm(   !k!    
++c                     | j         s)dt          |           j         dt          |           ddS t	          | j         d         d         d                    d | j         D                                 S )	N<@z#xz: empty>r   r9   z | c              3   4   K   | ]}t          |          V  d S r}   )reprrC  s     r3   r   z"_chain.__repr__.<locals>.<genexpr>  s(      331tAww333333r;   )r-   r   rs   r  r    joinr   s    r3   r  z_chain.__repr__  sx    z 	CBtDzz*BBRXXBBBBB)JqM&!JJ33
333335 5 	5r;   r}   r!  )NNNNNNNNNNNNNr"  r#  )rs   rt   ru   r   r-   r$  r   r   r   r   r   r   r   rH  r   r=   r"   rK  r   r&  r   r  r'  r(  s   @r3   r   r     s       ^->??E3 3 3 [3    2 2 2'" '" '"R      &
I 
I 
I 
I @D@D=A,/ ,/ ,/ ,/` 599=	 	 	 	2 2 2 2 #dt#'$4 I,?"&	Z Z Z Zx    " " X"5 5 5 5 5 5 5r;   r   c                   "     e Zd ZdZ fdZ xZS )r#   a  Chain tasks together.

    Each tasks follows one another,
    by being applied as a callback of the previous task.

    Note:
        If called with only one argument, then that argument must
        be an iterable of tasks to chain: this allows us
        to use generator expressions.

    Example:
        This is effectively :math:`((2 + 2) + 4)`:

        .. code-block:: pycon

            >>> res = chain(add.s(2, 2), add.s(4))()
            >>> res.get()
            8

        Calling a chain will return the result of the last task in the chain.
        You can get to the other tasks by following the ``result.parent``'s:

        .. code-block:: pycon

            >>> res.parent.get()
            4

        Using a generator expression:

        .. code-block:: pycon

            >>> lazy_chain = chain(add.s(i) for i in range(10))
            >>> res = lazy_chain(3)

    Arguments:
        *tasks (Signature): List of task signatures to chain.
            If only one argument is passed and that argument is
            an iterable, then that'll be used as the list of signatures
            to chain instead.  This means that you can use a generator
            expression.

    Returns:
        ~celery.chain: A lazy signature that can be called to apply the first
            task in the chain.  When that task succeeds the next task in the
            chain is applied, and so on.
    c                    |s|rt          |          dk    st          |d                   rt          |          dk    r|d         n|}t          t          j        |t                                }| t          k    rEt          |t
                    r0t          ||           s  t                      j	        | |j
        fi |S |S  t                      j	        | g|R i |S )Nr+   r   )r,   r   r	   operatoror_r   r#   rD   r   __new__r-   )r   r-   r   new_instancer   s       r3   rw  zchain.__new__?  s     	$% 	$5zzQ'%("3"3$'JJ!OOa  &hlE688DD%<<J|V$D$D<ZXdfiMjMj<*577?30BMMfMMM##uwws5U555f555r;   )rs   rt   ru   rv   rw  r'  r(  s   @r3   r#   r#     sC        - -`6 6 6 6 6 6 6 6 6r;   c                   Z     e Zd ZdZ edd          Zedd            Z fdZddZ	 xZ
S )	_basemapNr9   itc                 T     | |                      |d                   d|i|d         S Nr   r   r   _unpack_argsr   r   r   s      r3   r   z_basemap.from_dictQ  2    sC$$Qx[11KsKa	lKKKr;   c                 n     t                      j        | j        d|t          |          dfddi| d S )NrU   r9   r{  r   T)r   r   
_task_namer   )rW   r9   r{  r   r   s       r3   r   z_basemap.__init__U  sT    ""&eBii88	 	DH	LS	 	 	 	 	r;   c           	          |r|nd}|r|ni }|                      | j                  \  }} | j        j        d|t	          |          dfdt          | j                            d                    i|S )NrU   r  r   r9   )r  r   r   r   r0   r:   r   )rW   r   r   r   r9   r{  s         r3   r   z_basemap.apply_asyncZ  s    #tt!)r$$T[11b$ty$T"XX..
 
%dkoof&=&=>>
BF
 
 	
r;   r}   r!  )rs   rt   ru   r  r
   r  r$  r   r   r   r'  r(  s   @r3   rz  rz  M  s        J:fd++LL L L [L    

 
 
 
 
 
 
 
r;   rz  c                       e Zd ZdZdZd ZdS )r$   zMap operation for tasks.

    Note:
        Tasks executed sequentially in process, this is not a
        parallel operation like :class:`group`.
    z
celery.mapc                     |                      | j                  \  }}d|j         dt          t	          |          d           dS )N[z(x) for x in d   ]r  r   r9   r!   rq  rW   r9   r{  s      r3   r  zxmap.__repr__p  sF    $$T[11bE49EE8DHHc+B+BEEEEr;   Nrs   rt   ru   rv   r  r  rU   r;   r3   r$   r$   e  s9          JF F F F Fr;   r$   c                       e Zd ZdZdZd ZdS )r%   z.Map operation for tasks, using star arguments.zcelery.starmapc                     |                      | j                  \  }}d|j         dt          t	          |          d           dS )Nr  z(*x) for x in r  r  r  r  s      r3   r  zxstarmap.__repr__{  sF    $$T[11bF49FFHT"XXs,C,CFFFFr;   Nr  rU   r;   r3   r%   r%   u  s3        88!JG G G G Gr;   r%   c                        e Zd ZdZ eddd          Zedd            Z fdZd Z	dd	Z
d
 Zedd            Z xZS )r   z)Partition of tasks into chunks of size n.r9   r{  nNc                 T     | |                      |d                   d|i|d         S r}  r~  r  s      r3   r   zchunks.from_dict  r  r;   c                 f     t                      j        dd|t          |          |dfddi| d S )Nzcelery.chunksrU   )r9   r{  r  r   T)r   r   r   )rW   r9   r{  r  r   r   s        r3   r   zchunks.__init__  sT    ""&eBiia@@	 	#'	+2	 	 	 	 	r;   c                      | j         di |S )NrU   r   )rW   r   s     r3   r   zchunks.__call__  s    t**'***r;   c           	          |r|nd}|r|ni } |                                  j        ||fdt          | j                            d                    i|S )NrU   r   r9   )r&   r   r:   r   r   )rW   r   r   r   s       r3   r   zchunks.apply_async  sm    #tt!)r'tzz||'&
 
%dkoof&=&=>>
BF
 
 	
r;   c                                             j                  \  }}t           fdt          t	          |          |          D              j                  S )Nc              3   F   K   | ]}t          |j                   V  dS r   N)r%   r   )r   partrW   r9   s     r3   r   zchunks.group.<locals>.<genexpr>  sH       8 8 tTty999 8 8 8 8 8 8r;   r   )r  r   r&   _chunksiterr   )rW   r{  r  r9   s   `  @r3   r&   zchunks.group  sv    ''44b! 8 8 8 8 8")$r((A"6"68 8 8$ $ $ 	$r;   c                 0      | ||||                      S )Nr   rU   )r   r9   r{  r  r   s        r3   apply_chunkszchunks.apply_chunks  s#    (ss4QC(((***r;   r}   r!  )rs   rt   ru   rv   r
   r  r$  r   r   r   r   r&   r  r'  r(  s   @r3   r   r     s        33:fdC00LL L L [L    + + +
 
 
 
$ $ $ + + + [+ + + + +r;   r   c                 V   t          | t                    rt          |           } t          | t          t          f          r| j        } n]t          | t          j                  r| g} n?t          | t                    rt          fd| D                       } nfd| D             } | S )Nr   c              3   :   K   | ]}t          |           V  dS r  r(   r   rD  r   s     r3   r   z_maybe_group.<locals>.<genexpr>  s0      ??A)A3///??????r;   c                 2    g | ]}t          |           S r0  r  r  s     r3   r3  z _maybe_group.<locals>.<listcomp>  s&    :::qYqc***:::r;   )
rD   rE   r(   r&   r   r-   r   rU  r   r   )r-   r   s    `r3   _maybe_groupr    s    % *%S)))%%)) ;	E85	6	6 ;e]++ 	;?????????EE::::E:::ELr;   c                       e Zd ZdZ edd          Zedd            Z fdZd Z	d Z
dd
Z	 	 d dZd!dZd Zd"dZd Zd Zej        ej        eefdZ	 	 	 d#dZd Z	 	 d$dZ	 	 d$dZeZd Zd Zd Zd Z d Z!e"d             Z# xZ$S )%r&   aq  Creates a group of tasks to be executed in parallel.

    A group is lazy so you must call it to take action and evaluate
    the group.

    Note:
        If only one argument is passed, and that argument is an iterable
        then that'll be used as the list of tasks instead: this
        allows us to use ``group`` with generator expressions.

    Example:
        >>> lazy_group = group([add.s(2, 2), add.s(4, 4)])
        >>> promise = lazy_group()  # <-- evaluate: returns lazy result.
        >>> promise.get()  # <-- will wait for the task to return
        [4, 8]

    Arguments:
        *tasks (List[Signature]): A list of signatures that this group will
            call. If there's only one argument, and that argument is an
            iterable, then that'll define the list of signatures instead.
        **options (Any): Execution options applied to all tasks
            in the group.

    Returns:
        ~celery.group: signature that when called will then call all of the
            tasks in the group (and return a :class:`GroupResult` instance
            that can be used to inspect the state of the group).
    r-  zTasks in group.Nc                     |d         d         } t          |          fd|D                       x|d         d<   } | |fdi|d         S )a  Create a group signature from a dictionary that represents a group.

        Example:
            >>> group_dict = {
                "task": "celery.group",
                "args": [],
                "kwargs": {
                    "tasks": [
                        {
                            "task": "add",
                            "args": [
                                1,
                                2
                            ],
                            "kwargs": {},
                            "options": {},
                            "subtask_type": None,
                            "immutable": False
                        },
                        {
                            "task": "add",
                            "args": [
                                3,
                                4
                            ],
                            "kwargs": {},
                            "options": {},
                            "subtask_type": None,
                            "immutable": False
                        }
                    ]
                },
                "options": {},
                "subtask_type": "group",
                "immutable": False
            }
            >>> group_sig = group.from_dict(group_dict)

        Iterates over the given tasks in the dictionary and convert them to signatures.
        Tasks needs to be defined in d['kwargs']['tasks'] as a sequence
        of tasks.

        The tasks themselves can be dictionaries or signatures (or both).
        r   r-   c              3   :   K   | ]}t          |           V  dS r  r1  r2  s     r3   r   z"group.from_dict.<locals>.<genexpr>  sI       @
 @
/3ODc***@
 @
 @
 @
 @
 @
r;   r   r   )r   )r   r   r   
orig_tasksrebuilt_taskss     `  r3   r   zgroup.from_dict  s    d x[)
/?tJ/?/? @
 @
 @
 @
7A@
 @
 @
 0
 0
 	
(G} s=::c:Qy\:::r;   c                 f   t          |          dk    rw|d         }t          |t                    r|j        }t          |t          j                  r|                                g}t          |t                    st          |          } t                      j
        ddd|ifi | d| _        d S )Nr+   r   zcelery.grouprU   r-   r&   )r,   rD   r&   r-   r   rU  r   r   r   r   r   r   r8  s      r3   r   zgroup.__init__  s    u::??!HE%'' $%!;<< (eV,, % egu-= 	 	 	 	 	#r;   c                      | j         |fi |S r}   r   )rW   r   r   s      r3   r   zgroup.__call__  s    t88888r;   c                 0    t          | || j                  S )N)r<  r   )r'   r   r   s     r3   r   zgroup.__or__"  s    T495555r;         ?c                     t          |||d          }| j        D ]%}|                    t          |                     &| S )NT)
repeatlast)	countdown)r   r-   r   next)rW   startstopstepr{  r9   s         r3   skewz
group.skew&  sK    UD$4888J 	) 	)DHHtBxxH((((r;   Tc                    |r|nd}|t          d          |t          d          | j        }|j        j        r | j        ||fi |S | j        s|                                 S |                     |          \  }}	}
|                     | j        g |	|
|          }t                      }t           | j        ||||f||d|          }| j                            |	||          }|                                 t          |          dk    r#t          |d         t                    r|d         }|j        }|r|r|                    |           |S )NrU   z%Cannot add link to group: use a chordz5Cannot add link to group: do that on individual tasksr   r   )ready_barrierr+   r   )r.   r   rF  rG  r   r-   r   _freeze_gid	_preparedr   r0   _apply_tasksr   finalizer,   rD   current_worker_task	add_trail)rW   r   r   add_to_parentr  r   r   r   r   ry   r   r-   prQ  resultparent_tasks                   r3   r   zgroup.apply_async-  s   #ttCDDD!GI I Ih8% 	74:dF66g666z 	!;;== %)%5%5g%>%>"7tz2x#FFII(t(#q N.26N NELN N O O%%hq%II	

 v;;!
6!9k B BAYF- 	*[ 	*!!&)))r;   c                    rndrni | j         }| j        s|                                 S |                               \  }}|                     | j        g |||          }|                    |fd|D                       S )NrU   c                 8    g | ]\  }}} |j         dd S )r  rU   )r   )r   rc   r   r   r   r   s      r3   r3  zgroup.apply.<locals>.<listcomp>Y  sE     *
 *
 *
?HsAqICI:4::'::*
 *
 *
r;   )r   r-   r   r  r  r   )rW   r   r   r   r   ry   r   r-   s    ```    r3   r   zgroup.applyQ  s    #tt!)rhz 	!;;== %)%5%5g%>%>"7tz2x#FFx *
 *
 *
 *
 *
 *
LQ*
 *
 *
   	r;   c                 D    | j         D ]}|                    |           d S r}   r-   r   rW   r   r9   s      r3   r   zgroup.set_immutable]  s4    J 	* 	*Dy))))	* 	*r;   Fc                    d }| |j         | fi |pi } | j        ||fi |} | j        ||fi | t          | j        t
                    r.| j                            t          t          f||d|           ntg }| j        D ]<}t          || j
                  } |j        ||fi | |                    |           =t          | j        t                    r|| j        d d <   n|| _        | |j        | fi | d S d S )Nr>   r?   r   )rX   r   r   rD   r-   r   mapr  rA   r)   r   r=   rK   r   r[   )rW   r>   r?   r@   r   	new_tasksr9   s          r3   r=   zgroup.stampa  sb   4g4TEEWEEKO%$%o}PPPP-;;7;;;dj&)) 	'JNN8$5owVcoognooppppI
 ' '&t:::
7M==W===  &&&&$*o66 ' )
111&
 G 1111111 r;   c                     |                                                     d          }| j        d                             |          S )NTr   r   )r   r   r-   r   rW   rc   s     r3   r   z
group.linkx  s9     iikkooo--z!}!!#&&&r;   c                 D    t          fd| j        D                       S )Nc              3   j   K   | ]-}|                                         d                     V  .dS )Tr   N)r   r   )r   
child_taskrc   s     r3   r   z#group.link_error.<locals>.<genexpr>  s?      cc*Z**399t9+D+DEEccccccr;   )r   r-   r  s    `r3   r   zgroup.link_error  s,     ccccX\Xbccccccr;   c
              #     K   t          |          D ]\  }
} |||          r|                                }n |||          } ||t                    r'|                    |j        ||||          }|E d{V  k|r(|j        s! |	|           |	|j                  z   |_        ||                    |||
          |fV  dS )a  Recursively unroll the group into a generator of its tasks.

        This is used by :meth:`apply_async` and :meth:`apply` to
        unroll the group into a list of tasks that can be evaluated.

        Note:
            This does not change the group itself, it only returns
            a generator of the tasks that the group would evaluate to.

        Arguments:
            tasks (list): List of tasks in the group (may contain nested groups).
            partial_args (list): List of arguments to be prepended to
                the arguments of each task.
            group_id (str): The group id of the group.
            root_id (str): The root id of the group.
            app (Celery): The Celery app instance.
            CallableSignature (class): The signature class of the group's tasks.
            from_dict (fun): Function to create a signature from a dict.
            isinstance (fun): Function to check if an object is an instance
                of a class.
            tuple (class): A tuple-like class.

        Returns:
            generator: A generator for the unrolled group tasks.
                The generator yields tuples of the form ``(task, AsyncResult, group_id)``.
        r   N)ry   r   r   )	enumerater   r&   r  r-   r   r   r   )rW   r-   r   ry   r   r   rU  r   rD   r   indexr9   unrolls                r3   r  zgroup._prepared  s     < %U++ 	i 	iKE4z$ 122 0 zz|| !y3///z$&& 	iJh  "!!!!!!!! G G %l 3 3eeDI6F6F FDIDKK7X]K^^`hhhhhh#	i 	ir;   c	              +     K   |p| j         }|                    |          5 }d}
t          j        |          \  }}t	          |d           t	          |d          }t          |          D ]\  }}|\  }}}||n|j                            d          }|
t          	                    |          z  }
|||j
                            ||
            |j        d	|d|||d|	 |r5|j        s.|j        s'|xj        dz  c_        |                    |d           t	          |d          }|V  	 ddd           dS # 1 swxY w Y   dS )
aU  Run all the tasks in the group.

        This is used by :meth:`apply_async` to run all the tasks in the group
        and return a generator of their results.

        Arguments:
            tasks (list): List of tasks in the group.
            producer (Producer): The producer to use to publish the tasks.
            app (Celery): The Celery app instance.
            p (barrier): Barrier object to synchronize the tasks results.
            args (list): List of arguments to be prepended to
                the arguments of each task.
            kwargs (dict): Dict of keyword arguments to be merged with
                the keyword arguments of each task.
            **options (dict): Options to be merged with the options of each task.

        Returns:
            generator: A generator for the AsyncResult of the tasks in the group.
        r   Nr'   F)r  r  r'   r   r   r+   T)weakrU   )r   r  r   teer  r  r   r   _chord_descendr  set_chord_sizer   	cancelledreadyr2   then)rW   r-   r  r   r  r  r'   r   r   r   
chord_sizetasks_shifted	next_task
task_indexcurrent_taskrc   rb  ry   	chord_objs                      r3   r  zgroup._apply_tasks  s     0 oTX$$X.. %	(
 J#,=#7#7 M5%%%]D11I,5e,<,<  (
L
 &2"S(%*%6EECKOOG<T<T	 fooc222
(Y->K..xDDD +&/d6+ +")+ + +  +Q[ + +FFaKFFHHQTH*** 55					7%	 %	 %	 %	 %	 %	 %	 %	 %	 %	 %	 %	 %	 %	 %	 %	 %	 %	s   DD<<E E c                      i  j          fd|                                D             }|                    dt                                x|d<   }|||                    d          fS )z:Freeze the group id by the existing task_id or a new UUID.c                 @    i | ]\  }}|j         vs	|j        v||S rU   )r   r   )r   r   r   rW   s      r3   r   z%group._freeze_gid.<locals>.<dictcomp>  sC     &
 &
 &
Q///1DL3H3H q3H3H3Hr;   r   ry   r   )r   rC   r5  r   r   )rW   r   ry   s   `  r3   r  zgroup._freeze_gid  s    T\  &
 &
 &
 &
$]]__&
 &
 &
 
 KK	466**	,
h'++i"8"888r;   c           	         | j         }	 |d         }n%# t          $ r |pt                      x}|d<   Y nw xY w|r||d<   |r||d<   |||d<   |                    d|          }|                    d|          }t	          | j        t                    rjt          j        | 	                    | j                            \  }	}
t          |                     |	||||                    }t          |
          | _        nVg }t          |                     |||||                    }t	          | j        t                    r|| j        dd<   n|| _        ||fS )a?  Freeze the tasks in the group.

        Note:
            If the group tasks are created from a generator, the tasks generator would
            not be exhausted, and the tasks would be frozen lazily.

        Returns:
            tuple: A tuple of the group id, and the AsyncResult of each of the group tasks.
        r   ry   r'   Nr   r   r   )r   r   r   r   rD   r-   r   r   r  _unroll_tasksr   _freeze_tasksr0   _freeze_unrollr   )rW   r   ry   r'   r   r   r   r   gidtasks1tasks2rQ  r  s                r3   _freeze_group_taskszgroup._freeze_group_tasks
  s    |	7y/CC 	7 	7 	7$,$66C$y///	7 	('D 	"!DM""-D//)W55OOK;;	dj&)) 	' ']4+=+=dj+I+IJJNFFD..vxQZ[[\\GvDJJI 4..8UGY   G $*o66 ' )
111&
G|r   c           
      R     | j         j        |                     ||||||           S )N)r   ry   r'   r   r   r   )r   r   r  )rW   r   ry   r'   r   r   r   s          r3   r   zgroup.freeze=  s;    #tx#T%=%=hI; &> &
 &
  	r;   c              #   Z   K   fdt          |          D             E d{V  dS )zKCreates a generator for the AsyncResult of each task in the tasks argument.c              3   R   K   | ]!\  }}|                     |           V  "dS )ry   r'   r   r   r   N)r   )r   r   r9   r'   ry   r   r   s      r3   r   z&group._freeze_tasks.<locals>.<genexpr>H  s^       ? ?
 *T KK&+(/*3,7	   9 9 ? ? ? ? ? ?r;   N)r  )rW   r-   ry   r'   r   r   s     ````r3   r  zgroup._freeze_tasksF  sv      ? ? ? ? ? ? ?
 .7u-=-=? ? ? 	? 	? 	? 	? 	? 	? 	? 	? 	?r;   c              #   4    K    fd|D             E d{V  dS )z?Creates a generator for the cloned tasks of the tasks argument.c              3   h   K   | ],}t          |j                                                   V  -dS r  )r)   r   r   r   r9   rW   s     r3   r   z&group._unroll_tasks.<locals>.<genexpr>R  s>      SSTODdi888>>@@SSSSSSr;   NrU   rW   r-   s   ` r3   r  zgroup._unroll_tasksO  s<       TSSSUSSSSSSSSSSSSr;   c              #     K   t          | j                  }d}|rt          |                                | j                                                  }t          |t                    r|                    |j                   n6|	                    |           |
                    |||||          V  |dz  }|dS dS )a  Generator for the frozen flattened group tasks.

        Creates a flattened list of the tasks in the group, and freezes
        each task in the group. Nested groups will be recursively flattened.

        Exhausting the generator will create a new list of the flattened
        tasks in the group and will return it in the new_tasks argument.

        Arguments:
            new_tasks (list): The list to append the flattened tasks to.
            group_id (str): The group_id to use for the tasks.
            chord (Chord): The chord to use for the tasks.
            root_id (str): The root_id to use for the tasks.
            parent_id (str): The parent_id to use for the tasks.

        Yields:
            AsyncResult: The frozen task.
        r   r   r  r+   N)r   r-   r)   popleftr   r   rD   r&   
extendleftrK   r   )	rW   r  ry   r'   r   r   stackr   r9   s	            r3   r  zgroup._freeze_unrollT  s      * dj!! 	!"5==??	BBBHHJJD$&& !  ,,,,  &&&kk8(-w,5.9 " ; ; ; ; ; q   	! 	! 	! 	! 	!r;   c                 h    | j         r*t          | j         d         d         d| j         d          S dS )Nr   r9   zgroup()zgroup(<empty>))r-   r    r   s    r3   r  zgroup.__repr__x  sD    : 	*-
1f%((((* * *  r;   c                 *    t          | j                  S r}   )r,   r-   r   s    r3   __len__zgroup.__len__  s    4:r;   c                 r    | j         }|$	 | j        d         j        }n# t          $ r Y nw xY w||nt          S ri  )r   r-   r   rj  r   rk  s     r3   r   z	group.app  sQ    i;jm'   oss;6rl  r}   )r  Nr  )NNTNNNr!  r#  )NNNNNNNr"  )%rs   rt   ru   rv   r   r-   r$  r   r   r   r   r  r   r   r   r=   r   r   r   rU  r"   rD   r   r  r  r  r  r   r%  r  r  r  r  r  r&  r   r'  r(  s   @r3   r&   r&     s'        : ^->??E5; 5; 5; [5;n$ $ $ $ $9 9 96 6 6    AE9=" " " "H
 
 
 
* * *2 2 2 2.	' 	' 	'd d d %-$>%/'u/i /i /i /ib >B/3'+> > > >@
9 
9 
9 BFFJ1 1 1 1f 599=    G? ? ?T T T
"! "! "!H        7 7 X7 7 7 7 7r;   r&   r'   c                   2    e Zd ZdZedd            Zedd            Z	 	 d  fd	ZddZ	 fdZ
	 	 d!d	Zd"dZ	 	 	 d#dZ	 	 d$dZed             Zd Z	 	 	 d%dZ fdZd Zd Zd Zd Zed             ZddZ edd          Z edd          Z xZS )&r  aL  Barrier synchronization primitive.

    A chord consists of a header and a body.

    The header is a group of tasks that must complete before the callback is
    called.  A chord is essentially a callback for a group of tasks.

    The body is applied with the return values of all the header
    tasks as a list.

    Example:

        The chord:

        .. code-block:: pycon

            >>> res = chord([add.s(2, 2), add.s(4, 4)])(sum_task.s())

        is effectively :math:`\Sigma ((2 + 2) + (4 + 4))`:

        .. code-block:: pycon

            >>> res.get()
            12
    Nc                 p    |                                 } | j        di |d         \  }|d<    | |d|i|S )a  Create a chord signature from a dictionary that represents a chord.

        Example:
            >>> chord_dict = {
                "task": "celery.chord",
                "args": [],
                "kwargs": {
                    "kwargs": {},
                    "header": [
                        {
                            "task": "add",
                            "args": [
                                1,
                                2
                            ],
                            "kwargs": {},
                            "options": {},
                            "subtask_type": None,
                            "immutable": False
                        },
                        {
                            "task": "add",
                            "args": [
                                3,
                                4
                            ],
                            "kwargs": {},
                            "options": {},
                            "subtask_type": None,
                            "immutable": False
                        }
                    ],
                    "body": {
                        "task": "xsum",
                        "args": [],
                        "kwargs": {},
                        "options": {},
                        "subtask_type": None,
                        "immutable": False
                    }
                },
                "options": {},
                "subtask_type": "chord",
                "immutable": False
            }
            >>> chord_sig = chord.from_dict(chord_dict)

        Iterates over the given tasks in the dictionary and convert them to signatures.
        Chord header needs to be defined in d['kwargs']['header'] as a sequence
        of tasks.
        Chord body needs to be defined in d['kwargs']['body'] as a single task.

        The tasks themselves can be dictionaries or signatures (or both).
        r   r   rU   )r   r  )r   r   r   r   r   s        r3   r   z_chord.from_dict  sS    p &&(("2#"2"G"GWX5F"G"GghsD-c-W---r;   c                     | |f|fS r}   rU   )rg   r<  r   s      r3   r  z_chord._unpack_args  s     ~v%%r;   celery.chordc           
          |r|nd}|r|ndi i} t                      j        ||i |t          ||          t          ||          dfd|i| d| _        d S )NrU   r   r   )rg   r<  r   r'   )r   r   r  r)   r   )	rW   rg   r<  r9   r   r   r   r   r   s	           r3   r   z_chord.__init__  s    #tt!5"~tBF Bl63.G.G"1$C"@"@"@B B B	 	GJ	NU	 	 	 $r;   c                 ,     | j         d|rd|ini fi |S )NrU   r<  r   )rW   r<  r   s      r3   r   z_chord.__call__  s,    td$BVTNNNNgNNNr;   c                    t          |t          t          f          s:t          |t                    r%|                                 }|j        |z  |_        |S t          |t                    rLt          |j                  dk    r4t          |          }|                                 }|j        |z  |_        |S t                      
                    |          S )Nr+   )rD   r&   r   r"   r   r<  r,   r-   r4   r   r   )rW   r   rc   r   s      r3   r   z_chord.__or__  s    55&/22 	)5),,	) **,,Cx%'CHJu%% 	)#ek*:*:a*?*? 'u--E**,,Cx%'CHJ77>>%(((r;   c                    t          | j        t                    s t          | j        | j                  | _        | j                            ||| j                  }| j        j        | _        d }| j        r{| j                            |||||          }|}	t                      }
|	rJ|	j        |
v rt          d          |
	                    |	j                   |	j
        ||	_
        n	|	j
        }	|	J|S )Nr   )r   r   r'   )r   r'   ry   r   zRecursive result parents)rD   r-   r&   r   r   r<  r  r   RuntimeErroraddrV  )rW   r   ry   r'   r   r   r   header_resultbody_resultrc  seens              r3   r   z_chord.freeze	  s    $*e,, 	9tztx888DJ
))	 * C C*- 9 	#)**WEH' + ) )K D55D #7d??&'ABBB!!!;&"/DK{  # r;   Fc                    | j         }t          |t                    r|j         }d }| |j        | fi |pi } | j        ||fi |} | j        ||fi | t          |t                    r)|                    t          t          f||d|           n(|
                                }|D ]} |j        ||fi | | |j        | fi | |<| j        7 |j        | fi |pi } | j        ||fi |} | j        j        ||fi | d S d S d S )Nr  )r-   rD   r&   rh   r   r   r   r  r  rA   r   r=   rj   r<  rl   )rW   r>   r?   r@   r-   r   stampsr9   s           r3   r=   z_chord.stamp*  s   
eU## 	 KE;g;DLLGLLRPRO%$%o}PPPP-;;7;;;eV$$ 	=IIh0j'Q^jjbijjkkkk\\^^F = =
7M<<V<<<<'G'8888849#83g3DDDGDDJO)d)/=TTGTTGDIOG]>>g>>>>> #8#8r;   c	           	      2   |r|nd}|r|ni }|r+| j         s$t          |          t          | j                  z   n| j        }|                    dd           p| j        d         }
t          | j        d         fi |} |
j        di |	}
|                     |
          }t          | j	        t                    r| j	                                        n;t          | j	        || j                            dt                                          }|j        j        r8t!                      5   | j        ||f|
|d|	cd d d            S # 1 swxY w Y   |	rt          | j        fi |	n| j        }|                    dd           }||} | j        ||
|f||d|S )NrU   r<  r   r   )r   r   )r<  r   )r   r   )r   r   r   r5  r   rE   r   _get_apprD   r-   r&   r   r   r   rF  rG  r   r   rH  )rW   r   r   r   r  rL  r  router
result_clsr   r<  r   r-   merged_optionsoption_task_ids                  r3   r   z_chord.apply_asyncD  s6    #tt!)r> $>deDI....48I 	zz&$''>4;v+>dk(+66v66tz$$G$$mmD!!'1$*e'D'D ^!!###DJC9I9I)UYU[U[9\9\]]] 	8% 	I"$$ I I!tz$ I'+WI I@GI II I I I I I I I I I I I I I I I ;BSdl66g666t|'++It<<?$G txtT\76\\^\\\s   'EE
E
Tc                 J   |r|nd}|r|ni }|| j         n|}t          | j        t                    r| j                                        nt          | j        | j                  }|                    |                    ||                              |          f          S )NrU   r   )	propagate)r   )r<  rD   r-   r&   r   r   r   r   )rW   r   r   r  r<  r   r-   s          r3   r   z_chord.apply^  s    #tt!)r Ltyyd'1$*e'D'D 6!!###DJDH555 	zz++dF++//)/DDF  
 
 	
r;   c                 ^    t          |t                    s/t          |t                    rt                              |          }t          |t                    r6t          |j        d|j                  }t           fd|D                       S t          |t                    r4|j        ddd         D ]!} 	                    |          }|dk    r|c S "dS t          |t                    r 	                    |j                  S t          |t                    rdS t          |          S )zCount the number of tasks in the given signature recursively.

        Descend into the signature object and return the amount of tasks it contains.
        r-   c              3   B   K   | ]}                     |          V  d S r}   r  )r   r9   r   s     r3   r   z"_chord._descend.<locals>.<genexpr>u  s/      ??ds||D))??????r;   r;  Nr   r+   )rD   r"   rE   r   r&   r7   r-   sumr   r  r'   r<  r,   )r   sig_objsubtasks	child_sig
child_sizes   `    r3   r  z_chord._descendi  s.    '9-- 	3*Wd2K2K 	3))'22Ggu%% 	w}gw}EEH????h??????(( 	$]26r62 & &	 \\)44
>>%%%% " 1'' 	<<---++ 	17||r;   c                 p     t           j        d j                  }t           fd|D                       S )z@Return the number of tasks in this chord's header (recursively).r-   c              3   B   K   | ]}                     |          V  d S r}   r  r  s     r3   r   z)_chord.__length_hint__.<locals>.<genexpr>  s/      9944==&&999999r;   )r7   r-   r  r  s   ` r3   r/   z_chord.__length_hint__  s;    
GTZ8899995999999r;   r+   c                    |p|                      |          }|j                            d          pt                      }|j                            d          }|rt	          | j        fi |n| j        }|r0|                    dd           |j                            |           |                    |	|          }|                    dd           |                    dd           |                    dd           |                    |||          }|j	        r1|j
                            |||||            |j        ||
fd|i|}n$|                    g             | j        j        | }||_        |S )	a  Execute the chord.

        Executing the chord means executing the header and sending the
        result to the body. In case of an empty header, the body is
        executed immediately.

        Arguments:
            header (group): The header to execute.
            body (Signature): The body to execute.
            partial_args (tuple): Arguments to pass to the header.
            app (Celery): The Celery app instance.
            interval (float): The interval between retries.
            countdown (int): The countdown between retries.
            max_retries (int): The maximum number of retries.
            task_id (str): The task id to use for the body.
            kwargs (dict): Keyword arguments to pass to the header.
            options (dict): Options to pass to the header.

        Returns:
            AsyncResult: The result of the body (with the result of the header in the parent of the body).
        r   r   NrT  r#   r'   )ry   r'   r   )intervalr  max_retries)r  r   r   r   rE   r5  r   r   r  r-   r  apply_chordr   r   r   r   rV  )rW   rg   r<  r   r   r   r  r!  eagerr   r   r   ry   r   bodyresheader_result_argsr  s                    r3   rH  z
_chord.run  s   0 (T]]4((>%%i00:DFF,""9--3:L$t|//w/// 	)KK	4(((L(((++gw+77 	GT"""GT"""It$$$#77QU_f7gg< 	FK##"!#' $    /F.|VaaXaY`aaMM
 JJrNNN0DH02DEM&r;   c                      t                      j        |i |}	 t          |j        d         d          |j        d<   n# t          t
          f$ r Y nw xY w|S )Nr<  TrB  )r   r   r)   r   r1   r   )rW   r   r   r(   r   s       r3   r   z_chord.clone  sy    !EGGM42622		'6 ((6 (6 (6IV$$) 	 	 	D	s   $A AAc                 :    | j                             |           |S )z(Links a callback to the chord body only.)r<  r   r   s     r3   r   z_chord.link  s    	x   r;   c                    | j         j        j        rCt          | j                  pg D ]+}|                    |                    d                     ,nt          j        dt                     | j
                            |           |S )at  Links an error callback to the chord body, and potentially the header as well.

        Note:
            The ``task_allow_error_cb_on_chord_header`` setting controls whether
            error callbacks are allowed on the header. If this setting is
            ``False`` (the current default), then the error callback will only be
            applied to the body.
        Tr   aK  task_allow_error_cb_on_chord_header=False is pending deprecation in a future release of Celery.
Please test the new behavior by setting task_allow_error_cb_on_chord_header to True and report any concerns you might have in our issue tracker before we make a final decision regarding how errbacks should behave when used with chords.)r   rF  #task_allow_error_cb_on_chord_headerr   r-   r   r   warningswarnr   r<  )rW   rq   r9   s      r3   r   z_chord.link_error  s     8=< 	"4:..4" ? ? = =>>>>? MN
 +   		W%%%r;   c                 D    | j         D ]}|                    |           dS )zSets the immutable flag on the chord header only.

        Note:
            Does not affect the chord body.

        Arguments:
            immutable (bool): The new mutability value for chord header.
        Nr  r  s      r3   r   z_chord.set_immutable  s6     J 	* 	*Dy))))	* 	*r;   c                    | j         rt          | j         t                    rt          | j         j        d         d         d                    | j         j        d                             | j                  t          | j         j        dd          | j                                      S dt          | j         d         | j                             | j                            z   S d| j        dS )	Nr   r9   z%({} | {!r})r+   r   %z<chord without body: >)	r<  rD   r   r    r-   formatr   r#   r   r   s    r3   r  z_chord.__repr__	  s    9 
	C$)V,, 1IOA&v."))	*33DJ??dioabb1tyAAA    3	&!49#5#5dj#A#AC C C C6tz6666r;   c                 6    |                      | j                  S r}   )r  r<  r   s    r3   r   z
_chord.app	  s    }}TY'''r;   c                     | j         }|?	 | j        j        }n# t          $ r
 | j        }Y nw xY w|r|d         j         }|	||j         }||nt          S ri  )r   r-   r1   r   )rW   r<  r   r-   s       r3   r  z_chord._get_app	  sw    i;#
(! # # #
# $Ahm{t/ioss;6s    ,,zkwargs.headerzTasks in chord header.zkwargs.bodyzBody task of chord.r}   r!  )Nr  NNNr"  r#  )NNNNNNNN)NNTN)NNr+   NFNN)rs   rt   ru   rv   r$  r   staticmethodr  r   r   r   r   r=   r   r   r  r/   rH  r   r   r   r   r  r   r   r  r   r-   r<  r'  r(  s   @r3   r  r    s        4 9. 9. 9. [9.v & & & \&
 0>-1$ $ $ $ $ $O O O O) ) ) ) )" 599=   B? ? ? ?4 ;?>B,0] ] ] ]4 '+#'	
 	
 	
 	
   [<: : :
 BF16!%; ; ; ;z      
  <
* 
* 
*7 7 7 ( ( _(7 7 7 7 _.FGGEM+@AADDDDDr;   r  c                 
   |                     d          }t          | t                    rJt          | t          j                  r|                                 S t                              | |          S t          | g|R i |S )zCreate new signature.

    - if the first argument is a signature already then it's cloned.
    - if the first argument is a dict, then a Signature version is returned.

    Returns:
        Signature: The resulting signature.
    r   r   )r   rD   rE   r   rU  r   r"   r   )variesr   r   r   s       r3   r(   r(   +	  s     **U

C&$ 4fh899 	"<<>>!""6s"333V-d---f---r;   Fc                     | ^t          | t          j                  r|r|                                 } n$t          | t                    rt          |           } ||| _        | S )a  Ensure obj is a signature, or None.

    Arguments:
        d (Optional[Union[abstract.CallableSignature, Mapping]]):
            Signature or dict-serialized signature.
        app (celery.Celery):
            App to bind signature to.
        clone (bool):
            If d' is already a signature, the signature
           will be cloned when this flag is enabled.

    Returns:
        Optional[abstract.CallableSignature]
    )rD   r   rU  r   rE   r(   r   )r   r   r   s      r3   r)   r)   ?	  sb     	}a344 	 GGII4   	!A?AFHr;   )Tr#  )Orv   r   ru  r*  abcr   r   collectionsr   collections.abcr   r   r   	functoolsr   r  r	   r
   typesr   kombu.utils.functionalr   r   kombu.utils.objectsr   kombu.utils.uuidr   viner   celery._stater   celery.exceptionsr   celery.resultr   r   celery.utilsr   celery.utils.collectionsr   celery.utils.functionalr   r   r  r   r   r   r   r   celery.utils.objectsr   celery.utils.textr    r!   __all__r4   r:   rA   rF   rR   rU  registerrE   r"   r+  r   r   r#   rz  r$   r%   r  r&   r  r'   r(   subtaskr)   maybe_subtaskrU   r;   r3   <module>rL     s;          ' ' ' ' ' ' ' '       + + + + + +       ) ) ) ) ) )                   4 4 4 4 4 4 4 4 / / / / / / ! ! ! ! ! !       % % % % % % 8 8 8 8 8 8 8 8 8 8 8 8 8 8 ! ! ! ! ! ! - - - - - - * * * * * * 5 5 5 5 5 5 _ _ _ _ _ _ _ _ _ _ _ _ _ _ 1 1 1 1 1 1 B B B B B B B B6 6 6$' ' '  * * * *Zn n n n n n n n nb 
$	D 	D 	D 	D 	D 	D 	D %$	DD6! 6! 6!r g&&g5 g5 g5 g5 g5Y g5 g5 '&g5T<6 <6 <6 <6 <6F <6 <6 <6~
 
 
 
 
y 
 
 
0 F F F F F8 F F F G G G G Gx G G G #+ #+ #+ #+ #+Y #+ #+ #+L    R7 R7 R7 R7 R7I R7 R7 R7j g&&UB UB UB UB UBY UB UB '&UBt 	. . ."    6  r;   