o
    i 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   ]/var/www/myenv/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|||_n,|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   	autograph
tf_convert_funcr   convert_variables_to_tensorsr   r   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/   r1   r3   r   r   
wrapped_fn   s   zUStructuredFunctionWrapper.__init__.<locals>.trace_legacy_function.<locals>.wrapped_fnc                      s    S r4   r   r   r9   r   r   <lambda>   s    zSStructuredFunctionWrapper.__init__.<locals>.trace_legacy_function.<locals>.<lambda>)r	   Defunr   get_flat_tensor_typesr$   )defun_kwargsr8   r:   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
   convert_to_tensor.0tr   r   r   
<listcomp>       zaStructuredFunctionWrapper.__init__.<locals>.trace_py_function.<locals>.unused.<locals>.<listcomp>r5   r7   r8   r   r   unused      zMStructuredFunctionWrapper.__init__.<locals>.trace_py_function.<locals>.unused	func_namerI   F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   rA   r   rB   rD   r   r   r   rG      rH   znStructuredFunctionWrapper.__init__.<locals>.trace_py_function.<locals>.py_function_wrapper.<locals>.<listcomp>)	r   r#   r$   r   r'   r   r   r6   r*   )r-   r.   r/   r1   r   r   py_function_wrapper   s   
zZStructuredFunctionWrapper.__init__.<locals>.trace_py_function.<locals>.py_function_wrapper)rO   r%   rP   c                     s   t  | tjS r4   )r   eager_py_funcr   r=   r*   )r-   )rR   r1   r   r   r9      s   
zQStructuredFunctionWrapper.__init__.<locals>.trace_py_function.<locals>.wrapped_fn)popr   Functionr   get_flat_tensor_specsr$   get_concrete_functionr	   )r>   rI   rK   tf_functionr   r9   r8   )rR   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   rA   r   rB   rD   r   r   r   rG      rH   zeStructuredFunctionWrapper.__init__.<locals>.trace_tf_function.<locals>.wrapped_fn.<locals>.<listcomp>r5   r7   r8   r   r   r9      rJ   zQStructuredFunctionWrapper.__init__.<locals>.trace_tf_function.<locals>.wrapped_fnrK   r9   FrL   )rT   r   rU   r   rV   r$   rW   )r>   r9   rK   rX   r8   r   r   trace_tf_function   s   
z=StructuredFunctionWrapper.__init__.<locals>.trace_tf_functionrK   _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   convert_legacy_structurer$   element_specr'   lenreplacejoinr   get_func_nameautograph_ctxcontrol_status_ctxupdatestrr
   uidr   
DEBUG_MODEr   functions_run_eagerlywarningswarn	_functionr   executing_eagerlyadd_to_graphget_default_graphseedgraph
_seed_used)r1   funcr2   datasetinput_classesinput_shapesinput_typesinput_structurero   use_legacy_functionr>   readable_transformation_namerK   symbolr?   rY   rZ   
fn_factoryouter_graph_seedr   )r   r1   r2   r3   r   __init__F   s   ,

-



z"StructuredFunctionWrapper.__init__c                 C      | j S r4   )r*   rQ   r   r   r   output_structure     z*StructuredFunctionWrapper.output_structurec                 C      t dd | jS )Nc                 S      |   S r4   )_to_legacy_output_classescomponent_specr   r   r   r;   $      z:StructuredFunctionWrapper.output_classes.<locals>.<lambda>r   map_structurer*   rQ   r   r   r   output_classes!     z(StructuredFunctionWrapper.output_classesc                 C   r   )Nc                 S   r   r4   )_to_legacy_output_shapesr   r   r   r   r;   *  r   z9StructuredFunctionWrapper.output_shapes.<locals>.<lambda>r   rQ   r   r   r   output_shapes'  r   z'StructuredFunctionWrapper.output_shapesc                 C   r   )Nc                 S   r   r4   )_to_legacy_output_typesr   r   r   r   r;   0  r   z8StructuredFunctionWrapper.output_types.<locals>.<lambda>r   rQ   r   r   r   output_types-  r   z&StructuredFunctionWrapper.output_typesc                 C   r   r4   )rm   rQ   r   r   r   r	   3  r   z"StructuredFunctionWrapper.function)NNNNNTFN)__name__
__module____qualname____doc__r   propertyr   r   r   r   r	   r   r   r   r   r   C   s,    
 X



r   )r   rk    tensorflow.python.autograph.corer   rd    tensorflow.python.autograph.implr   r%   tensorflow.python.data.opsr   tensorflow.python.data.utilr   r   tensorflow.python.eagerr   r   tensorflow.python.frameworkr	   r
   tensorflow.python.opsr   tensorflow.python.utilr   r   r   r   r   r   r   r   r   <module>   s"   