U
    Z+d-                     @   sN  d Z ddlZddlZddlmZ ddlmZ ddlmZm	Z	m
Z
 ddlmZmZmZmZmZmZmZ ddlmZ dZd	ZG d
d dZG dd deZdd Zdd Zdd Zdd Zd8ddZdd Zd9ddZdd Z dd Z!d d! Z"d"d# Z#G d$d% d%ee$Z%d:d'd(Z&d;d*d+Z'd,d- Z(d<d.d/Z)d0d1 Z*d2d3 Z+d4d5 Z,d6d7 Z-dS )=zFunctional-style utilities.    N)UserList)partial)isliceteezip_longest)LRUCache
dictfilteris_listlazymaybe_evaluate
maybe_listmemoize)promise)r   r	   r   r   mlazynoopfirstfirstmethodchunkspadlistmattrgetteruniqregenr   r
   r   head_from_funmaybefun_accepts_kwargsz4
def {fun_name}({fun_args}):
    return {fun_value}
c                   @   s   e Zd Zdd Zdd ZdS )DummyContextc                 C   s   | S N selfr   r   ;/tmp/pip-unpacked-wheel-ucduq0nd/celery/utils/functional.py	__enter__   s    zDummyContext.__enter__c                 G   s   d S r   r   )r   exc_infor   r   r    __exit__   s    zDummyContext.__exit__N)__name__
__module____qualname__r!   r#   r   r   r   r    r      s   r   c                       s(   e Zd ZdZdZdZ fddZ  ZS )r   zMemoized lazy evaluation.

    The function is only evaluated once, every subsequent access
    will return the same value.
    FNc                    s   | j st  | _d| _ | jS NT)	evaluatedsuperevaluate_valuer   	__class__r   r    r*   -   s    zmlazy.evaluate)r$   r%   r&   __doc__r(   r+   r*   __classcell__r   r   r,   r    r   "   s   r   c                  O   s   dS )zONo operation.

    Takes any arguments/keyword arguments and does nothing.
    Nr   )argskwargsr   r   r    r   4   s    r   c                 O   s   | S )z%Return the first positional argument.r   )argr0   r1   r   r   r    pass1;   s    r3   c                 c   s$   | D ]}t |tr| }|V  qd S r   )
isinstancer   )itvaluer   r   r    evaluate_promises@   s    
r7   c                    s   t  fddt|D dS )zReturn the first element in ``it`` that ``predicate`` accepts.

    If ``predicate`` is None it will return the first item that's not
    :const:`None`.
    c                 3   s,   | ]$} d k	r |rn|d k	r|V  qd S r   r   ).0v	predicater   r    	<genexpr>N   s
     
 zfirst.<locals>.<genexpr>N)nextr7   )r;   r5   r   r:   r    r   G   s    r   c                    s    fdd}|S )zMultiple dispatch.

    Return a function that with a list of instances,
    finds the first instance that gives a value for the given method.

    The list can also contain lazy instances
    (:class:`~kombu.utils.functional.lazy`.)
    c              	      sd   | D ]Z}z0t t| }r,|f||n|||}W n tk
rL   Y qX |d k	r|  S qd S r   )getattrr   AttributeError)r5   r0   r1   objmethZreplymethodon_callr   r    _matcher^   s    zfirstmethod.<locals>._matcherr   )rC   rD   rE   r   rB   r    r   T   s    
r   c                 c   s(   | D ]}|gt t| |d  V  qdS )as  Split an iterator into chunks with `n` elements each.

    Warning:
        ``it`` must be an actual iterator, if you pass this a
        concrete sequence will get you repeating elements.

        So ``chunks(iter(range(1000)), 10)`` is fine, but
        ``chunks(range(1000), 10)`` is not.

    Example:
        # n == 2
        >>> x = chunks(iter([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]), 2)
        >>> list(x)
        [[0, 1], [2, 3], [4, 5], [6, 7], [8, 9], [10]]

        # n == 3
        >>> x = chunks(iter([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]), 3)
        >>> list(x)
        [[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 10]]
       N)listr   )r5   nitemr   r   r    r   m   s    r   c                 C   s"   t | d| |g|t|    S )a  Pad list with default elements.

    Example:
        >>> first, last, city = padlist(['George', 'Costanza', 'NYC'], 3)
        ('George', 'Costanza', 'NYC')
        >>> first, last, city = padlist(['George', 'Costanza'], 3)
        ('George', 'Costanza', None)
        >>> first, last, city, planet = padlist(
        ...     ['George', 'Costanza', 'NYC'], 4, default='Earth',
        ... )
        ('George', 'Costanza', 'NYC', 'Earth')
    N)rG   len)	containersizedefaultr   r   r    r      s    r   c                     s    fddS )zGet attributes, ignoring attribute errors.

    Like :func:`operator.itemgetter` but return :const:`None` on missing
    attributes instead of raising :exc:`AttributeError`.
    c                    s    fddD S )Nc                    s   i | ]}|t  |d qS r   )r>   )r8   attrr@   r   r    
<dictcomp>   s      z1mattrgetter.<locals>.<lambda>.<locals>.<dictcomp>r   rO   attrsrO   r    <lambda>       zmattrgetter.<locals>.<lambda>r   rQ   r   rQ   r    r      s    r   c                    s   t    fdd| D S )z7Return all unique elements in ``it``, preserving order.c                 3   s$   | ]}| kr  |p|V  qd S r   )add)r8   r@   seenr   r    r<      s      zuniq.<locals>.<genexpr>)setr5   r   rV   r    r      s    r   c                 C   s    t | \}}t|d t||S )zYield pairs of (current, next) items in `it`.

    `next` is None if `current` is the last item.
    Example:
        >>> list(lookahead(x for x in range(6)))
        [(0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (5, None)]
    N)r   r=   r   )r5   abr   r   r    	lookahead   s    
r\   c                 C   s   t | ttfr| S t| S )zConvert iterator to an object that can be consumed multiple times.

    ``Regen`` takes any iterable, and if the object is an
    generator it will cache the evaluated list on first access,
    so that the generator can be "consumed" multiple times.
    )r4   rG   tuple_regenrY   r   r   r    r      s    r   c                   @   sZ   e Zd Zdd Zdd Zdd Zddd	Zd
d Zdd Zdd Z	e
dd Zdd ZdS )r^   c                 C   s   || _ g | _d| _d S )NF)
_regen__it_regen__consumed_regen__done)r   r5   r   r   r    __init__   s    z_regen.__init__c                 C   s   t | jffS r   )rG   datar   r   r   r    
__reduce__   s    z_regen.__reduce__c                 C   s
   | j  S r   )r_   __length_hint__r   r   r   r    re      s    z_regen.__length_hint__Nc                 c   s   | j s|d ks|dkrt| j}zt|}W n tk
rB   Y d S X | j| | j sz@zt|}| j| W n" tk
r   d| _ Y W qY nX W 5 |V  X |}|d k	rP|d8 }|dkrPqqPd S )Nr   TrF   )ra   iterr_   r=   StopIterationr`   append)r   limitr5   nowZnext_r   r   r    Z__lookahead_consume   s(    
z_regen.__lookahead_consumec                 c   s   | j E d H  |  E d H  d S r   )r`   _regen__lookahead_consumer   r   r   r    __iter__   s    z_regen.__iter__c                 C   s@   |dk r| j | S |t| j d }| j|dD ]}q0| j| S )Nr   rF   )ri   )rc   rJ   r`   rk   )r   indexZconsume_count_r   r   r    __getitem__   s    
z_regen.__getitem__c                 C   s>   t | jrdS ztt|  W n tk
r4   Y dS X dS d S )NTF)rJ   r`   r=   rf   rg   r   r   r   r    __bool__   s    
z_regen.__bool__c                 C   s    | j s| j| j d| _ | jS r'   )ra   r`   extendr_   r   r   r   r    rc     s    z_regen.datac                 C   s.   d | jjddd | jD | js(dndS )Nz<{}: [{}{}]>, c                 s   s   | ]}t |V  qd S r   )repr)r8   er   r   r    r<     s     z"_regen.__repr__.<locals>.<genexpr>z... )formatr-   r$   joinr`   ra   r   r   r   r    __repr__	  s
    z_regen.__repr__)N)r$   r%   r&   rb   rd   re   rk   rl   ro   rp   propertyrc   rx   r   r   r   r    r^      s   


r^   Tc           
      C   sP  | j rXt| j }|r&ttt| j n| j }| jd |  }tt| j| d  |}n| jg  }}| j}| j}| jrt	| j
t	| j  }|rdd t| j D }	qt| j }	n| j
g  }}	dtd d|ddd |D |rd| nd |s|	r|sdnd |r"d|nd ddd |	D |rFd| nd gS )	Nc                 S   s   g | ]\}}||fqS r   r   )r8   ikwr   r   r    
<listcomp>   s    z!_argsfromspec.<locals>.<listcomp>rr   c                 s   s    | ]\}}| d | V  qdS )=Nr   r8   kr9   r   r   r    r<   *  s     z _argsfromspec.<locals>.<genexpr>*c                 s   s"   | ]\}}| d | dV  qdS )z=""Nr   r~   r   r   r    r<   .  s     z**)defaultsrJ   rG   ranger0   zipvarargsvarkwkwonlydefaultsrX   
kwonlyargskeys	enumerateitemsrw   filter)
specZreplace_defaultssplitr   
positionaloptionalr   r   r   Zkwonlyargs_optionalr   r   r    _argsfromspec  s6    
r   Fc                 C   s   t | }t| d}| jjdk}t | }|sL|rL|sL|sL| jj| j }} n| j}tj|t	t 
| dd}|r~t|tjd d| ji}	t||	 |	| }
||
_|rt|
t S |
S )z1Generate signature function from actual function.__call__Zcython_function_or_methodrF   )Zfun_nameZfun_argsZ	fun_value)filer$   )inspect
isfunctionhasattrr-   r$   ismethodr   FUNHEAD_TEMPLATErv   r   getfullargspecprintsysstderrr%   exec_sourcer   object)funbounddebugZis_functionZis_callableZ	is_cythonZ	is_methodnameZ
definition	namespaceresultr   r   r    r   3  s*    




r   c                 C   s   t | }|jpt|j|kS r   )r   r   r   rJ   r0   )r   rH   Zargspecr   r   r    arity_greaterU  s    
r   c                 C   s2   t |}|jp0|jp0|r(t|j|kS | |jkS r   )r   r   r   r   rJ   r0   )r   r   positionr   r   r   r    fun_takes_argumentZ  s    
r   c                 C   s   t dd t| j D S )z<Return true if function accepts arbitrary keyword arguments.c                 s   s   | ]}|j |jkr|V  qd S r   )kindVAR_KEYWORD)r8   pr   r   r    r<   d  s   z%fun_accepts_kwargs.<locals>.<genexpr>)anyr   	signature
parametersvalues)r   r   r   r    r   b  s    r   c                 C   s   |dk	r| |S |S )z$Call typ on value if val is defined.Nr   )typvalr   r   r    r   j  s    r   c                 C   s   t | tr| |f S | |g S )zReturn copy of sequence seq with item added.

    Returns:
        Sequence: if seq is a tuple, the result will be a tuple,
           otherwise it depends on the implementation of ``__add__``.
    )r4   r]   )seqrI   r   r   r    seq_concat_itemo  s    r   c                 C   s@   t t| |gtd}t| |s&|| } t||s8||}| | S )a  Concatenate two sequences: ``a + b``.

    Returns:
        Sequence: The return value will depend on the largest sequence
            - if b is larger and is a tuple, the return value will be a tuple.
            - if a is larger and is a list, the return value will be a list,
    )key)typemaxrJ   r4   )rZ   r[   Zpreferr   r   r    seq_concat_seqy  s    	

r   )N)N)T)FF)N).r.   r   r   collectionsr   	functoolsr   	itertoolsr   r   r   Zkombu.utils.functionalr   r   r	   r
   r   r   r   Zviner   __all__r   r   r   r   r3   r7   r   r   r   r   r   r   r\   r   rG   r^   r   r   r   r   r   r   r   r   r   r   r   r    <module>   s>   $	

	S
"
"

