
    BVh,*                     `   d Z ddlZddlZddlZddlmZ ddlmZ ddl	m
Z
 ddlmZ ddlmZ ddlmZ dd	lmZ dd
lmZ  ed e       d      Z	 	 ddZd Zd Zd Zd Zd Zd Zd Zd Z G d dej<                        Z e       Z ejB                  d        Z"d Z#ejB                  d        Z$y)zKUtility functions shared between SavedModel saving/loading implementations.    N)context)backend)base_layer_utils)control_flow_util)tf_contextlib)
tf_inspect)
LazyLoader)tf_decoratortraining_libz'tensorflow.python.keras.engine.trainingc                     	 t               }t        |d      r|j                  }|j                  }n|}t	        ||||      \  	}	 fd}t        j                  |||      }rt        j                  |       S |S )a:  Creates fn that adds the losses returned by call_fn & returns the outputs.

  Args:
    layer: A Keras layer object
    call_fn: tf.function that takes layer inputs (and possibly a training arg),
      and returns a tuple of (outputs, list of losses).
    default_training_value: Default value of the training kwarg. If `None`, the
      default is `K.learning_phase()`.
    return_method: Whether to return a method bound to the layer.

  Returns:
    function that calls call_fn and returns the outputs. Losses returned by
    call_fn are added to the layer losses.
  original_layer_callc                      r| dd }  | i |\  }}j                  |d       t        j                         r0j                         D ]  }|ust        j
                  g|_         |S )zFReturns the outputs from the layer call function, and adds the losses.   NT)inputs)add_lossr   executing_eagerly_flatten_layersr   REVIVED_LOSS_PLACEHOLDER_eager_losses)argskwargsoutputslossesifnlayerreturn_methods        `/home/dcms/DCMS/lib/python3.12/site-packages/tensorflow/python/keras/saving/saved_model/utils.pyreturn_outputs_and_add_lossesz7use_wrapped_call.<locals>.return_outputs_and_add_losses@   sz    !"Xd$)&)OGV	NN6$N'   "$$& H!E>-FFG!/H N    )targetdecorator_funcdecorator_argspec)	layer_uses_training_boolhasattrr   __call__maybe_add_training_argr
   make_decoratortypes
MethodType)
r   call_fndefault_training_valuer   expects_training_argoriginal_callarg_specr   	decoratedr   s
   `  `     @r   use_wrapped_callr1   &   s      2%8W+,//MGM'W24JL,"h, ))2 ")
 Iu--r    c                     | j                   ry| h}t        |       }|rQ|j                         } | |v rt        | dd      ry|j	                  |        |j                  t        |              |rQy)zHReturns whether this layer or any of its children uses the training arg.T_expects_training_argF)r3   list_all_layerspopgetattraddextend)r   visitedto_visits      r   r$   r$   a   so    
  G'U#(LLNEu-t4KKOOOE*+ 	 
r    c                     t        | t        j                        r| j                  S t	        | j                  dd            S )NF)include_self	recursive)
isinstancer   Modellayerslistr   )objs    r   r4   r4   r   s9    \''( ::##%#HIIr    c                     t        | g      }|j                  t        j                  j	                  d t        |       D                     |S )Nc              3   2   K   | ]  }t        |        y wN)list_all_layers_and_sublayers).0r   s     r   	<genexpr>z0list_all_layers_and_sublayers.<locals>.<genexpr>}   s      )N/4#E*)Ns   )setupdate	itertoolschainfrom_iterabler4   )rB   ss     r   rF   rF   {   sE    	3%j!((9??(( )N8G8L)N N O	
(r    c           	      j    |sdfS  fd}t        j                         }|j                  t        |j                        ng }|j                  }|j
                  xs i }d|j                  vr|j                  d       |d<   nc|j                  j                  d      }	t        |j                        |	z
  }
|j                  r$t        |j                        |
k\  r||
    ||
 <   t        j                  |j                  |j                  |j                  ||||j                        }||fS )a  Decorate call and optionally adds training argument.

  If a layer expects a training argument, this function ensures that 'training'
  is present in the layer args or kwonly args, with the default training value.

  Args:
    original_call: Original call function.
    wrapped_call: Wrapped call function.
    expects_training_arg: Whether to include 'training' argument.
    default_training_value: Default value of the training kwarg to include in
      the arg spec. If `None`, the default is `K.learning_phase()`.

  Returns:
    Tuple of (
      function that calls `wrapped_call` and sets the training arg,
      Argspec of returned function or `None` if the argspec is unchanged)
  Nc                       t              t               }|xs t        j                         }t	                j                          fdt        j                  |fdfd      S )z<Wrap the `wrapped_call` function, and set training argument.c                 0    t        |         i S rE   )set_training_arg)trainingr   r   training_arg_indexwrapped_calls    r   replace_training_and_callzYmaybe_add_training_arg.<locals>.wrap_with_training_arg.<locals>.replace_training_and_call   s"    x!3T6B4*6**r    c                        d      S NT rV   s   r   <lambda>zHmaybe_add_training_arg.<locals>.wrap_with_training_arg.<locals>.<lambda>   s    3D9 r    c                        d      S NFrY   rZ   s   r   r[   zHmaybe_add_training_arg.<locals>.wrap_with_training_arg.<locals>.<lambda>   s    )%0 r    )get_training_arg_indexget_training_argKlearning_phaserA   copyr   
smart_cond)r   r   rS   rV   rT   r,   r.   rU   s   `` @@r   wrap_with_training_argz6maybe_add_training_arg.<locals>.wrap_with_training_arg   sm    /> 2D&AH'=1+;+;+=h:D[[]F+ ''902 2r    rS   )r   varargsvarkwdefaults
kwonlyargskwonlydefaultsannotations)r   getfullargspecrg   rA   rh   ri   r   appendindexlenFullArgSpecre   rf   rj   )r.   rU   r-   r,   rd   r/   rg   rh   ri   rm   training_default_indexr#   s   `` `        r   r'   r'      s0   & 
2( &&}5((0(9(9(ET(##$2(""***0b.x}}$j!!7N:MM
+E /%7H"88(()1*@h&&' ,,==NN#&&( 
 !2	22r    c                 *   t        j                  |       }|j                  rd|j                  v s|j                  ryy|j
                  }t        j                  |       r|dd }d|v r|j                  d      S d|j                  v s|j                  ryy)ab  Returns the index of 'training' in the layer call function arguments.

  Args:
    call_fn: Call function.

  Returns:
    - n: index of 'training' in the call function arguments.
    - -1: if 'training' is not found in the arguments, but layer.call accepts
          variable keyword arguments
    - None: if layer doesn't expect a training argument.
  rS   Nr   )r   rk   re   rh   rf   r   ismethodrm   )r+   argspecarg_lists      r   r^   r^      s     %%g.'__W'''7== ||H7#!"hX^^J''	w))	)W]]r    c                 P    ||dk  st        |      |k  r	| |d<   ||fS | ||<   ||fS Nr   rS   )rn   )rS   rm   r   r   s       r   rR   rR      sC    
]eai3t9#5!F: 
v DK	vr    c                 Z    | | dk  st        |      | k  r|j                  dd       S ||    S rw   )rn   getrm   r   r   s      r   r_   r_      s3    
]eai3t9#5::j$'';r    c                 v    | | dk  st        |      | k  r|j                  dd        y |j                  |        y rw   )rn   r5   rz   s      r   remove_training_argr|      s1    
]eai3t9#5
JJz4 HHUOr    c                        e Zd Z fdZ xZS )SaveOptionsContextc                 8    t         t        |           d| _        y rX   )superr~   __init__save_traces)self	__class__s    r   r   zSaveOptionsContext.__init__   s    	
d,.Dr    )__name__
__module____qualname__r   __classcell__)r   s   @r   r~   r~      s     r    r~   c              #      K   t         j                  }	 | t         _        d  |t         _        y # |t         _        w xY wwrE   _save_options_contextr   )r   previous_values     r   keras_option_scoper     s4     (44.7(3%	(6%%s   ?/ ?<?c                  "    t         j                  S )zHWhether to trace layer functions-can be disabled in the save_traces arg.r   rY   r    r   should_save_tracesr     s    		*	**r    c              #   d   K   t        | dd      }d| _        	 d || _        y# || _        w xY ww)a  A context that disables automatic dependency tracking when assigning attrs.

  Objects that inherit from Autotrackable automatically creates dependencies
  to trackable objects through attribute assignments, and wraps data structures
  (lists or dicts) with trackable classes. This scope may be used to temporarily
  disable this behavior. This works similar to the decorator
  `no_automatic_dependency_tracking`.

  Example usage:
  ```
  model = tf.keras.Model()
  model.arr1 = []  # Creates a ListWrapper object
  with no_automatic_dependency_tracking_scope(model):
    model.arr2 = []  # Creates a regular, untracked python list
  ```

  Args:
    obj: A trackable object.

  Yields:
    a scope in which the object doesn't track dependencies.
  _setattr_trackingTFN)r6   r   )rB   r   s     r   &no_automatic_dependency_tracking_scoper     s7     0 3 3T:.#+	*CNCs   0$ 0	-0r]   )%__doc__rK   	threadingr)   tensorflow.python.eagerr   tensorflow.python.kerasr   r`   tensorflow.python.keras.enginer   tensorflow.python.keras.utilsr   r   r   +tensorflow.python.keras.utils.generic_utilsr	   tensorflow.python.utilr
   globalsr   r1   r$   r4   rF   r'   r^   rR   r_   r|   localr~   r   contextmanagerr   r   r   rY   r    r   <module>r      s    R    + 0 ; ; 7 4 B / GI-/ =A#(8v"JB3J>  +,  7 7+
 + +r    