
    2Vh0U                        d Z ddlZddlZddlZddlZddlZddlmZ ddlm	Z	 da
dZdZ ej                         Z ej                         a ej                         ad Zd	 Zd
 Z G d d      Z G d d      Z G d d      Z G d de      Z G d d      Z	 d!dZej6                  d        Z eddg      d        Z	 	 	 d"dZ eddg      	 	 	 d"d       Zd Z d Z!d  Z"y)#z,Legacy serialization logic for Keras models.    N)keras_export)object_registrationFzlayer was saved without configshared_object_idc                  $    t        t        dd      S )zFGet whether shared object handling is disabled in a threadsafe manner.disabledF)getattrSHARED_OBJECT_DISABLED     U/home/dcms/DCMS/lib/python3.12/site-packages/keras/src/legacy/saving/serialization.py_shared_object_disabledr   %   s    ):u==r   c                  4    t        t        dt                     S )BGet the current shared object saving scope in a threadsafe manner.scope)r   SHARED_OBJECT_LOADINGNoopLoadingScoper
   r   r   _shared_object_loading_scoper   *   s    ('3C3EFFr   c                  $    t        t        dd      S )r   r   N)r   SHARED_OBJECT_SAVINGr
   r   r   _shared_object_saving_scoper   /   s    '$77r   c                       e Zd ZdZd Zd Zy)DisableSharedObjectScopezA context manager for disabling handling of shared objects.

    Disables shared object handling for both saving and loading.

    Created primarily for use with `clone_model`, which does extra surgery that
    is incompatible with shared objects.
    c                 V    dt         _        t               | _        t	               | _        y NT)r	   r   r   _orig_loading_scoper   _orig_saving_scopeselfs    r   	__enter__z"DisableSharedObjectScope.__enter__=   s!    *.'#?#A "="?r   c                 n    dt         _        | j                  t        _        | j
                  t        _        y )NF)r	   r   r   r   r   r   r   r   argskwargss      r   __exit__z!DisableSharedObjectScope.__exit__B   s)    */'&*&>&>#%)%<%<"r   N)__name__
__module____qualname____doc__r   r$   r
   r   r   r   r   4   s    @
=r   r   c                       e Zd ZdZd Zd Zy)r   zThe default shared object loading scope. It does nothing.

    Created to simplify serialization code that doesn't care about shared
    objects (e.g. when serializing a single object).
    c                      y Nr
   )r   unused_object_ids     r   getzNoopLoadingScope.getO   s    r   c                      y r+   r
   r   	object_idobjs      r   setzNoopLoadingScope.setR   s    r   N)r%   r&   r'   r(   r-   r2   r
   r   r   r   r   H   s    r   r   c                   (    e Zd ZdZd Zd Zd Zd Zy)SharedObjectLoadingScopeaW  A context manager for keeping track of loaded objects.

    During the deserialization process, we may come across objects that are
    shared across multiple layers. In order to accurately restore the network
    structure to its original state, `SharedObjectLoadingScope` allows us to
    re-use shared objects rather than cloning them.
    c                 R    t               r
t               S | t        _        i | _        | S r+   )r   r   r   r   _obj_ids_to_objr   s    r   r   z"SharedObjectLoadingScope.__enter___   s)    "$#%% '+#!r   c                 >    |y| j                   j                  |      S )a  Given a shared object ID, returns a previously instantiated object.

        Args:
          object_id: shared object ID to use when attempting to find
            already-loaded object.

        Returns:
          The object, if we've seen this ID before. Else, `None`.
        N)r6   r-   )r   r0   s     r   r-   zSharedObjectLoadingScope.geth   s$     ##''	22r   c                 (    |y|| j                   |<   y)z<Stores an instantiated object for future lookup and sharing.N)r6   r/   s      r   r2   zSharedObjectLoadingScope.setx   s    *-Y'r   c                 *    t               t        _        y r+   )r   r   r   r!   s      r   r$   z!SharedObjectLoadingScope.__exit__~   s    &6&8#r   N)r%   r&   r'   r(   r   r-   r2   r$   r
   r   r   r4   r4   V   s    3 .9r   r4   c                   (     e Zd ZdZ fdZd Z xZS )SharedObjectConfiga  A configuration container that keeps track of references.

    `SharedObjectConfig` will automatically attach a shared object ID to any
    configs which are referenced more than once, allowing for proper shared
    object reconstruction at load time.

    In most cases, it would be more proper to subclass something like
    `collections.UserDict` or `collections.Mapping` rather than `dict` directly.
    Unfortunately, python's json encoder does not support `Mapping`s. This is
    important functionality to retain, since we are dealing with serialization.

    We should be safe to subclass `dict` here, since we aren't actually
    overriding any core methods, only augmenting with a new one for reference
    counting.
    c                 B    d| _         || _        t        |   |fi | y N   )	ref_countr0   super__init__)r   base_configr0   r#   	__class__s       r   rA   zSharedObjectConfig.__init__   s#    "//r   c                 r    | j                   dk(  r| j                  | t        <   | xj                   dz  c_         y r=   )r?   r0   SHARED_OBJECT_KEYr   s    r   increment_ref_countz&SharedObjectConfig.increment_ref_count   s-    
 >>Q&*nnD"#!r   )r%   r&   r'   r(   rA   rF   __classcell__)rC   s   @r   r;   r;      s     0
r   r;   c                   (    e Zd ZdZd Zd Zd Zd Zy)SharedObjectSavingScopez6Keeps track of shared object configs when serializing.c                     t               ry t               d| _        t               S d| _        | t        _        t        j                         | _        d| _        | S )NTFr   )	r   r   _passthroughr   r   weakrefWeakKeyDictionary_shared_objects_config_next_idr   s    r   r   z!SharedObjectSavingScope.__enter__   sU    "$ '(4 $D.00 %D%)"&-&?&?&A#r   c                 p    	 | j                   |   }|j                          |S # t        t        f$ r Y yw xY w)a  Gets a `SharedObjectConfig` if one has already been seen for `obj`.

        Args:
          obj: The object for which to retrieve the `SharedObjectConfig`.

        Returns:
          The SharedObjectConfig for a given object, if already seen. Else,
            `None`.
        N)rN   	TypeErrorKeyErrorrF   )r   r1   shared_object_configs      r   
get_configz"SharedObjectSavingScope.get_config   sG    	#'#>#>s#C  	002## 8$ 	
 	s   # 55c                     t        || j                        }| xj                  dz  c_        	 || j                  |<   |S # t        $ r Y |S w xY w)z3Create a new SharedObjectConfig for a given object.r>   )r;   rO   rN   rQ   )r   rB   r1   rS   s       r   create_configz%SharedObjectSavingScope.create_config   sZ    1+t}}M	/CD'', $#  	
 ##	s   > 	A
Ac                 6    t        | dd      sd t        _        y y )NrK   F)r   r   r   r!   s      r   r$   z SharedObjectSavingScope.__exit__   s    t^U3)- & 4r   N)r%   r&   r'   r(   r   rT   rV   r$   r
   r   r   rI   rI      s    @,$*$.r   rI   c                     | |d}|	||t         <   t               9|7t               j                  |      }|t               j                  ||      S |S |S )z=Returns the serialization of the class with the given config.)
class_nameconfig)rE   r   rT   rV   )cls_name
cls_configr1   r   rB   rS   s         r    serialize_keras_class_and_configr]      sl     "*Z@K
 #)9%& #$0S_:<GGL'.0>>{CPP##r   c               #   8   K   t         } 	 da d  | a y # | a w xY wwr   )_SKIP_FAILED_SERIALIZATION)prevs    r   skip_failed_serializationra      s'      &D*%)"%)"T"s    z*keras.legacy.saving.serialize_keras_objectz)keras.utils.legacy.serialize_keras_objectc                    t        j                  |       } | yt        | d      rt        j                  | j
                        }	 | j                         }i }|j                         D ]Q  \  }}t        |t              r|||<   	 t        |      }t        |t              rt        |t              sd|d<   |||<   S t        j                  | j
                        }t        |||       S t        | d      rt        j                  |       S t!        d|  d      # t        $ r$}t        rt        |t        di      cY d}~S |d}~ww xY w# t         $ r |||<   Y w xY w)a  Serialize a Keras object into a JSON-compatible representation.

    Calls to `serialize_keras_object` while underneath the
    `SharedObjectSavingScope` context manager will cause any objects re-used
    across multiple layers to be saved with a special shared object ID. This
    allows the network to be re-created properly during deserialization.

    Args:
      instance: The object to serialize.

    Returns:
      A dict-like, JSON-compatible representation of the object's config.
    NrT   T__passive_serialization__r%   zCannot serialize z- because it doesn't implement `get_config()`.)inspectunwraphasattrr   get_registered_namerC   rT   NotImplementedErrorr_   r]   _LAYER_UNDEFINED_CONFIG_KEYitems
isinstancestrserialize_keras_objectdict
ValueError)instancenamerZ   eserialization_configkeyitemserialized_items           r   rm   rm   	  s}   , ~~h'Hx&"66x7I7IJ	((*F  " 	1IC$$,0$S)1"8">ot4Z$> DHO$?@,;$S)	1" #66x7I7IJ/&
 	
 x$"66x@@

H: & 	 = # 	)76=  G	*  1,0$S)1s6   D 5E	E D?7E=D??EEEc                 j   t        | t              rd| vsd| vrt        d|  d      | d   }t        j                  |||      }|t        d| d| d      | d   }t        |t
              r||fS i }|j                         D ]  \  }}	|dk(  r|	||<   t        |	t              rd	|	v rt        |	||d
      ||<   8t        |	t              sIt        j                  t        j                  |	|            sst        j                  |	|      ||<    |j                         D ]  \  }}	||   ||<    ||fS )z@Returns the class name and config for a serialized keras object.rY   rZ   zImproper config format for zB. Expecting python dict contains `class_name` and `config` as keysUnknown : ''. Please ensure you are using a `keras.utils.custom_object_scope` and that this object is included in the scope. See https://www.tensorflow.org/guide/keras/save_and_serialize#registering_the_custom_object for details.rq   rc   config_item)module_objectscustom_objectsprintable_module_name)rk   rn   ro   r   get_registered_objectlistrj   deserialize_keras_objectrl   rd   
isfunction)
rZ   r|   r}   r~   rY   clsr\   deserialized_objectsrt   ru   s
             r   ,class_and_config_for_serialized_keras_objectr   K  s    vt$v%6!)& 2O O
 	

 %J

3
3NNC {,-S =: :
 	
 !J *d#Z  %%' 	T&=
 )- %d#(Ct(K(@--&3	) % c"w'9'955dNK(
 $99$O !%7< *//1 4	T.s3
34 r   z,keras.legacy.saving.deserialize_keras_objectz+keras.utils.legacy.deserialize_keras_objectc                    | yt        | t              r/| }t        ||||      \  }}|j                  t              }t               j                  |      }||S t        |d      rt        j                  |j                        }	|xs i }t        |dd      }d|	j                  v r&|j                  |i t        j                  |      }
n\t        j                  |      5  |j                  |      }
ddd       n,|xs i }t        j                  |      5   |di |}
ddd       t               j                  |
       |
S t        | t               r| }|r||v r|j                  |      }n|t        j"                  j$                  v rt        j"                  j$                  |   }nK|t        j&                  v rt        j&                  |   }n%|j                  |      }|t)        d| d| d      t        j*                  |      r |       S |S t        j,                  |       r| S t)        d	| d
|        # 1 sw Y   xY w# 1 sw Y   (xY w)a  Turns the serialized form of a Keras object back into an actual object.

    This function is for mid-level library implementers rather than end users.

    Importantly, this utility requires you to provide the dict of
    `module_objects` to use for looking up the object config; this is not
    populated by default. If you need a deserialization utility that has
    preexisting knowledge of built-in Keras objects, use e.g.
    `keras.layers.deserialize(config)`, `keras.metrics.deserialize(config)`,
    etc.

    Calling `deserialize_keras_object` while underneath the
    `SharedObjectLoadingScope` context manager will cause any already-seen
    shared objects to be returned as-is rather than creating a new object.

    Args:
      identifier: the serialized form of the object.
      module_objects: A dictionary of built-in objects to look the name up in.
        Generally, `module_objects` is provided by midlevel library
        implementers.
      custom_objects: A dictionary of custom objects to look the name up in.
        Generally, `custom_objects` is provided by the end user.
      printable_module_name: A human-readable string representing the type of
        the object. Printed in case of exception.

    Returns:
      The deserialized object.

    Example:

    A mid-level library implementer might want to implement a utility for
    retrieving an object from its config, as such:

    ```python
    def deserialize(config, custom_objects=None):
       return deserialize_keras_object(
         identifier,
         module_objects=globals(),
         custom_objects=custom_objects,
         name="MyObjectType",
       )
    ```

    This is how e.g. `keras.layers.deserialize()` is implemented.
    Nfrom_configzkeras.r}   )r}   rx   ry   rz   zCould not interpret serialized z: r
   )rk   rn   r   r-   rE   r   rf   rd   getfullargspecr   _find_replace_nested_dictr"   r   GLOBAL_CUSTOM_OBJECTSCustomObjectScoper2   rl   _THREAD_LOCAL_CUSTOM_OBJECTS__dict___GLOBAL_CUSTOM_OBJECTSro   isclassr   )
identifierr|   r}   r~   rZ   r   r\   r   shared_objectarg_specdeserialized_objobject_namer1   s                r   r   r     s   t *d#HNN4I
j "::&7846::;KL$  3&--coo>H+1rN 3HhJ  8==0#&??$-CC$($ $3 $  )::>J C'*z'B$C C ,1rN$66~F 5#&#4#4 5 	%&**+;=MN	J	$ k^; $$[1C"??HHI &BBKKC /FFF%<<[IC $$[1C{ 45S FB B  ??35L
			J	'-$%R
|5
 	
cC C5 5s   !H9	I9IIc                 6    t        | t              xr t        | vS )z=Determines whether config appears to be a valid layer config.)rk   rn   ri   )rZ   s    r   validate_configr   .  s     	64 N%@%Nr   c                     t        | dd      S )z:Check if a method is decorated with the `default` wrapper._is_defaultF)r   )methods    r   
is_defaultr   5  s    6=%00r   c                 ~    t        j                  |       }|j                  ||      }t        j                  |      } | S r+   )jsondumpsreplaceloads)rZ   findr   dict_strs       r   r   r   :  s5    zz&!Hg.HZZ!FMr   )NN)NNobject)#r(   
contextlibrd   r   	threadingrL   keras.src.api_exportr   keras.src.savingr   r_   ri   rE   localr	   r   r   r   r   r   r   r   r4   rn   r;   rI   r]   contextmanagerra   rm   r   r   r   r   r   r
   r   r   <module>r      sG   2      . 0
 #  ?  ' (* '	) &y( >
G
8
= =( *9 *9Z @?. ?.F 6:2 * * 4399| "	K\ 65 "	L
L
^1
r   