B
    ѻd;                 @   s   d Z ddlZddlZddlmZ edZG dd deZedZ	edZ
d	d
 Zdd Zd"ddZedddddgZi Zg Zd#ddZdd Zdd Zdd Zdd Zd d! ZdS )$zSerialization Registration for SavedModel.

revived_types registration will be migrated to this infrastructure.

See the Advanced saving section in go/savedmodel-configurability.
This API is approved for TF internal use only.
    N)
tf_inspectz^[a-zA-Z0-9._-]+$c               @   sX   e Zd ZdZdZdd Zedd Zdd Zd	d
 Z	dd Z
dd Zdd Zdd ZdS )_PredicateRegistrya  Registry with predicate-based lookup.

  See the documentation for `register_checkpoint_saver` and
  `register_serializable` for reasons why predicates are required over a
  class-based registry.

  Since this class is used for global registries, each object must be registered
  to unique names (an error is raised if there are naming conflicts). The lookup
  searches the predicates in reverse order, so that later-registered predicates
  are executed first.
  )_registry_name_registered_map_registered_predicates_registered_namesc             C   s   || _ i | _i | _g | _d S )N)r   r   r   r   )selfname r
   i/var/www/html/venv/lib/python3.7/site-packages/tensorflow/python/saved_model/registration/registration.py__init__/   s    z_PredicateRegistry.__init__c             C   s   | j S )N)r   )r   r
   r
   r   r	   8   s    z_PredicateRegistry.namec          
   C   s   t |trt |ts8td| j dt| dt| t|sZtd| j dt| |d | }t|std| j dtj	 d	| d
| d	|| j
krtd| d| j d| j
|  || j
|< || j|< | j| dS )zCRegisters a candidate object under the package, name and predicate.z%The package and name registered to a z must be strings, got: package=z, name=zThe predicate registered to a z must be callable, got: .zInvalid registered z;. Please check that the package and name follow the regex 'z': (package='z	', name='z')z
The name 'z#' has already been registered to a z	. Found: N)
isinstancestr	TypeErrorr	   typecallable_VALID_REGISTERED_NAMEmatch
ValueErrorpatternr   r   r   append)r   packager	   	predicate	candidateregistered_namer
   r
   r   register<   s     "
$
 

z_PredicateRegistry.registerc             C   s   | j | | S )aR  Looks up the registered object using the predicate.

    Args:
      obj: Object to pass to each of the registered predicates to look up the
        registered object.
    Returns:
      The object registered with the first passing predicate.
    Raises:
      LookupError if the object does not match any of the predicate functions.
    )r   get_registered_name)r   objr
   r
   r   lookupU   s    z_PredicateRegistry.lookupc          	   C   s<   y
| j | S  tk
r6   td| j d| dY nX dS )z9Looks up the registered object using the registered name.zThe z registry does not have name 'z' registered.N)r   KeyErrorLookupErrorr	   )r   r   r
   r
   r   name_lookupb   s    
z_PredicateRegistry.name_lookupc             C   sJ   x(t | jD ]}| j| }||r|S qW td| j dt| dd S )NzCould not find matching z for r   )reversedr   r   r!   r	   r   )r   r   r   r   r
   r
   r   r   j   s
    
z&_PredicateRegistry.get_registered_namec          	   C   s<   y
| j | S  tk
r6   td| j d| dY nX d S )NzThe z registry does not have name 'z' registered.)r   r    r!   r	   )r   r   r
   r
   r   get_predicateq   s    
z _PredicateRegistry.get_predicatec             C   s   | j S )N)r   )r   r
   r
   r   get_registrationsx   s    z$_PredicateRegistry.get_registrationsN)__name__
__module____qualname____doc__	__slots__r   propertyr	   r   r   r"   r   r$   r%   r
   r
   r
   r   r       s   	r   zserializable classzcheckpoint saverc             C   s$   y
t | S  tk
r   d S X d S )N)_class_registryr   r!   )r   r
   r
   r   get_registered_class_name   s    
r-   c             C   s$   y
t | S  tk
r   d S X d S )N)r,   r"   r!   )r   r
   r
   r   get_registered_class   s    
r.   Customc                s    fdd}|S )aq  Decorator for registering a serializable class.

  THIS METHOD IS STILL EXPERIMENTAL AND MAY CHANGE AT ANY TIME.

  Registered classes will be saved with a name generated by combining the
  `package` and `name` arguments. When loading a SavedModel, modules saved with
  this registered name will be created using the `_deserialize_from_proto`
  method.

  By default, only direct instances of the registered class will be saved/
  restored with the `serialize_from_proto`/`deserialize_from_proto` methods. To
  extend the registration to subclasses, use the `predicate argument`:

  ```python
  class A(tf.Module):
    pass

  register_serializable(
      package="Example", predicate=lambda obj: isinstance(obj, A))(A)
  ```

  Args:
    package: The package that this class belongs to.
    name: The name to serialize this class under in this package. If None, the
      class's name will be used.
    predicate: An optional function that takes a single Trackable argument, and
      determines whether that object should be serialized with this `package`
      and `name`. The default predicate checks whether the object's type exactly
      matches the registered class. Predicates are executed in the reverse order
      that they are added (later registrations are checked first).

  Returns:
    A decorator that registers the decorated class with the passed names and
    predicate.
  c                sR   t  std dk	r$n j}dkr> fddt|   S )z3Registers a class with the serialization framework.z+Registered serializable must be a class: {}Nc                s
   t |  S )N)r   )x)argr
   r   <lambda>       z:register_serializable.<locals>.decorator.<locals>.<lambda>)r   isclassr   formatr&   r,   r   )r1   
class_name)r	   r   r   )r1   r   	decorator   s    
z(register_serializable.<locals>.decoratorr
   )r   r	   r   r7   r
   )r	   r   r   r   register_serializable   s    $r8   RegisteredSaverr	   r   save_fn
restore_fnTc             C   sN   t |stdt| t |s4tdt| t| |||||f dS )a  Registers functions which checkpoints & restores objects with custom steps.

  If you have a class that requires complicated coordination between multiple
  objects when checkpointing, then you will need to register a custom saver
  and restore function. An example of this is a custom Variable class that
  splits the variable across different objects and devices, and needs to write
  checkpoints that are compatible with different configurations of devices.

  The registered save and restore functions are used in checkpoints and
  SavedModel.

  Please make sure you are familiar with the concepts in the [Checkpointing
  guide](https://www.tensorflow.org/guide/checkpoint), and ops used to save the
  V2 checkpoint format:

  * io_ops.SaveV2
  * io_ops.MergeV2Checkpoints
  * io_ops.RestoreV2

  **Predicate**

  The predicate is a filter that will run on every `Trackable` object connected
  to the root object. This function determines whether a `Trackable` should use
  the registered functions.

  Example: `lambda x: isinstance(x, CustomClass)`

  **Custom save function**

  This is how checkpoint saving works normally:
  1. Gather all of the Trackables with saveable values.
  2. For each Trackable, gather all of the saveable tensors.
  3. Save checkpoint shards (grouping tensors by device) with SaveV2
  4. Merge the shards with MergeCheckpointV2. This combines all of the shard's
     metadata, and renames them to follow the standard shard pattern.

  When a saver is registered, Trackables that pass the registered `predicate`
  are automatically marked as having saveable values. Next, the custom save
  function replaces steps 2 and 3 of the saving process. Finally, the shards
  returned by the custom save function are merged with the other shards.

  The save function takes in a dictionary of `Trackables` and a `file_prefix`
  string. The function should save checkpoint shards using the SaveV2 op, and
  list of the shard prefixes. SaveV2 is currently required to work a correctly,
  because the code merges all of the returned shards, and the `restore_fn` will
  only be given the prefix of the merged checkpoint. If you need to be able to
  save and restore from unmerged shards, please file a feature request.

  Specification and example of the save function:

  ```
  def save_fn(trackables, file_prefix):
    # trackables: A dictionary mapping unique string identifiers to trackables
    # file_prefix: A unique file prefix generated using the registered name.
    ...
    # Gather the tensors to save.
    ...
    io_ops.SaveV2(file_prefix, tensor_names, shapes_and_slices, tensors)
    return file_prefix  # Returns a tensor or a list of string tensors
  ```

  The save function is executed before the unregistered save ops.

  **Custom restore function**

  Normal checkpoint restore behavior:
  1. Gather all of the Trackables that have saveable values.
  2. For each Trackable, get the names of the desired tensors to extract from
     the checkpoint.
  3. Use RestoreV2 to read the saved values, and pass the restored tensors to
     the corresponding Trackables.

  The custom restore function replaces steps 2 and 3.

  The restore function also takes a dictionary of `Trackables` and a
  `merged_prefix` string. The `merged_prefix` is different from the
  `file_prefix`, since it contains the renamed shard paths. To read from the
  merged checkpoint, you must use `RestoreV2(merged_prefix, ...)`.

  Specification:

  ```
  def restore_fn(trackables, merged_prefix):
    # trackables: A dictionary mapping unique string identifiers to Trackables
    # merged_prefix: File prefix of the merged shard names.

    restored_tensors = io_ops.restore_v2(
        merged_prefix, tensor_names, shapes_and_slices, dtypes)
    ...
    # Restore the checkpoint values for the given Trackables.
  ```

  The restore function is executed after the non-registered restore ops.

  Args:
    package: Optional, the package that this class belongs to.
    name: (Required) The name of this saver, which is saved to the checkpoint.
      When a checkpoint is restored, the name and package are used to find the
      the matching restore function. The name and package are also used to
      generate a unique file prefix that is passed to the save_fn.
    predicate: (Required) A function that returns a boolean indicating whether a
      `Trackable` object should be checkpointed with this function. Predicates
      are executed in the reverse order that they are added (later registrations
      are checked first).
    save_fn: (Required) A function that takes a dictionary of trackables and a
      file prefix as the arguments, writes the checkpoint shards for the given
      Trackables, and returns the list of shard prefixes.
    restore_fn: (Required) A function that takes a dictionary of trackables and
      a file prefix as the arguments and restores the trackable values.
    strict_predicate_restore: If this is `True` (default), then an error will be
      raised if the predicate fails during checkpoint restoration. If this is
      `True`, checkpoint restoration will skip running the restore function.
      This value is generally set to `False` when the predicate does not pass on
      the Trackables after being saved/loaded from SavedModel.

  Raises:
    ValueError: if the package and name are already registered.
  z#The save_fn must be callable, got: z&The restore_fn must be callable, got: N)r   r   r   _saver_registryr   )r   r	   r   r:   r;   Zstrict_predicate_restorer
   r
   r   register_checkpoint_saver   s    |r=   c             C   s$   y
t | S  tk
r   dS X dS )z?Returns the name of the registered saver to use with Trackable.N)r<   r   r!   )	trackabler
   r
   r   get_registered_saver_nameK  s    
r?   c             C   s   t | d S )z)Returns save function registered to name.r   )r<   r"   )r   r
   r
   r   get_save_functionS  s    r@   c             C   s   t | d S )z,Returns restore function registered to name.   )r<   r"   )r   r
   r
   r   get_restore_functionX  s    rB   c             C   s   t | d S )zHReturns if the registered restore can be ignored if the predicate fails.   )r<   r"   )r   r
   r
   r   get_strict_predicate_restore]  s    rD   c          	   C   sb   yt | W n* tk
r8   td|  d| dY nX t || s^td|  d| ddS )aJ  Validates whether the trackable can be restored with the saver.

  When using a checkpoint saved with a registered saver, that same saver must
  also be also registered when loading. The name of that saver is saved to the
  checkpoint and set in the `registered_name` arg.

  Args:
    trackable: A `Trackable` object.
    registered_name: String name of the expected registered saver. This argument
      should be set using the name saved in a checkpoint.

  Raises:
    ValueError if the saver could not be found, or if the predicate associated
      with the saver does not pass.
  zError when restoring object zH from checkpoint. This object was saved using a registered saver named 'z9', but this saver cannot be found in the current context.zObject z, was saved with the registered saver named 'z`'. However, this saver cannot be used to restore the object because the predicate does not pass.N)r<   r"   r!   r   r$   )r>   r   r
   r
   r   validate_restore_functionb  s    rE   )r/   NN)r/   NNNNT)r)   collectionsreZtensorflow.python.utilr   compiler   objectr   r,   r<   r-   r.   r8   
namedtupler9   Z_REGISTERED_SAVERSZ_REGISTERED_SAVER_NAMESr=   r?   r@   rB   rD   rE   r
   r
   r
   r   <module>   s4   
[
3     
 