o
    h-%                     @   sh   d dl Z d dlmZ d dlZd dlZd dlmZ g dZG dd dZdd Z	d	d
 Z
G dd dZdS )    N)OrderedDict)Any)RemovableHandleunserializable_hookwarn_if_has_hooksBackwardHookc                   @   s   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
dZdddZ	dd Z
dddZdddZdededed	dfddZdS )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                C   sj   t || _tj| _t jd7  _d| _t|tr"t |f| _d S t|t	r3t
dd |D | _d S d S )N    c                 s       | ]}t |V  qd S Nweakrefref.0dr   r   e/var/www/html/construction_image-detection-poc/venv/lib/python3.10/site-packages/torch/utils/hooks.py	<genexpr>!       z+RemovableHandle.__init__.<locals>.<genexpr>)r   r   hooks_dict_refr   r	   r   extra_dict_ref
isinstancedictlisttuple)selfr   r
   r   r   r   __init__   s   

zRemovableHandle.__init__c                 C   sR   |   }|d ur| j|v r|| j= | jD ]}| }|d ur&| j|v r&|| j= qd S r   )r   r   r   )r    r   r   r
   r   r   r   remove#   s   
zRemovableHandle.removec                 C   s8   | j d u r|  | jfS |  | jtdd | j D fS )Nc                 s   s    | ]}| V  qd S r   r   )r   r   r   r   r   r   1   s    z/RemovableHandle.__getstate__.<locals>.<genexpr>)r   r   r   r   r    r   r   r   __getstate__-   s   
 zRemovableHandle.__getstate__c                 C   s   |d d u rt t | _nt |d | _|d | _ttj| jd t_t|dk s1|d d u r6d| _	d S t
dd |d D | _	d S )Nr   r         r   c                 s   r   r   r   r   r   r   r   r   ?   r   z/RemovableHandle.__setstate__.<locals>.<genexpr>)r   r   r   r   r   maxr   r	   lenr   r   )r    stater   r   r   __setstate__3   s   

zRemovableHandle.__setstate__c                 C   s   | S r   r   r#   r   r   r   	__enter__A   s   zRemovableHandle.__enter__typevaluetbc                 C   s   |    d S r   )r"   )r    r,   r-   r.   r   r   r   __exit__D   s   zRemovableHandle.__exit__)r   N)r   r   )__name__
__module____qualname____doc__int__annotations__r	   r   r!   r"   r$   r*   r+   r/   r   r   r   r   r   
   s   
 




r   c                 C   s
   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__)fr   r   r   r   H   s   r   c                 C   sD   | j r| j D ]}| j | }t|dstdt| d qd S d S )Nr6   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hookr   r   r   r   S   s   


r   c                   @   sH   e Zd ZdZdd Zdd Zdd Zdd	 Zd
d Zdd Z	dd Z
dS )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                 C   s4   || _ || _|| _d | _d| _d | _d| _d | _d S )N)
user_hooksuser_pre_hooksmodulegrad_outputs	n_outputsoutput_tensors_indexn_inputsinput_tensors_index)r    rC   rA   rB   r   r   r   r!   h   s   
zBackwardHook.__init__c                 C   s.   d g| }t ||D ]\}}|||< q
t|S r   )zipr   )r    indicesvaluessizeresidxvalr   r   r   _pack_with_nones   s   

zBackwardHook._pack_with_nonec                    s    fdd|D }t |S )Nc                    s   g | ]} | qS r   r   )r   rN   rK   r   r   
<listcomp>{   s    z-BackwardHook._unpack_none.<locals>.<listcomp>)r   )r    rJ   rK   rM   r   rQ   r   _unpack_nonez   s   zBackwardHook._unpack_nonec                    s    fdd}| | d S )Nc                    s    j d u rd S   j|  j} jD ]'}| j| j }|d u r"qt|t|kr8tdt| dt| |}qd  _   j|S )Nz<Backward hook returned an invalid number of grad_input, got , but expected )	rD   rP   rH   rG   rA   rC   r(   RuntimeErrorrS   )
grad_input_rM   r?   outr#   r   r   r?      s    

z)BackwardHook._set_user_hook.<locals>.hookregister_hook)r    grad_fnr?   r   r#   r   _set_user_hook   s   zBackwardHook._set_user_hookc                 C   s  g }g }d}t |D ]\}}t|tjr#|| || ||jO }q
|r*t s.|d fS tjjj	j
j| }t|dkrAtddd |D }	t|	dkrRtd||	d  t|}
t||D ]\}}||
|< qat|tu rxt|
}||fS t||
 }||fS )NFr   zCCannot set Module backward hook for a Module with no input Tensors.c                 S   s*   g | ]}|j d ur|j  dkr|j qS )NBackwardHookFunctionBackward)r[   name)r   tr   r   r   rR      s   * z2BackwardHook._apply_on_tensors.<locals>.<listcomp>zaError while setting up backward hooks. Please open an issue with a code sample to reproduce this.)	enumerater   torchTensorappendrequires_gradis_grad_enablednnmodules
_functionsBackwardHookFunctionapplyr(   rU   r   rI   r,   r   )r    fnargstensors_idxtensorsrd   iargnew_tensorsgrad_fnsarg_listrN   rO   rX   r   r   r   _apply_on_tensors   s4   



zBackwardHook._apply_on_tensorsc                    s0    fdd}  ||\}}t| _| _|S )Nc                    s     |  d S r   )r\   )r[   r#   r   r   rk      s   z)BackwardHook.setup_input_hook.<locals>.fn)rt   r(   rG   rH   )r    rl   rk   rM   	input_idxr   r#   r   setup_input_hook   s
   
zBackwardHook.setup_input_hookc                    sT    fdd}d}t |ts|f}d} ||\}}t| _| _|s(|d }|S )Nc                    s    fdd}|  | d S )Nc           	         s   j|j_jr9tj}jD ]#}|jj}|d u r#qt|}||kr5td| d| |_qj jd u rp g g j	}j
D ] }|j|j}|d urlt|trhtdd |D sltdqLd _ d urjd us{J t fddjD S d S )NzABackward pre hook returned an invalid number of grad_output, got rT   c                 s   s    | ]}|d u V  qd S r   r   )r   elr   r   r   r          zKBackwardHook.setup_output_hook.<locals>.fn.<locals>.hook.<locals>.<genexpr>zoBackward hook for Modules where no input requires gradient should always return None or None for all gradients.c                 3   s    | ]} | V  qd S r   r   )r   ro   local_grad_outputsr   r   r      rx   )rP   rF   rE   rD   rB   r(   rC   rU   rH   rG   rA   r   r   all)	rW   grad_outputexpected_lenuser_pre_hookhook_grad_outputs
actual_lengrad_inputs	user_hookrM   r#   ry   r   r?      s>   



$z8BackwardHook.setup_output_hook.<locals>.fn.<locals>.hookrY   )r[   r?   r#   r   r   rk      s   $z*BackwardHook.setup_output_hook.<locals>.fnTFr   )r   r   rt   r(   rE   rF   )r    rl   rk   is_tuplerM   
output_idxr   r#   r   setup_output_hook   s   '

zBackwardHook.setup_output_hookN)r0   r1   r2   r3   r!   rP   rS   r\   rt   rv   r   r   r   r   r   r   ]   s    
%	r   )ra   collectionsr   r   r:   typingr   __all__r   r   r   r   r   r   r   r   <module>   s   >
