
    6biV                        S r SSKrSSKrSSKJs  Jr  SSKJr  SSKJ	r	  SSK
Jr  SqSrSr\R                  " 5       r\R                  " 5       q\R                  " 5       qS	 rS
 rS r " S S5      r " S S5      r " S S5      r " S S\5      r " S S5      r SS jr\R:                  S 5       r\" S5      S 5       r   S S jr \" S5         S S j5       r!S r"S r#g)!z/Legacy serialization logic for TF-Keras models.    N)tf_contextlib)
tf_inspect)keras_exportFzlayer was saved without configshared_object_idc                  $    [        [        SS5      $ )zFGet whether shared object handling is disabled in a threadsafe manner.disabledF)getattrSHARED_OBJECT_DISABLED     b/home/james-whalen/.local/lib/python3.13/site-packages/tf_keras/src/saving/legacy/serialization.py_shared_object_disabledr   4   s    ):u==r   c                  4    [        [        S[        5       5      $ )BGet the current shared object saving scope in a threadsafe manner.scope)r	   SHARED_OBJECT_LOADINGNoopLoadingScoper   r   r   _shared_object_loading_scoper   9   s    ('3C3EFFr   c                  $    [        [        SS5      $ )r   r   N)r	   SHARED_OBJECT_SAVINGr   r   r   _shared_object_saving_scoper   >   s    '$77r   c                   $    \ rS rSrSrS rS rSrg)DisableSharedObjectScopeC   zA 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    S[         l        [        5       U l        [	        5       U l        g NT)r
   r   r   _orig_loading_scoper   _orig_saving_scopeselfs    r   	__enter__"DisableSharedObjectScope.__enter__L   s!    *.'#?#A "="?r   c                 n    S[         l        U R                  [        l        U R
                  [        l        g )NF)r
   r   r   r   r   r   r   r    argskwargss      r   __exit__!DisableSharedObjectScope.__exit__Q   s)    */'&*&>&>#%)%<%<"r   )r   r   N)__name__
__module____qualname____firstlineno____doc__r!   r'   __static_attributes__r   r   r   r   r   C   s    @
=r   r   c                   $    \ rS rSrSrS rS rSrg)r   W   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                     g Nr   )r    unused_object_ids     r   getNoopLoadingScope.get^   s    r   c                     g r2   r   r    	object_idobjs      r   setNoopLoadingScope.seta   s    r   r   N)r)   r*   r+   r,   r-   r4   r:   r.   r   r   r   r   r   W   s    r   r   c                   0    \ rS rSrSrS rS rS rS rSr	g)	SharedObjectLoadingScopee   aC  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                 \    [        5       (       a
  [        5       $ U [        l        0 U l        U $ r2   )r   r   r   r   _obj_ids_to_objr   s    r   r!   "SharedObjectLoadingScope.__enter__n   s,    "$$#%% '+#!r   c                 @    Uc  gU R                   R                  U5      $ )zGiven 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)r@   r4   )r    r8   s     r   r4   SharedObjectLoadingScope.getw   s$     ##''	22r   c                 (    Uc  gX R                   U'   g)z<Stores an instantiated object for future lookup and sharing.Nr@   r7   s      r   r:   SharedObjectLoadingScope.set   s    *-Y'r   c                 *    [        5       [        l        g r2   )r   r   r   r$   s      r   r'   !SharedObjectLoadingScope.__exit__   s    &6&8#r   rE   N)
r)   r*   r+   r,   r-   r!   r4   r:   r'   r.   r   r   r   r=   r=   e   s    3 .9r   r=   c                   2   ^  \ rS rSrSrU 4S jrS rSrU =r$ )SharedObjectConfig   a  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   > SU l         X l        [        TU ]  " U40 UD6  g N   )	ref_countr8   super__init__)r    base_configr8   r&   	__class__s       r   rQ   SharedObjectConfig.__init__   s!    "//r   c                 t    U R                   S:X  a  U R                  U [        '   U =R                   S-  sl         g rM   )rO   r8   SHARED_OBJECT_KEYr   s    r   increment_ref_count&SharedObjectConfig.increment_ref_count   s-    
 >>Q&*nnD"#!r   )r8   rO   )	r)   r*   r+   r,   r-   rQ   rW   r.   __classcell__)rS   s   @r   rJ   rJ      s     0
 r   rJ   c                   0    \ rS rSrSrS rS rS rS rSr	g)	SharedObjectSavingScope   z6Keeps track of shared object configs when serializing.c                     [        5       (       a  g [        5       b  SU l        [        5       $ SU l        U [        l        [
        R                  " 5       U l        SU l        U $ )NTFr   )	r   r   _passthroughr   r   weakrefWeakKeyDictionary_shared_objects_config_next_idr   s    r   r!   !SharedObjectSavingScope.__enter__   sX    "$$ '(4 $D.00 %D%)"&-&?&?&A#r   c                 r     U R                   U   nUR                  5         U$ ! [        [        4 a     gf = f)zGets 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)ra   	TypeErrorKeyErrorrW   )r    r9   shared_object_configs      r   
get_config"SharedObjectSavingScope.get_config   sG    	#'#>#>s#C  	002## 8$ 	
 	s   # 66c                     [        XR                  5      nU =R                  S-  sl         X0R                  U'   U$ ! [         a     U$ f = f)z3Create a new SharedObjectConfig for a given object.rN   )rJ   rb   ra   re   )r    rR   r9   rg   s       r   create_config%SharedObjectSavingScope.create_config   sV    1+}}M	/C'', $#  	
 ##	s   < 
A
	A
c                 @    [        U SS5      (       d  S [        l        g g )Nr^   F)r	   r   r   r$   s      r   r'    SharedObjectSavingScope.__exit__   s    t^U33)- & 4r   )rb   r^   ra   N)
r)   r*   r+   r,   r-   r!   rh   rk   r'   r.   r   r   r   r[   r[      s    @,$*$.r   r[   c                     XS.nUb  X4[         '   [        5       b:  Ub7  [        5       R                  U5      nUc  [        5       R                  XB5      $ U$ U$ )z=Returns the serialization of the class with the given config.)
class_nameconfig)rV   r   rh   rk   )cls_name
cls_configr9   r   rR   rg   s         r    serialize_keras_class_and_configrt      sf     "*@K
 #)9%& #$0S_:<GGL'.0>>{PP##r   c               #   8   #    [         n  Sq S v   U q g ! U q f = f7fr   )_SKIP_FAILED_SERIALIZATION)prevs    r   skip_failed_serializationrx     s&      &D*%)"%)"T"s    z)keras.utils.legacy.serialize_keras_objectc                    SSK Jn  [        R                  R                  R                  U 5      u  p U c  g[        U S5      (       a  UR                  U R                  5      n U R                  5       n0 nUR                  5        H_  u  px[        U[         5      (       a  XU'   M    [#        U5      n	[        U	[$        5      (       a  [        U[$        5      (       d  SU	S'   XU'   Ma     UR                  U R                  5      n[        X6U 5      $ [        U S5      (       a  UR                  U 5      $ ['        SU  S	35      e! [         a)  n[        (       a  [        U[        S05      s SnA$ UeSnAff = f! [&         a	    XU'    GM  f = f)
a  Serialize a TF-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.
r   object_registrationNrh   T__passive_serialization__r)   zCannot serialize z- because it doesn't implement `get_config()`.)tf_keras.src.savingr{   tf__internal__	decoratorunwraphasattrget_registered_namerS   rh   NotImplementedErrorrv   rt   _LAYER_UNDEFINED_CONFIG_KEYitems
isinstancestrserialize_keras_objectdict
ValueError)
instancer{   _namerq   eserialization_configkeyitemserialized_items
             r   r   r     s    8//++228<KAx&&"66x7I7IJ	((*F  "IC$$$,0S)1"8">ot44Z$> > DHO$?@,;S) (" #66x7I7IJ/
 	
 x$$"66x@@

H: & 	 = # 	))76=  G	*  1,0S)1s6   #E  &>E6 
E3
E.&E3,E..E36F	F	c                    SSK Jn  [        U [        5      (       a  SU ;  d  SU ;  a  [	        SU  S35      eU S   nUR                  XRU5      nUc  [	        SU SU S	35      eU S   n[        U[        5      (       a  Xg4$ 0 nUR                  5        H  u  pU	S
:X  a  XU	'   M  [        U
[        5      (       a  SU
;   a  [        U
UUSS9X'   M<  [        U
[        5      (       d  MS  [        R                  " UR                  X5      5      (       d  M  UR                  X5      UU	'   M     UR                  5        H  u  pX   Xy'   M     Xg4$ )z@Returns the class name and config for a serialized keras object.r   rz   rp   rq   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/tf_keras/save_and_serialize#registering_the_custom_object for details.r   r|   config_item)module_objectscustom_objectsprintable_module_name)r}   r{   r   r   r   get_registered_objectlistr   deserialize_keras_objectr   r   
isfunction)rq   r   r   r   r{   rp   clsrs   deserialized_objectsr   r   s              r   ,class_and_config_for_serialized_keras_objectr   U  s    8 vt$$v%6!)& 2O O
 	

 %J

3
3NC {,-S =: :
 	
 !J *d##  %%'	&=
 )-%d##(Ct(K(@--&3	) % c""z'<'<55dK(
 (
 $99$O !7 (< *//1	.3
 2 r   z+keras.utils.legacy.deserialize_keras_objectc                     SSK Jn  U c  g[        U [        5      (       Ga;  U n[	        XQX#5      u  pgUR                  [        5      n[        5       R                  U5      n	U	b  U	$ [        US5      (       a  [        R                  " UR                  5      n
U=(       d    0 nSU
R                  ;   a7  UR                  R                  nUR                  U0 UR                  EUEUES9nOYUR!                  U5         UR                  U5      nSSS5        O-U=(       d    0 nUR!                  U5         U" S0 UD6nSSS5        [        5       R#                  UW5        U$ [        U [$        5      (       a  U nU(       a  X;   a  UR                  U5      nOyUUR                  R                  ;   a  UR                  R                  U   nOEXR                  ;   a  UR                  U   nO&UR                  U5      nUc  ['        SU SU S	35      e[        R(                  " U5      (       a  U" 5       $ U$ [        R*                  " U 5      (       a  U $ ['        S
U SU  35      e! , (       d  f       GN+= f! , (       d  f       GN== f)a>  Turns the serialized form of a TF-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 TF-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.
r   rz   Nfrom_configr   )r   r   r   r   zCould not interpret serialized z: r   )r}   r{   r   r   r   r4   rV   r   r   r   getfullargspecr   r%   _THREAD_LOCAL_CUSTOM_OBJECTS__dict___GLOBAL_CUSTOM_OBJECTSCustomObjectScoper:   r   r   isclassr   )
identifierr   r   r   r{   rq   r   rs   r   shared_objectarg_spectlcodeserialized_objobject_namer9   s                  r   r   r     s   j 8*d##HN
 "::&7846::;KL$  3&&!00AH+1rN8==0*GGPP#&??$-DD$$ )$ $3 $  )::>J'*z'B$ KJ ,1rN$66~F#&#4#4  G 	%&**+;=MN	J	$	$ k; $$[1C"??HHI &BBKKC FFF%<<[IC $$[1C{ 45S F# #  c""5L
			z	*	*-$%R
|5
 	
e KJ GFs   8I/	I.
I+.
I=c                 B    [        U [        5      =(       a	    [        U ;  $ )z=Determines whether config appears to be a valid layer config.)r   r   r   )rq   s    r   validate_configr   3  s     	64 N%@%Nr   c                     [        U SS5      $ )z:Check if a method is decorated with the `default` wrapper._is_defaultF)r	   )methods    r   
is_defaultr   :  s    6=%00r   )NN)NNobject)$r-   	threadingr_   tensorflow.compat.v2compatv2r~   tf_keras.src.utilsr   r    tensorflow.python.util.tf_exportr   rv   r   rV   localr
   r   r   r   r   r   r   r   r=   r   rJ   r[   rt   contextmanagerrx   r   r   r   r   r   r   r   r   <module>r      s*   6   ! ! , ) :
 #  ?  ' "* !)  ( >
G
8
= =( *9 *9Z @?. ?.F 6:2 * * 9:9 ;9| "	L^ ;< "	K
 =K
\1r   