U
    yh6                     @   s  d dl mZ d dlZd dlm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dd	d
ddddddddgZG dd deZdd	 Zededdd
 ZededefddZdd Z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 )!    )warnN)
deprecated   )orderingambiguitiessuper_signatureAmbiguityWarning)expand_tuples)Variadic
isvariadicMDNotImplementedErrorambiguity_warnhalt_orderingrestart_orderingvariadic_signature_matches_itervariadic_signature_matches
DispatchersourceMethodDispatcherstr_signaturewarning_textc                   @   s   e Zd ZdZdS )r   z- A NotImplementedError for multiple dispatch N)__name__
__module____qualname____doc__ r   r   o/var/www/html/venv/lib/python3.8/site-packages/torch/fx/experimental/unification/multipledispatch/dispatcher.pyr      s   c                 C   s   t t| j|t dS )aA   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   r   namer   )
dispatcherr   r   r   r   r      s    z?`halt_ordering` is deprecated, you can safely remove this call.categoryc                   C   s   dS )z5Deprecated interface to temporarily disable ordering.Nr   r   r   r   r   r       s    z`restart_ordering` is deprecated, if you would like to eagerly order the dispatchers, you should call the `reorder()` method on each dispatcher.c                 C   s   dS )z4Deprecated interface to temporarily resume ordering.Nr   )on_ambiguityr   r   r   r   (   s    c                 c   sx   t |}t|}| D ]$}t||}|V  t|st|}qzt|}W n& tk
rl   t|sbtdV  Y nX dV  dS )ag  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AssertionError)typesfull_signatureZsigitersigtypmatchesr   r   r   r   1   s    

c                 C   s   |st tt| |S N)r&   allr   )r'   r(   r   r   r   r   X   s    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eded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 )-r   a   Dispatch methods based on type signature
    Use ``dispatch`` to add implementations
    Examples
    --------
    >>> # xdoctest: +SKIP("bad import name")
    >>> 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.   r1   r0   )selfr   r1   r   r   r   __init__r   s    zDispatcher.__init__c                    s    fdd}|S )a   register dispatcher with new implementation
        >>> # xdoctest: +SKIP
        >>> 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 r,   )add)funckwargsr2   r'   r   r   _df   s    z Dispatcher.register.<locals>._dfr   )r2   r'   r7   r8   r   r6   r   registery   s    zDispatcher.registerc                 C   s"   t tdrt|}|j S d S )N	signature)hasattrinspectr:   
parametersvaluesclsr5   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 )z; get annotations of function positional parameters
        c                 3   s$   | ]}|j  j jfk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,   )
annotationrE   r   r   r   rJ      s   c                 3   s   | ]}| j k	V  qd S r,   )empty)rF   annrH   r   r   rJ      s     N)rA   r<   rI   tupler-   )r@   r5   paramsannotationsr   rH   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| d	| d
| j
 t|tr|t|krt	dt|dkrt	d|t|d   qV|| qV|| jt|< | j  z| `W n tk
r$   Y nX dS )ay   Add new types/method pair to dispatcher
        >>> # xdoctest: +SKIP
        >>> 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,   )
isinstancerN   )rF   r*   r   r   r   rJ      s     z!Dispatcher.add.<locals>.<genexpr>Nr   )start, c                 s   s&   | ]}t |tr|jnt|V  qd S r,   )rR   typer   str)rF   cr   r   r   rJ      s   zTried to dispatch on non-type: z
In signature: <z>
In function: z+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   )rQ   anyr	   r4   	enumeraterR   rU   listjoin	TypeErrorr   lenappendr
   r.   rN   r0   clearr/   AttributeError)	r2   r:   r5   rP   ZtypsZnew_signatureindexr*   Zstr_sigr   r   r   r4      s@    



zDispatcher.addc                 C   s*   z| j W S  tk
r$   |   Y S X d S r,   )r/   r`   reorderr2   r   r   r   r      s    zDispatcher.orderingc                 C   s,   t | j | _}t| j}|r(|| | |S r,   )r   r.   r/   r   )r2   r!   Zodambr   r   r   rb      s
    

zDispatcher.reorderc                 O   s  t dd |D }z| j| }W nX tk
rx } z:| j| }|s^td| j dt| d||| j|< W 5 d }~X Y nX z|||W S  tk
r } zl| j| }t	| |D ]2}z|||W    W Y :S  tk
r   Y qX qtd| j dt| d|W 5 d }~X Y nX d S )Nc                 S   s   g | ]}t |qS r   rU   rF   argr   r   r   
<listcomp>   s     z'Dispatcher.__call__.<locals>.<listcomp>Could not find signature for : <>zMatching functions for z(> found, but none completed successfully)
rN   r0   KeyErrordispatchNotImplementedErrorr   r   r   dispatch_iterr#   )r2   argsr7   r'   r5   er.   r   r   r   __call__   s6    

zDispatcher.__call__c                 C   s   d| j  dS )Nz<dispatched rk   r   rc   r   r   r   __str__  s    zDispatcher.__str__c                 G   s@   || j kr| j | S zt| j| W S  tk
r:   Y dS X dS )ai  Determine 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.
        >>> # xdoctest: +SKIP
        >>> 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#   ro   r%   r2   r'   r   r   r   rm     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)r]   r   r-   mapr$   r.   r   r   )r2   r'   nr:   resultr   r   r   ro   2  s    



zDispatcher.dispatch_iterz1`resolve()` is deprecated, use `dispatch(*types)`r   c                 C   s
   | j | S )z Determine appropriate implementation for this type signature
        .. deprecated:: 0.4.4
            Use ``dispatch(*types)`` instead
        )rm   ru   r   r   r   resolve>  s    zDispatcher.resolvec                 C   s   | j | jdS )Nr   r.   r{   rc   r   r   r   __getstate__F  s    zDispatcher.__getstate__c                 C   s*   |d | _ |d | _t| j| _i | _d S )Nr   r.   )r   r.   r   r/   r0   )r2   dr   r   r   __setstate__J  s    

zDispatcher.__setstate__c                 C   s   d| j  g}| jr || j g }| jd d d D ]`}| j| }|jrdt| d}|dt| d 7 }||j 7 }|| q4|t| q4|r|dd	|  d		|S )
NzMultiply dispatched method: rv   z	Inputs: <z>
-
zOther signatures:
    z
    

)
r   r1   r^   r   r.   r   r   r]   stripr[   )r2   docsotherr)   r5   sr   r   r   r   P  s    
zDispatcher.__doc__c                 G   s   | j tt| jS r,   )rm   rw   rU   r   )r2   rp   r   r   r   _helpg  s    zDispatcher._helpc                 O   s   t | j|  dS )z: Print docstring for the function corresponding to inputs N)printr   r2   rp   r7   r   r   r   helpj  s    zDispatcher.helpc                 G   s$   | j tt| }|stdt|S )NzNo function found)rm   rw   rU   r\   r   )r2   rp   r5   r   r   r   _sourcen  s    zDispatcher._sourcec                 O   s   t | j|  dS )z< Print source code for the function corresponding to inputs N)r   r   r   r   r   r   r   t  s    zDispatcher.source)N)r   r   r   r   	__slots__r3   r9   classmethodrA   rQ   r4   propertyr   r   rb   rr   rt   __repr__rm   ro   r   FutureWarningrz   r|   r~   r   r   r   r   r   r   r   r   r   ^   s6   


?



c                 C   s$   dt |  d}|t |  }|S )NzFile: r   )r<   getsourcefile	getsource)r5   r   r   r   r   r   y  s    c                   @   s0   e Zd ZdZdZedd Zdd Zdd Zd	S )
r   zO Dispatch methods based on type signature
    See Also:
        Dispatcher
    objr@   c                 C   s,   t tdr(t|}t|j dd S d S )Nr:   r   )r;   r<   r:   itlislicer=   r>   r?   r   r   r   rA     s    

z MethodDispatcher.get_func_paramsc                 C   s   || _ || _| S r,   r   )r2   instanceownerr   r   r   __get__  s    zMethodDispatcher.__get__c                 O   sN   t dd |D }| j| }|s<td| j dt| d|| jf||S )Nc                 S   s   g | ]}t |qS r   re   rf   r   r   r   rh     s     z-MethodDispatcher.__call__.<locals>.<listcomp>ri   rj   rk   )rN   rm   rn   r   r   r   )r2   rp   r7   r'   r5   r   r   r   rr     s
    
zMethodDispatcher.__call__N)	r   r   r   r   r   r   rA   r   rr   r   r   r   r   r     s   
c                 C   s   d dd | D S )zb String representation of type signature
    >>> str_signature((int, float))
    'int, float'
    rT   c                 s   s   | ]}|j V  qd S r,   )r   )rF   r@   r   r   r   rJ     s     z str_signature.<locals>.<genexpr>r[   )r)   r   r   r   r     s    c                    sf   d  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 warnings z*
Ambiguities exist in dispatched function r   z;The following signatures may result in ambiguous behavior:
	rT   c                 s   s   | ]}d t | d V  qdS )[]N)r   rF   r   r   r   r   rJ     s     zwarning_text.<locals>.<genexpr>r   z,

Consider making the following additions:

c                    s(   g | ] }d t t| d  d qS )z
@dispatch(z)
def z(...))r   r   r   rs   r   r   rh     s   
z warning_text.<locals>.<listcomp>r   )r   rd   textpairr   rs   r   r     s    
)warningsr   r<   typing_extensionsr   conflictr   r   r   r   utilsr	   Zvariadicr
   r   	itertoolsr   __all__rn   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   <module>   sF   
     
'  