U
    <cX                     @   s   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	d
 Zdd Ze jdd ZG dd dZG dd deZdS )    N)_len_torch_dispatch_stack_get_dispatch_stack_at_pop_torch_dispatch_stack_push_on_torch_dispatch_stack_set_torch_dispatch_modec                   @   s6   e Zd Z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
   t  d S N)NotImplementedErrorselffunctypesargskwargsr   r   @/tmp/pip-unpacked-wheel-gikjz4vx/torch/utils/_python_dispatch.py__torch_dispatch__,   s    z$TorchDispatchMode.__torch_dispatch__c                 C   s   t |  | S r	   )
_push_mode)r   r   r   r   	__enter__/   s    zTorchDispatchMode.__enter__c                 C   s
   t   d S r	   )	_pop_mode)r   exc_typeexc_valexc_tbr   r   r   __exit__3   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   push6   s    

zTorchDispatchMode.push)r   N)	__name__
__module____qualname____doc__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_mode<   s    r&   c                  C   s   t  } dd t| D S )Nc                 S   s   g | ]}t |qS r   )r   ).0ir   r   r   
<listcomp>C   s     z4_get_current_dispatch_mode_stack.<locals>.<listcomp>)r   ranger%   r   r   r    _get_current_dispatch_mode_stackA   s    r+   c                 C   s    t  dkrtt  t|  d S Nr   )r   r   _TorchDispatchStackModer   )moder   r   r   r   E   s    

r   c                  C   s   t  } t dkrtd  | S r,   )r   r   r   oldr   r   r   r   K   s    
r   c                  c   s    t  } z
| V  W 5 t|  X d S r	   )r   r   r/   r   r   r   _pop_mode_temporarilyR   s    
r1   c                   @   s   e Zd ZdddZdS )r-   r   Nc              
   C   sf   t  V}t dkrt|  |jjt|kr@tt| dd |||||W  5 Q R  S Q R X d S )Nr   z's torch_dispatch function z,should be a normal method not a class method)r1   r   r   r   __self__typeRuntimeError)r   r   r   r   r   r0   r   r   r   r   ]   s    
z*_TorchDispatchStackMode.__torch_dispatch__)r   Nr   r    r!   r   r   r   r   r   r-   \   s   r-   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   h   s    z(BaseTorchDispatchMode.__torch_dispatch__)r   Nr5   r   r   r   r   r6   g   s   r6   )
contextlibr   Ztorch._Cr   r   r   r   r   r   r&   r+   r   r   contextmanagerr1   r-   r6   r   r   r   r   <module>   s   
.
	