B
    dd/                 @   s   d dl mZ 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ZG dd deZd	d
 ZG dd dZdd Ze ZdgZdd ZefddZG dd dZdd ZG dd deZdd Zdd ZdS )    )Set)warnN   )orderingambiguitiessuper_signatureAmbiguityWarning)expand_tuplesc               @   s   e Zd ZdZdS )MDNotImplementedErrorz- A NotImplementedError for multiple dispatch N)__name__
__module____qualname____doc__ r   r   n/work/yifan.wang/ringdown/master-ringdown-env/lib/python3.7/site-packages/sympy/multipledispatch/dispatcher.pyr
   
   s   r
   c             C   s   t t| j|t dS )aC   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               @   s    e Zd ZdZdd Zdd ZdS )RaiseNotImplementedErrorz*Raise ``NotImplementedError`` when called.c             C   s
   || _ d S )N)r   )selfr   r   r   r   __init__$   s    z!RaiseNotImplementedError.__init__c             O   s.   t dd |D }td| jjt|f d S )Nc             s   s   | ]}t |V  qd S )N)type).0ar   r   r   	<genexpr>(   s    z4RaiseNotImplementedError.__call__.<locals>.<genexpr>z Ambiguous signature for %s: <%s>)tupleNotImplementedErrorr   r   str_signature)r   argskwargstypesr   r   r   __call__'   s    z!RaiseNotImplementedError.__call__N)r   r   r   r   r   r"   r   r   r   r   r   !   s   r   c             C   sD   x>|D ]6}t t|}tt|dkr(q| j|t| td qW dS )a  
    If super signature for ambiguous types is duplicate types, ignore it.
    Else, register instance of ``RaiseNotImplementedError`` for ambiguous types.

    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
        ambiguity_warn
    r   )on_ambiguityN)r   r   lensetaddr   #ambiguity_register_error_ignore_dup)r   r   amb	signaturer   r   r   r'   .   s    
r'   Tc               C   s   dt d< d S )NFr   )_resolver   r   r   r   halt_orderingN   s    r+   c             C   s*   dt d< xtr$t }|j| d q
W d S )NTr   )r#   )r*   _unresolved_dispatcherspopreorder)r#   r   r   r   r   restart_orderingR   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	e
f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 ))
Dispatcheraj   Dispatch methods based on type signature

    Use ``dispatch`` to add implementations

    Examples
    --------

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

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

    >>> f(3)
    4
    >>> f(3.0)
    2.0
    )r   r   funcsr   _cachedocNc             C   s,   | | _ | _t | _t | _g | _|| _d S )N)r   r   dictr1   r2   r   r3   )r   r   r3   r   r   r   r   q   s
    zDispatcher.__init__c                s    fdd}|S )a#   Register dispatcher with new implementation

        >>> from sympy.multipledispatch.dispatcher import Dispatcher
        >>> 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  | S )N)r&   )func)r    r   r!   r   r   _   s    zDispatcher.register.<locals>._r   )r   r!   r    r6   r   )r    r   r!   r   registerx   s    zDispatcher.registerc             C   s"   t tdrt|}|j S d S )Nr)   )hasattrinspectr)   
parametersvalues)clsr5   sigr   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 sR|S dS )z; Get annotations of function positional parameters
        c             3   s$   | ]}|j  j jfkr|V  qd S )N)kindPOSITIONAL_ONLYPOSITIONAL_OR_KEYWORD)r   param)	Parameterr   r   r      s    z2Dispatcher.get_func_annotations.<locals>.<genexpr>c             s   s   | ]}|j V  qd S )N)
annotation)r   rB   r   r   r   r      s   c             3   s   | ]}| j kV  qd S )N)empty)r   ann)rC   r   r   r      s    N)r>   r9   rC   r   any)r<   r5   paramsannotationsr   )rC   r   get_func_annotations   s    

zDispatcher.get_func_annotationsc             C   s   |s|  |}|r|}tdd |D rLxt|D ]}| ||| q2W dS x>|D ]6}t|tsRddd |D }td||| jf qRW || j	|< | j
|d | j  dS )a   Add new types/method pair to dispatcher

        >>> from sympy.multipledispatch import 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 )N)
isinstancer   )r   typr   r   r   r      s    z!Dispatcher.add.<locals>.<genexpr>Nz, c             s   s&   | ]}t |tr|jnt|V  qd S )N)rK   r   r   str)r   cr   r   r   r      s   zDTried to dispatch on non-type: %s
In signature: <%s>
In function: %s)r#   )rJ   rG   r	   r&   rK   r   join	TypeErrorr   r1   r.   r2   clear)r   r)   r5   r#   rI   ZtypsrL   Zstr_sigr   r   r   r&      s"    





zDispatcher.addc             C   s<   t d r.t| j| _t| j}|r8|| | n
t|  d S )Nr   )r*   r   r1   r   r,   r&   )r   r#   r(   r   r   r   r.      s    
zDispatcher.reorderc             O   s   t dd |D }y| j| }W nB tk
rb   | j| }|sTtd| jt|f || j|< Y nX y
|||S  tk
r   | j| }t	| x,|D ]$}y
|||S  tk
r   Y qX qW td| jt|f Y nX d S )Nc             S   s   g | ]}t |qS r   )r   )r   argr   r   r   
<listcomp>   s    z'Dispatcher.__call__.<locals>.<listcomp>z%Could not find signature for %s: <%s>zFMatching functions for %s: <%s> found, but none completed successfully)
r   r2   KeyErrordispatchr   r   r   r
   dispatch_iternext)r   r   r    r!   r5   r1   r   r   r   r"      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 kr| j | S yt| j| S  tk
r6   dS X dS )a`   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 sympy.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:
            ``sympy.multipledispatch.conflict`` - module to determine resolution order
        N)r1   rW   rV   StopIteration)r   r!   r   r   r   rU     s    

zDispatcher.dispatchc             g   sH   t |}x:| jD ]0}t ||krttt||r| j| }|V  qW d S )N)r$   r   allmap
issubclassr1   )r   r!   nr)   resultr   r   r   rV   #  s
    
zDispatcher.dispatch_iterc             C   s   t dt | j| S )z Deterimine appropriate implementation for this type signature

        .. deprecated:: 0.4.4
            Use ``dispatch(*types)`` instead
        z-resolve() is deprecated, use dispatch(*types))r   DeprecationWarningrU   )r   r!   r   r   r   resolve*  s    zDispatcher.resolvec             C   s   | j | jdS )N)r   r1   )r   r1   )r   r   r   r   __getstate__5  s    zDispatcher.__getstate__c             C   s,   |d | _ |d | _t| j| _t | _d S )Nr   r1   )r   r1   r   r4   r2   )r   dr   r   r   __setstate__9  s    

zDispatcher.__setstate__c             C   s   d| j  g}| jr|| j g }xp| jd d d D ]\}| j| }|jrdt| }|dt| d 7 }||j 7 }|| q4|t| q4W |r|dd	|  d	|S )	NzMultiply dispatched method: %szInputs: <%s>
-
zOther signatures:
    z
    z

)
r   r3   appendr   r1   r   r   r$   striprO   )r   docsotherr=   r5   sr   r   r   r   ?  s    
zDispatcher.__doc__c             G   s   | j tt| jS )N)rU   r[   r   r   )r   r   r   r   r   _helpV  s    zDispatcher._helpc             O   s   t | j|  dS )z: Print docstring for the function corresponding to inputs N)printrl   )r   r   r    r   r   r   helpY  s    zDispatcher.helpc             G   s$   | j tt| }|stdt|S )NzNo function found)rU   r[   r   rP   source)r   r   r5   r   r   r   _source]  s    zDispatcher._sourcec             O   s   t | j|  dS )z< Print source code for the function corresponding to inputs N)rm   rp   )r   r   r    r   r   r   ro   c  s    zDispatcher.source)N)r   r   r   r   	__slots__r   r7   classmethodr>   rJ   r   r&   r.   r"   rX   __repr__rU   rV   r`   ra   rc   propertyrl   rn   rp   ro   r   r   r   r   r0   Y   s*   
 ,	r0   c             C   s    dt |  }|t |  }|S )Nz
File: %s

)r9   getsourcefile	getsource)r5   rk   r   r   r   ro   h  s    ro   c               @   s,   e Zd ZdZedd Zdd Zdd ZdS )	MethodDispatcherzP Dispatch methods based on type signature

    See Also:
        Dispatcher
    c             C   s,   t tdr(t|}t|j dd S d S )Nr)   r   )r8   r9   r)   itlislicer:   r;   )r<   r5   r=   r   r   r   r>   u  s    

z MethodDispatcher.get_func_paramsc             C   s   || _ || _| S )N)objr<   )r   instanceownerr   r   r   __get__{  s    zMethodDispatcher.__get__c             O   sH   t dd |D }| j| }|s6td| jt|f || jf||S )Nc             S   s   g | ]}t |qS r   )r   )r   rR   r   r   r   rS     s    z-MethodDispatcher.__call__.<locals>.<listcomp>z%Could not find signature for %s: <%s>)r   rU   r   r   r   rz   )r   r   r    r!   r5   r   r   r   r"     s    
zMethodDispatcher.__call__N)r   r   r   r   rr   r>   r}   r"   r   r   r   r   rw   n  s   rw   c             C   s   d dd | D S )z String representation of type signature

    >>> from sympy.multipledispatch.dispatcher import str_signature
    >>> str_signature((int, float))
    'int, float'
    z, c             s   s   | ]}|j V  qd S )N)r   )r   r<   r   r   r   r     s    z str_signature.<locals>.<genexpr>)rO   )r=   r   r   r   r     s    r   c                sf   d  }|d7 }x,|D ]$}|dd dd |D  d 7 }qW |d7 }|d	  fd
d|D 7 }|S )z! The text for ambiguity warnings z.
Ambiguities exist in dispatched function %s

z;The following signatures may result in ambiguous behavior:
	z, c             s   s   | ]}d t | d V  qdS )[]N)r   )r   rk   r   r   r   r     s    zwarning_text.<locals>.<genexpr>rf   z,

Consider making the following additions:

z

c                s$   g | ]}d t t| d   qS )z
@dispatch(z)
def %s(...))r   r   )r   rk   )r   r   r   rS     s   z warning_text.<locals>.<listcomp>)rO   )r   r(   textpairr   )r   r   r     s    
"r   )typingr   ZtSetwarningsr   r9   conflictr   r   r   r   utilsr	   	itertoolsrx   r   r
   r   r   r'   r%   r,   r*   r+   r/   r0   ro   rw   r   r   r   r   r   r   <module>   s(     
