a
    %gh4                     @   s   d dl mZ d dlZddlmZmZmZmZ ddlm	Z	 ddl
mZmZ d dlZG dd deZd	d
 Zdd ZefddZdd Zdd ZG dd deZdd ZG dd deZdd Zdd ZdS )    )warnN   )orderingambiguitiessuper_signatureAmbiguityWarning)expand_tuples)Variadic
isvariadicc                   @   s   e Zd ZdZdS )MDNotImplementedErrorz+A NotImplementedError for multiple dispatchN)__name__
__module____qualname____doc__ r   r   k/mounts/lovelace/software/anaconda3/envs/metaDMG/lib/python3.9/site-packages/multipledispatch/dispatcher.pyr   	   s   r   c                 C   s   t t| j|t dS )aB  Raise warning when ambiguity is detected

    Parameters
    ----------
    dispatcher : Dispatcher
        The dispatcher on which the ambiguity was detected
    ambiguities : set
        Set of type signature pairs that are ambiguous within this dispatcher

    See Also:
        Dispatcher.add
        warning_text
    N)r   warning_textnamer   )
dispatcherr   r   r   r   ambiguity_warn   s    r   c                   C   s   t dt dS )z5Deprecated interface to temporarily disable ordering.z=halt_ordering is deprecated, you can safely remove this call.Nr   DeprecationWarningr   r   r   r   halt_ordering   s    r   c                 C   s   t dt dS )z4Deprecated interface to temporarily resume ordering.zrestart_ordering is deprecated, if you would like to eagerly orderthe dispatchers, you should call the ``reorder()`` method on each dispatcher.Nr   )on_ambiguityr   r   r   restart_ordering&   s    r   c                 c   sv   t |}t|}| D ]$}t||}|V  t|st|}qzt|}W n$ tyj   t|s`J dV  Y n0 dV  dS )aj  Check if a set of input types matches a variadic signature.

    Notes
    -----
    The algorithm is as follows:

    Initialize the current signature to the first in the sequence

    For each type in `types`:
        If the current signature is variadic
            If the type matches the signature
                yield True
            Else
                Try to get the next signature
                If no signatures are left we can't possibly have a match
                    so yield False
        Else
            yield True if the type matches the current signature
            Get the next signature
    TFN)iternext
issubclassr
   StopIteration)typesfull_signatureZsigitersigtypmatchesr   r   r   variadic_signature_matches_iter0   s    

r$   c                 C   s   |sJ t t| |S N)allr$   )r   r    r   r   r   variadic_signature_matchesZ   s    r'   c                   @   s   e Zd ZdZdZd*ddZdd Zedd	 Zed
d Z	dd Z
edd ZefddZdd Zdd ZeZdd Zdd Zdd Zdd Zdd Zed d! Zd"d# Zd$d% Zd&d' Zd(d) ZdS )+
DispatcheraV  Dispatch methods based on type signature

    Use ``dispatch`` to add implementations

    Examples
    --------

    >>> from multipledispatch import dispatch
    >>> @dispatch(int)
    ... def f(x):
    ...     return x + 1

    >>> @dispatch(float)
    ... def f(x):
    ...     return x - 1

    >>> f(3)
    4
    >>> f(3.0)
    2.0
    )r   r   funcs	_ordering_cachedocNc                 C   s"   | | _ | _i | _|| _i | _d S r%   )r   r   r)   r,   r+   )selfr   r,   r   r   r   __init__y   s    zDispatcher.__init__c                    s    fdd}|S )a  register dispatcher with new implementation

        >>> f = Dispatcher('f')
        >>> @f.register(int)
        ... def inc(x):
        ...     return x + 1

        >>> @f.register(float)
        ... def dec(x):
        ...     return x - 1

        >>> @f.register(list)
        ... @f.register(tuple)
        ... def reverse(x):
        ...     return x[::-1]

        >>> f(1)
        2

        >>> f(1.0)
        0.0

        >>> f([1, 2, 3])
        [3, 2, 1]
        c                    s   j | fi   | S r%   )add)funckwargsr-   r   r   r   _df   s    z Dispatcher.register.<locals>._dfr   )r-   r   r2   r3   r   r1   r   register   s    zDispatcher.registerc                 C   s"   t tdrt|}|j S d S )N	signature)hasattrinspectr5   
parametersvaluesclsr0   r!   r   r   r   get_func_params   s    

zDispatcher.get_func_paramsc                    sV   |  |}|rRtj  fdd|D }tdd |D }t fdd|D rR|S dS )z1get annotations of function positional parametersc                 3   s$   | ]}|j  j jfv r|V  qd S r%   )kindPOSITIONAL_ONLYPOSITIONAL_OR_KEYWORD.0param	Parameterr   r   	<genexpr>   s
   
z2Dispatcher.get_func_annotations.<locals>.<genexpr>c                 s   s   | ]}|j V  qd S r%   )
annotationr@   r   r   r   rE          c                 3   s   | ]}| j uV  qd S r%   )empty)rA   annrC   r   r   rE      rG   N)r<   r7   rD   tupler&   )r;   r0   paramsannotationsr   rC   r   get_func_annotations   s    

zDispatcher.get_func_annotationsc           	      C   s   |s|  |}|r|}tdd |D rFt|D ]}| || q0dS g }t|ddD ]\}}t|ttfsddd |D }t	d||| j
f t|tr|t|krt	d	t|dkrt	d
|t|d   qV|| qV|| jt|< | j  z| `W n ty   Y n0 dS )aK  Add new types/method pair to dispatcher

        >>> D = Dispatcher('add')
        >>> D.add((int, int), lambda x, y: x + y)
        >>> D.add((float, float), lambda x, y: x + y)

        >>> D(1, 2)
        3
        >>> D(1, 2.0)
        Traceback (most recent call last):
        ...
        NotImplementedError: Could not find signature for add: <int, float>

        When ``add`` detects a warning it calls the ``on_ambiguity`` callback
        with a dispatcher/itself, and a set of ambiguous type signature pairs
        as inputs.  See ``ambiguity_warn`` for an example.
        c                 s   s   | ]}t |tV  qd S r%   )
isinstancerJ   )rA   r"   r   r   r   rE      rG   z!Dispatcher.add.<locals>.<genexpr>Nr   )start, c                 s   s&   | ]}t |tr|jnt|V  qd S r%   )rN   typer   str)rA   cr   r   r   rE      s   zDTried to dispatch on non-type: %s
In signature: <%s>
In function: %sz+Variadic signature must be the last elementzVariadic signature must contain exactly one element. To use a variadic union type place the desired types inside of a tuple, e.g., [(int, str)]r   )rM   anyr   r/   	enumeraterN   rQ   listjoin	TypeErrorr   lenappendr	   r)   rJ   r+   clearr*   AttributeError)	r-   r5   r0   rL   ZtypsZnew_signatureindexr"   Zstr_sigr   r   r   r/      sD    




zDispatcher.addc                 C   s(   z| j W S  ty"   |   Y S 0 d S r%   )r*   r\   reorderr-   r   r   r   r      s    zDispatcher.orderingc                 C   s,   t | j | _}t| j}|r(|| | |S r%   )r   r)   r*   r   )r-   r   Zodambr   r   r   r^     s
    

zDispatcher.reorderc                 O   s   t dd |D }z| j| }W n@ ty`   | j| }|sRtd| jt|f || j|< Y n0 z||i |W S  ty   | j| }t	| |D ]0}z||i |W    Y S  ty   Y q0 qtd| jt|f Y n0 d S )Nc                 S   s   g | ]}t |qS r   rQ   rA   argr   r   r   
<listcomp>  rG   z'Dispatcher.__call__.<locals>.<listcomp>%Could not find signature for %s: <%s>zFMatching functions for %s: <%s> found, but none completed successfully)
rJ   r+   KeyErrordispatchNotImplementedErrorr   str_signaturer   dispatch_iterr   )r-   argsr2   r   r0   r)   r   r   r   __call__
  s:    

zDispatcher.__call__c                 C   s
   d| j  S )Nz<dispatched %s>r   r_   r   r   r   __str__+  s    zDispatcher.__str__c                 G   s>   || j v r| j | S zt| j| W S  ty8   Y dS 0 dS )aQ  Deterimine appropriate implementation for this type signature

        This method is internal.  Users should call this object as a function.
        Implementation resolution occurs within the ``__call__`` method.

        >>> from multipledispatch import dispatch
        >>> @dispatch(int)
        ... def inc(x):
        ...     return x + 1

        >>> implementation = inc.dispatch(int)
        >>> implementation(3)
        4

        >>> print(inc.dispatch(float))
        None

        See Also:
          ``multipledispatch.conflict`` - module to determine resolution order
        N)r)   r   rj   r   r-   r   r   r   r   rg   0  s    

zDispatcher.dispatchc                 g   st   t |}| jD ]`}t ||kr@ttt||r@| j| }|V  qt |rt|d rt||r| j| }|V  qd S )N)rY   r   r&   mapr   r)   r
   r'   )r-   r   nr5   resultr   r   r   rj   N  s    



zDispatcher.dispatch_iterc                 C   s   t dt | j| S )zDeterimine appropriate implementation for this type signature

        .. deprecated:: 0.4.4
            Use ``dispatch(*types)`` instead
        z-resolve() is deprecated, use dispatch(*types))r   r   rg   ro   r   r   r   resolveY  s    
zDispatcher.resolvec                 C   s   | j | jdS )Nr   r)   ru   r_   r   r   r   __getstate__c  s    zDispatcher.__getstate__c                 C   s,   |d | _ |d | _t| j| _t | _d S )Nr   r)   )r   r)   r   r*   dictr+   )r-   dr   r   r   __setstate__f  s    

zDispatcher.__setstate__c                 C   s   d| j  g}| jr|| j g }| jd d d D ]\}| j| }|jrdt| }|dt| d 7 }||j 7 }|| q2|t| q2|r|dd	|  d	|S )	NzMultiply dispatched method: %srp   zInputs: <%s>
-
zOther signatures:
    z
    

)
r   r,   rZ   r   r)   r   ri   rY   striprW   )r-   docsotherr!   r0   sr   r   r   r   l  s    
zDispatcher.__doc__c                 G   s   | j tt| jS r%   )rg   rq   rQ   r   )r-   rk   r   r   r   _help  s    zDispatcher._helpc                 O   s   t | j|  dS )z8Print docstring for the function corresponding to inputsN)printr   r-   rk   r2   r   r   r   help  s    zDispatcher.helpc                 G   s$   | j tt| }|stdt|S )NzNo function found)rg   rq   rQ   rX   source)r-   rk   r0   r   r   r   _source  s    zDispatcher._sourcec                 O   s   t | j|  dS )z:Print source code for the function corresponding to inputsN)r   r   r   r   r   r   r     s    zDispatcher.source)N)r   r   r   r   	__slots__r.   r4   classmethodr<   rM   r/   propertyr   r   r^   rl   rn   __repr__rg   rj   rt   rv   ry   r   r   r   r   r   r   r   r   r(   `   s4   
!

B
!

r(   c                 C   s    dt |  }|t |  }|S )Nz
File: %s

)r7   getsourcefile	getsource)r0   r   r   r   r   r     s    r   c                   @   s0   e Zd ZdZdZedd Zdd Zdd Zd	S )
MethodDispatcherzODispatch methods based on type signature

    See Also:
        Dispatcher
    objr;   c                 C   s,   t tdr(t|}t|j dd S d S )Nr5   r   )r6   r7   r5   itlislicer8   r9   r:   r   r   r   r<     s    

z MethodDispatcher.get_func_paramsc                 C   s   || _ || _| S r%   r   )r-   instanceownerr   r   r   __get__  s    zMethodDispatcher.__get__c                 O   sN   t dd |D }| j| }|s6td| jt|f || jg|R i |S )Nc                 S   s   g | ]}t |qS r   ra   rb   r   r   r   rd     rG   z-MethodDispatcher.__call__.<locals>.<listcomp>re   )rJ   rg   rh   r   ri   r   )r-   rk   r2   r   r0   r   r   r   rl     s    
zMethodDispatcher.__call__N)	r   r   r   r   r   r   r<   r   rl   r   r   r   r   r     s   
r   c                 C   s   d dd | D S )zbString representation of type signature

    >>> str_signature((int, float))
    'int, float'
    rP   c                 s   s   | ]}|j V  qd S r%   )r   )rA   r;   r   r   r   rE     rG   z str_signature.<locals>.<genexpr>rW   )r!   r   r   r   ri     s    ri   c                    sb   d  }|d7 }|D ]$}|dd dd |D  d 7 }q|d7 }|d	  fd
d|D 7 }|S )zThe text for ambiguity warningsz.
Ambiguities exist in dispatched function %s

z;The following signatures may result in ambiguous behavior:
	rP   c                 s   s   | ]}d t | d V  qdS )[]N)ri   rA   r   r   r   r   rE     rG   zwarning_text.<locals>.<genexpr>r{   z,

Consider making the following additions:

r|   c                    s$   g | ]}d t t| d   qS )z
@dispatch(z)
def %s(...))ri   r   r   rm   r   r   rd     s   z warning_text.<locals>.<listcomp>r   )r   r`   textpairr   rm   r   r     s    "
r   )warningsr   r7   conflictr   r   r   r   utilsr   Zvariadicr	   r
   	itertoolsr   rh   r   r   r   r   r$   r'   objectr(   r   r   ri   r   r   r   r   r   <module>   s$   
*  7	