o
    ?e1                     @   s   d 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 ddlmZ ddlmZ ddlmZ ddlmZ dd Zdd ZG dd dZdS )z6Utilities for managing tf.data user-defined functions.    N)ag_ctx)api)
debug_mode)nest)	structure)context)def_function)function)ops)
script_ops)function_utils)variable_utilsc                 C   s
   t | tS )a   Determines whether the caller needs to pack the argument in a tuple.

  If user-defined function returns a list of tensors, `nest.flatten()` and
  `ops.convert_to_tensor()` and would conspire to attempt to stack those tensors
  into a single tensor because the tf.data version of `nest.flatten()` does
  not recurse into lists. Since it is more likely that the list arose from
  returning the result of an operation (such as `tf.numpy_function()`) that
  returns a list of not-necessarily-stackable tensors, we treat the returned
  value as a `tuple` instead. A user wishing to pack the return value into a
  single tensor can use an explicit `tf.stack()` before returning.

  Args:
    arg: argument to check

  Returns:
    Indication of whether the caller needs to pack the argument in a tuple.
  )
isinstancelistarg r   o/home/www/facesmatcher.com/pyenv/lib/python3.10/site-packages/tensorflow/python/data/ops/structured_function.py_should_pack"   s   
r   c                 C   s   t | tu S )zDetermines whether the caller needs to unpack the argument from a tuple.

  Args:
    arg: argument to check

  Returns:
    Indication of whether the caller needs to unpack the argument from a tuple.
  )typetupler   r   r   r   _should_unpack7   s   	r   c                   @   sf   e Zd ZdZ								dddZedd Zed	d
 Zedd Zedd Z	edd Z
dS )StructuredFunctionWrapperzHA function wrapper that supports structured arguments and return values.NTFc                    s<  |du r6|du r!|du s|du s|du rt dt|||_qM|du r-|du r-|du s1t d|j_n|du rF|du rF|du rF|du sJt d|_|_|
du rVi }
tdkrfdddd nd}d|t	
|g}d	D ]}||d}qtt   fd
dfdd}fdd}fdd}|	r|
d|d tt  i ||
}n#|
d|i |
ddi tjr||
}nt rtd ||
}| _|t  M }||	O }|rjt  |	st j}|rjjj|krjjjrtjd||f dd dS dS dS dS dS )a1  Creates a new `StructuredFunctionWrapper` for the given function.

    Args:
      func: A function from a (nested) structure to another (nested) structure.
      transformation_name: Human-readable name of the transformation in which
        this function is being instantiated, for error messages.
      dataset: (Optional.) A `tf.data.Dataset`. If given, the structure of this
        dataset will be assumed as the structure for `func` arguments; otherwise
        `input_classes`, `input_shapes`, and `input_types` must be defined.
      input_classes: (Optional.) A (nested) structure of `type`. If given, this
        argument defines the Python types for `func` arguments.
      input_shapes: (Optional.) A (nested) structure of `tf.TensorShape`. If
        given, this argument defines the shapes and structure for `func`
        arguments.
      input_types: (Optional.) A (nested) structure of `tf.DType`. If given,
        this argument defines the element types and structure for `func`
        arguments.
      input_structure: (Optional.) A `Structure` object. If given, this argument
        defines the element types and structure for `func` arguments.
      add_to_graph: (Optional.) If `True`, the function will be added to the
        default graph, if it exists.
      use_legacy_function: (Optional.) A boolean that determines whether the
        function be created using `tensorflow.python.eager.function.defun`
        (default behavior) or `tensorflow.python.framework.function.Defun`
        (legacy behavior).
      defun_kwargs: (Optional.) A dictionary mapping string argument names to
        values. If supplied, will be passed to `function` as keyword arguments.

    Raises:
      ValueError: If an invalid combination of `dataset`, `input_classes`,
        `input_shapes`, and `input_types` is passed.
    NzsEither `dataset`, `input_structure` or all of `input_classes`, `input_shapes`, and `input_types` must be specified.ztEither `dataset`, `input_structure`, or all of `input_classes`, `input_shapes`, and `input_types` must be specified.   ._ )<>\' c               
      s   t j| }t|s|f}tj | }t|}t	|r$t
|}z	t |_W |S  ttfyG } ztd d| d|d}~ww )zDWrapper for passing nested structures to and from tf.data functions.z1Unsupported return value from function passed to z: r   N)r   from_compatible_tensor_list_input_structurer   	autographZ
tf_convert_funcr   Zconvert_variables_to_tensorsr   r   Ztype_spec_from_value_output_structure
ValueError	TypeError)argsnested_argsrete)r   selftransformation_namer   r   wrapper_helper   s,   
z:StructuredFunctionWrapper.__init__.<locals>.wrapper_helperc                    s2   t jtji | fdd  fddS )Nc                     s   |  }t  j|S Nr   to_tensor_listr'   r*   r,   r.   r0   r   r   
wrapped_fn   s   zUStructuredFunctionWrapper.__init__.<locals>.trace_legacy_function.<locals>.wrapped_fnc                      s    S r1   r   r   r6   r   r   <lambda>   s    zSStructuredFunctionWrapper.__init__.<locals>.trace_legacy_function.<locals>.<lambda>)r	   ZDefunr   get_flat_tensor_typesr$   )defun_kwargsr5   r7   r   trace_legacy_function   s
   zAStructuredFunctionWrapper.__init__.<locals>.trace_legacy_functionc                    sv   fdd}|  dd}tj||tjd| d}| }fdd tjtjd| d	 fd
d}|jS )Nc                     $   |  }t  j|}dd |D S )Nc                 S      g | ]}t |qS r   r
   Zconvert_to_tensor.0tr   r   r   
<listcomp>       zaStructuredFunctionWrapper.__init__.<locals>.trace_py_function.<locals>.unused.<locals>.<listcomp>r2   r4   r5   r   r   unused      zMStructuredFunctionWrapper.__init__.<locals>.trace_py_function.<locals>.unused	func_namerD   FZpython_functionnameinput_signaturer%   experimental_attributesc                     sR   t  j| }t|s|f} j| }t|rt|}t  j|}dd |D S )Nc                 S   r=   r   r>   r?   r   r   r   rB      rC   znStructuredFunctionWrapper.__init__.<locals>.trace_py_function.<locals>.py_function_wrapper.<locals>.<listcomp>)	r   r#   r$   r   r&   r   r   r3   r'   )r*   r+   r,   r.   r   r   py_function_wrapper   s   
zZStructuredFunctionWrapper.__init__.<locals>.trace_py_function.<locals>.py_function_wrapper)rI   r%   rJ   c                     s   t  | tjS r1   )r   Zeager_py_funcr   r9   r'   )r*   )rL   r.   r   r   r6      s   
zQStructuredFunctionWrapper.__init__.<locals>.trace_py_function.<locals>.wrapped_fn)popr   Functionr   get_flat_tensor_specsr$   get_concrete_functionr	   )r:   rD   rF   tf_functionr   r6   r5   )rL   r   trace_py_function   s,   
z=StructuredFunctionWrapper.__init__.<locals>.trace_py_functionc                    s<    fdd}|  dd}tj||t jd| d}|jS )Nc                     r<   )Nc                 S   r=   r   r>   r?   r   r   r   rB      rC   zeStructuredFunctionWrapper.__init__.<locals>.trace_tf_function.<locals>.wrapped_fn.<locals>.<listcomp>r2   r4   r5   r   r   r6      rE   zQStructuredFunctionWrapper.__init__.<locals>.trace_tf_function.<locals>.wrapped_fnrF   r6   FrG   )rM   r   rN   r   rO   r$   rP   )r:   r6   rF   rQ   r5   r   r   trace_tf_function   s   
z=StructuredFunctionWrapper.__init__.<locals>.trace_tf_functionrF   Z_tf_data_functionTzEven though the `tf.config.experimental_run_functions_eagerly` option is set, this option does not apply to tf.data functions. To force eager execution of tf.data functions, please use `tf.data.experimental.enable_debug_mode()`.zSeed %s from outer graph might be getting used by function %s, if the random op has not been provided any seed. Explicitly set the seed in the function if this is not the intended behavior.   )
stacklevel)r(   r   Zconvert_legacy_structurer$   Zelement_specr&   lenreplacejoinr   Zget_func_nameautograph_ctxZcontrol_status_ctxupdatestrr
   uidr   Z
DEBUG_MODEr   Zfunctions_run_eagerlywarningswarn	_functionr   Zexecuting_eagerlyadd_to_graphZget_default_graphseedgraphZ
_seed_used)r.   funcr/   ZdatasetZinput_classesZinput_shapesZinput_typesZinput_structurer`   Zuse_legacy_functionr:   Zreadable_transformation_namerF   symbolr;   rR   rS   Z
fn_factoryZouter_graph_seedr   )r   r.   r/   r0   r   __init__F   s   ,


-



z"StructuredFunctionWrapper.__init__c                 C      | j S r1   )r'   rK   r   r   r   output_structure     z*StructuredFunctionWrapper.output_structurec                 C      t dd | jS )Nc                 S      |   S r1   )Z_to_legacy_output_classesZcomponent_specr   r   r   r8   $      z:StructuredFunctionWrapper.output_classes.<locals>.<lambda>r   Zmap_structurer'   rK   r   r   r   output_classes!     z(StructuredFunctionWrapper.output_classesc                 C   ri   )Nc                 S   rj   r1   )Z_to_legacy_output_shapesrk   r   r   r   r8   *  rl   z9StructuredFunctionWrapper.output_shapes.<locals>.<lambda>rm   rK   r   r   r   output_shapes'  ro   z'StructuredFunctionWrapper.output_shapesc                 C   ri   )Nc                 S   rj   r1   )Z_to_legacy_output_typesrk   r   r   r   r8   0  rl   z8StructuredFunctionWrapper.output_types.<locals>.<lambda>rm   rK   r   r   r   output_types-  ro   z&StructuredFunctionWrapper.output_typesc                 C   rf   r1   )r_   rK   r   r   r   r	   3  rh   z"StructuredFunctionWrapper.function)NNNNNTFN)__name__
__module____qualname____doc__re   propertyrg   rn   rp   rq   r	   r   r   r   r   r   C   s,    
 X



r   )ru   r]   Z tensorflow.python.autograph.corer   rY   Z tensorflow.python.autograph.implr   r%   Ztensorflow.python.data.opsr   Ztensorflow.python.data.utilr   r   Ztensorflow.python.eagerr   r   Ztensorflow.python.frameworkr	   r
   Ztensorflow.python.opsr   Ztensorflow.python.utilr   r   r   r   r   r   r   r   r   <module>   s"   