U
    •Ê¹jâ  ã                   @   sÒ   d dl Z d dlmZ d dlZd dlZd dlmZmZmZm	Z	m
Z
 G dd„ dƒZdd„ Zdd	„ Zdee
 d
œdd„Zdee
 d
œdd„Ze jdee
 d
œdd„ƒZe jdd„ ƒZG dd„ deƒZdd„ Zdd„ ZdS )é    N)ÚOptional)Ú_len_torch_dispatch_stackÚ_get_dispatch_stack_atÚ_pop_torch_dispatch_stackÚ_push_on_torch_dispatch_stackÚDispatchKeyc                   @   s@   e Zd ZdZddd„Zddd„Zdd	„ Zd
d„ Zedd„ ƒZ	dS )ÚTorchDispatchModeaþ  
    A ``TorchDispatchMode`` allows you to override the meaning of all
    ``__torch_dispatch__`` overrideable functions within a dynamic scope,
    without having to actually create a tensor subclass or manually
    monkey-patch functions in the PyTorch API.  Some common situations
    where you should use a mode:

        * You want to override the meaning of factory functions, or other
          functions that do not otherwise take a tensor as an argument
          (these cannot be overridden with tensor subclasses).

        * You want to override the behavior of all functions without needing
          to wrap your inputs in tensor subclasses; e.g., if you are just
          interested in logging intermediate computations.

        * You want to control the order of execution of various tensor
          subclasses explicitly, rather than implicitly via the return of
          ``NotImplemented``.

    Independent subclasses of :class:`TorchDispatchMode` are compositional:
    modes can be pushed onto a stack using ``with MyMode():``.
    When you call functions in the PyTorch API inside your
    ``__torch_dispatch__`` implementation, by default, they will forward on to
    the next mode on the mode stack.  If you want recursively call back into
    your current ``__torch_dispatch__`` implementation, either explicitly
    invoke ``self.__torch_dispatch__(...)``, or use the context manager
    ``__torch_dispatch__(self)`` to make PyTorch
    API self-referential (beware of infinite loops, in this case!)
    Nc                 C   s(   |d k	r$t |tjjƒst‚|| jd< d S ©NÚ_dispatch_key)Ú
isinstanceÚtorchÚ_Cr   ÚAssertionErrorÚ__dict__)Úselfr
   © r   ú[/var/www/html/bwave/python/venv/lib/python3.8/site-packages/torch/utils/_python_dispatch.pyÚ__init__.   s    zTorchDispatchMode.__init__r   c                 C   s
   t ƒ ‚d S ©N)ÚNotImplementedError©r   ÚfuncÚtypesÚargsÚkwargsr   r   r   Ú__torch_dispatch__3   s    z$TorchDispatchMode.__torch_dispatch__c                 C   s   t | | j dd ¡ƒ | S r	   )Ú
_push_moder   Úget)r   r   r   r   Ú	__enter__6   s    zTorchDispatchMode.__enter__c                 C   s   t | j dd ¡ƒ d S r	   )Ú	_pop_moder   r   )r   Úexc_typeÚexc_valÚexc_tbr   r   r   Ú__exit__:   s    zTorchDispatchMode.__exit__c                 O   s   t  d¡ | ||Ž}|S )NzP`Mode.push()` is no longer necessary and can be replaced with just `with Mode()`)ÚwarningsÚwarn)Úclsr   r   Úinstancer   r   r   Úpush=   s    

zTorchDispatchMode.push)N)r   N)
Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   r   r   r#   Úclassmethodr(   r   r   r   r   r      s   

r   c                  C   s   t ƒ } | dkrt| d ƒS d S )Nr   é   )r   r   ©Z	stack_lenr   r   r   Ú_get_current_dispatch_modeC   s    r0   c                  C   s   t ƒ } dd„ t| ƒD ƒS )Nc                 S   s   g | ]}t |ƒ‘qS r   )r   )Ú.0Úir   r   r   Ú
<listcomp>J   s     z4_get_current_dispatch_mode_stack.<locals>.<listcomp>)r   Úranger/   r   r   r   Ú _get_current_dispatch_mode_stackH   s    r5   )Úkc                 C   s\   |d k	rPddl m}m} tj |¡}|ƒ D ]}|D ]}| |¡ q2q*||| ƒ nt| ƒ d S )Nr   )Úpush_mode_for_keyÚget_cached_ops)Ú
torch._opsr7   r8   r   r   Z_functionality_to_backend_keysZ_uncache_dispatchr   )Úmoder6   r7   r8   ÚksÚopÚkeyr   r   r   r   L   s    
r   c                 C   s&   | d k	rddl m} || ƒS tƒ S d S )Nr   )Úpop_mode_for_key)r9   r>   r   )r6   r>   r   r   r   r   Z   s    r   c              	   c   s$   t | ƒ}z
|V  W 5 t|| ƒ X d S r   )r   r   )r6   Úoldr   r   r   Ú_pop_mode_temporarilyb   s    
r@   c               	   c   s@   t ƒ } dd„ t| ƒD ƒ}z
|V  W 5 t|ƒD ]}t|ƒ q,X d S )Nc                 S   s   g | ]
}t ƒ ‘qS r   )r   )r1   Ú_r   r   r   r3   n   s     z*_disable_current_modes.<locals>.<listcomp>)r   r4   Úreversedr   )Zmode_lenZ	old_modesr:   r   r   r   Ú_disable_current_modesk   s    
rC   c                   @   s   e Zd Zddd„ZdS )ÚBaseTorchDispatchModer   Nc                 C   s   |d kri }|||ŽS r   r   r   r   r   r   r   w   s    z(BaseTorchDispatchMode.__torch_dispatch__)r   N)r)   r*   r+   r   r   r   r   r   rD   v   s   rD   c                 C   s2   t | tjƒot| ƒtjk}|o0t| dƒo0t| dƒS )NÚ__tensor_flatten__Ú__tensor_unflatten__)r   r   ÚTensorÚtypeÚhasattr)ÚtZis_subclassr   r   r   Úis_traceable_wrapper_subclass}   s    rK   c                 C   sV   t | ƒstdt| ƒ› �ƒ‚ddlm} t| ƒ | ¡\}}|tj||ƒ}t| ƒ ||¡S )Nz+Expects traceable wrapper subclass but got r   )Útree_map_only)	rK   r   rH   Ztorch.utils._pytreerL   rE   r   rG   rF   )rJ   ÚcallbackrL   Zflattened_tensorsÚctxZtransformed_tensorsr   r   r   Útransform_subclass„   s
    rO   )N)N)N)Ú
contextlibÚtypingr   r$   r   Ztorch._Cr   r   r   r   r   r   r0   r5   r   r   Úcontextmanagerr@   rC   rD   rK   rO   r   r   r   r   Ú<module>   s    
3

