
    ǄgV%                     t    d dl Z d dlmZ d dlZd dlZd dlmZmZ g dZ G d d      Z	d Z
d Z G d	 d
      Zy)    N)OrderedDict)AnyTuple)RemovableHandleunserializable_hookwarn_if_has_hooksBackwardHookc                   z    e Zd ZU dZeed<   dZeed<   dddeded	dfd
ZddZ	d Z
ddZddZdededed	dfdZy)r   a]  
    A handle which provides the capability to remove a hook.

    Args:
        hooks_dict (dict): A dictionary of hooks, indexed by hook ``id``.
        extra_dict (Union[dict, List[dict]]): An additional dictionary or list of
            dictionaries whose keys will be deleted when the same keys are
            removed from ``hooks_dict``.
    idr   next_idN)
extra_dict
hooks_dictr   returnc                J   t        j                  |      | _        t        j                  | _        t        xj                  dz  c_        d| _        t        |t              rt        j                  |      f| _        y t        |t              rt        d |D              | _        y y )N    c              3   F   K   | ]  }t        j                  |        y wNweakrefref.0ds     Y/home/mcse/projects/flask_80/flask-venv/lib/python3.12/site-packages/torch/utils/hooks.py	<genexpr>z+RemovableHandle.__init__.<locals>.<genexpr>!   s     'K1A'K   !)r   r   hooks_dict_refr   r   r   extra_dict_ref
isinstancedictlisttuple)selfr   r   s      r   __init__zRemovableHandle.__init__   sy    %kk*5!))1$%'j$'#*;;z#:"<D
D)"''K
'K"KD *    c                     | j                         }|| j                  |v r|| j                  = | j                  D ](  } |       }|| j                  |v s|| j                  = * y r   )r   r   r   )r$   r   r   r   s       r   removezRemovableHandle.remove#   sf    ((*
!dgg&;477#&& 	(CJ%$''Z*?tww'	(r&   c                     | j                   | j                         | j                  fS | j                         | j                  t        d | j                   D              fS )Nc              3   *   K   | ]  } |         y wr   r   )r   r   s     r   r   z/RemovableHandle.__getstate__.<locals>.<genexpr>1   s     9_C#%9_s   )r   r   r   r#   r$   s    r   __getstate__zRemovableHandle.__getstate__-   sQ    &'')47733'')477E9_4K^K^9_4_``r&   c                 l   |d   #t        j                  t                     | _        nt        j                  |d         | _        |d   | _        t        t        j                  | j                  dz         t        _        t        |      dk  s|d   d| _	        y t        d |d   D              | _	        y )Nr   r         r   c              3   F   K   | ]  }t        j                  |        y wr   r   r   s     r   r   z/RemovableHandle.__setstate__.<locals>.<genexpr>?   s     'I1A'Ir   )r   r   r   r   r   maxr   r   lenr   r#   )r$   states     r   __setstate__zRemovableHandle.__setstate__3   s    8")++km"<D")++eAh"7D("%o&=&=tww{"Ku:>U1X-"$D"''Ia'I"IDr&   c                     | S r   r   r+   s    r   	__enter__zRemovableHandle.__enter__A   s    r&   typevaluetbc                 $    | j                          y r   )r(   )r$   r7   r8   r9   s       r   __exit__zRemovableHandle.__exit__D   s    r&   )r   N)r   r   )__name__
__module____qualname____doc__int__annotations__r   r   r%   r(   r,   r4   r6   r;   r   r&   r   r   r   
   sp     	GGS=A 	L3 	Ls 	Ld 	L(aJS  # $ r&   r   c                     d| _         | S )z
    Mark a function as an unserializable hook with this decorator.

    This suppresses warnings that would otherwise arise if you attempt
    to serialize a tensor that has a hook.
    T)__torch_unserializable__)fs    r   r   r   H   s     "&AHr&   c                     | j                   rP| j                   D ]@  }| j                   |   }t        |d      rt        j                  dt	        |       d       B y y )NrC   zbackward hook z on tensor will not be serialized.  If this is expected, you can decorate the function with @torch.utils.hooks.unserializable_hook to suppress this warning)_backward_hookshasattrwarningswarnrepr)tensorkhooks      r   r   r   S   s`    '' 	:A))!,D4!;<tDzl ;9 9 :	: r&   c                   :    e Zd ZdZd Zd Zd Zd Zd Zd Z	d Z
y	)
r	   a  
    A wrapper class to implement nn.Module backward hooks.

    It handles:
      - Ignoring non-Tensor inputs and replacing them by None before calling the user hook
      - Generating the proper Node to capture a set of Tensor's gradients
      - Linking the gradients captures for the outputs with the gradients captured for the input
      - Calling the user hook once both output and input gradients are available
    c                 t    || _         || _        || _        d | _        d| _        d | _        d| _        d | _        y )N)
user_hooksuser_pre_hooksmodulegrad_outputs	n_outputsoutput_tensors_indexn_inputsinput_tensors_index)r$   rS   rQ   rR   s       r   r%   zBackwardHook.__init__h   s>    $, $(!#' r&   c                 V    d g|z  }t        ||      D ]
  \  }}|||<    t        |      S r   )zipr#   )r$   indicesvaluessizeresidxvals          r   _pack_with_nonezBackwardHook._pack_with_nones   s<    ftmGV, 	HCCH	 Szr&   c                 R    g }|D ]  }|j                  ||           t        |      S r   )appendr#   )r$   r[   r\   r^   r_   s        r   _unpack_nonezBackwardHook._unpack_nonez   s2     	$CJJvc{#	$ Szr&   c                 2      fd}|j                  |       y )Nc           	         j                   y j                  j                  | j                        }j                  D ]_  } |j
                  |j                         }|$t        |      t        |      k7  r#t        dt        |       dt        |             |}a d _         j                  j                  |      S )Nz<Backward hook returned an invalid number of grad_input, got , but expected )	rT   ra   rX   rW   rQ   rS   r2   RuntimeErrorrd   )
grad_input_r^   rM   outr$   s        r   rM   z)BackwardHook._set_user_hook.<locals>.hook   s      ( &&t'?'?T]][C 
4;;T->->?;s8s3x'& (..1#hZs3xj(R S S 
 !%D$$T%=%=sCCr&   register_hook)r$   grad_fnrM   s   `  r   _set_user_hookzBackwardHook._set_user_hook   s    	D0 	d#r&   c                 ,   g }g }d}t        |      D ]Q  \  }}t        |t        j                        s!|j	                  |       |j	                  |       ||j
                  z  }S |rt        j                         s|d fS t        j                  j                  j                  j                  j                  | }t        |      dk(  rt        d      |D 	cg c]9  }	|	j                  |	j                  j                         dk(  s.|	j                  ; }
}	t        |
      dk(  rt        d       ||
d          t!        |      }t#        ||      D ]
  \  }}|||<    t%        |      t&        u rt'        |      }||fS  t%        |      | }||fS c c}	w )NFr   zCCannot set Module backward hook for a Module with no input Tensors.BackwardHookFunctionBackwardzaError while setting up backward hooks. Please open an issue with a code sample to reproduce this.)	enumerater    torchTensorrc   requires_gradis_grad_enablednnmodules
_functionsBackwardHookFunctionapplyr2   rh   rn   namer"   rZ   r7   r#   )r$   fnargstensors_idxtensorsru   iargnew_tensorstgrad_fnsarg_listr_   r`   rk   s                  r   _apply_on_tensorszBackwardHook._apply_on_tensors   s    o 	3FAs#u||,""1%s#!2!22		3 %"7"7"9:hh&&11FFLLgV{q dee'2  D!aii6KPQPYPYP^P^P`  eC  QCAII  D  Dx=A  P Q Q 	8A;:K5 	 HCHSM	  :/C K $t*h'CK Ds   F)FFc                 j      fd} j                  ||      \  }}t        |       _        | _        |S )Nc                 (    j                  |        y r   )ro   )rn   r$   s    r   r}   z)BackwardHook.setup_input_hook.<locals>.fn   s    (r&   )r   r2   rW   rX   )r$   r~   r}   r^   	input_idxs   `    r   setup_input_hookzBackwardHook.setup_input_hook   s8    	) //D9YD	#, 
r&   c                       fd}d}t        |t              s|f}d} j                  ||      \  }}t        |       _        | _        |s|d   }|S )Nc                 2    fd}| j                  |       y )Nc                   	 
j                  
j                  |
j                        
_        
j                  rnt        
j                        }
j                  D ]J  } |
j                  
j                        }|#t        |      }||k7  rt        d| d|       |
_        L 
j                  	
j                  
j                  g g 
j                        }
j                  D ]P  } |
j                  |
j                        }|$t        |t              rt        d |D              rGt        d       d 
_        	,
j                  J t        	fd
j                  D              S y )NzABackward pre hook returned an invalid number of grad_output, got rg   c              3   $   K   | ]  }|d u  
 y wr   r   )r   els     r   r   zKBackwardHook.setup_output_hook.<locals>.fn.<locals>.hook.<locals>.<genexpr>   s     RlbdSUY]S]Rls   zoBackward hook for Modules where no input requires gradient should always return None or None for all gradients.c              3   (   K   | ]	  }|     y wr   r   )r   r   local_grad_outputss     r   r   zKBackwardHook.setup_output_hook.<locals>.fn.<locals>.hook.<locals>.<genexpr>   s      Z1!3A!6 Zs   )ra   rV   rU   rT   rR   r2   rS   rh   rX   rW   rQ   r    r#   all)rj   grad_outputexpected_lenuser_pre_hookhook_grad_outputs
actual_lengrad_inputs	user_hookr^   r   r$   s            @r   rM   z8BackwardHook.setup_output_hook.<locals>.fn.<locals>.hook   s   $($8$89R9R9D9=%I! &&#&t'8'8#9L)-)<)< 	>,9$++tGXGX,Y),4$%():%;
%5". 066@\Q]P^0` #a a,=)	> &*%6%6" ++3"&"6"6r2t}}"MK%)__ p	'[$BSBST?JsE4JsRlhkRlOl". 0o #p pp
 )-D%%144@@@  Z@Y@Y ZZZ 2r&   rl   )rn   rM   r$   s     r   r}   z*BackwardHook.setup_output_hook.<locals>.fn   s    "[H !!$'r&   TFr   )r    r#   r   r2   rU   rV   )r$   r~   r}   is_tupler^   
output_idxs   `     r   setup_output_hookzBackwardHook.setup_output_hook   s`    %	(N $&7DH00T:ZT$.!a&C
r&   N)r<   r=   r>   r?   r%   ra   rd   ro   r   r   r   r   r&   r   r	   r	   ]   s+    	($6# J3r&   r	   )rs   collectionsr   r   rH   typingr   r   __all__r   r   r   r	   r   r&   r   <module>r      s:     #   
Y; ;|:` `r&   