B
    ٻd2                 @   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 ede dZede dZede dZdd Zdd ZG dd dZdS )z6Utilities for managing tf.data user-defined functions.    N)nest)	structure)context)def_function)function)ops)
script_ops)function_utils)lazy_loader)variable_utils	autographz$tensorflow.python.autograph.impl.apiautograph_ctxz'tensorflow.python.autograph.core.ag_ctxdataset_opsz&tensorflow.python.data.ops.dataset_opsc             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/html/venv/lib/python3.7/site-packages/tensorflow/python/data/ops/structured_function.py_should_pack,   s    r   c             C   s   t | tk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tuple)r   r   r   r   _should_unpackA   s    	r   c               @   sV   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                s8  |dkrl|dkrB|dks(|dks(|dkr0t dt|||_q|dkrZ|dkrZ|dksbt d|j_n.|dkr|dkr|dkr|dkst d|_|_|
dkri }
tdkr̈dddd nd}d|t	
|g}xd	D ]}||d}qW t   fd
dfdd}fdd}fdd}|	rn|
d|d tt  i ||
}nJ|
d|i |
ddi tjr||
}nt rtd ||
}| _|t  M }||	O }|rjt  |	s4t j}|r4jjj|kr4jjjr4tjd||f dd 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	|rHt
|}yt |_W n> ttfk
r } ztd d| d|W dd}~X Y nX |S )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   r   Z
tf_convert_funcr   Zconvert_variables_to_tensorsr   r   Ztype_spec_from_value_output_structure
ValueError	TypeError)argsnested_argsrete)ag_ctxselftransformation_namer   r   wrapper_helper   s    

z:StructuredFunctionWrapper.__init__.<locals>.wrapper_helperc                s.   t jtj| 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 )Nr   r   )r2   r   r   <lambda>       zSStructuredFunctionWrapper.__init__.<locals>.trace_legacy_function.<locals>.<lambda>)r   ZDefunr   get_flat_tensor_typesr$   )defun_kwargs)r.   r0   )r2   r   trace_legacy_function   s    zAStructuredFunctionWrapper.__init__.<locals>.trace_legacy_functionc                sf   t jtjd| dfdd}| }fdd t jtjd| d fdd}|jS )	NF)input_signaturer   
attributesc                 s$   |  }t  j|}dd |D S )Nc             S   s   g | ]}t |qS r   )r   convert_to_tensor).0tr   r   r   
<listcomp>   s    zaStructuredFunctionWrapper.__init__.<locals>.trace_py_function.<locals>.unused.<locals>.<listcomp>)r   r1   r&   )r)   r+   )r.   r0   r   r   unused   s    zMStructuredFunctionWrapper.__init__.<locals>.trace_py_function.<locals>.unusedc                 sR   t  j| }t|s|f} j| }t|r6t|}t  j|}dd |D S )Nc             S   s   g | ]}t |qS r   )r   r:   )r;   r<   r   r   r   r=      s    znStructuredFunctionWrapper.__init__.<locals>.trace_py_function.<locals>.py_function_wrapper.<locals>.<listcomp>)	r   r#   r$   r   r%   r   r   r1   r&   )r)   r*   r+   )r.   r   r   py_function_wrapper   s    

zZStructuredFunctionWrapper.__init__.<locals>.trace_py_function.<locals>.py_function_wrapperc                 s   t  | tjS )N)r   Zeager_py_funcr   r5   r&   )r)   )r?   r.   r   r   r2      s    zQStructuredFunctionWrapper.__init__.<locals>.trace_py_function.<locals>.wrapped_fn)eager_functiondefun_with_attributesr   get_flat_tensor_specsr$   get_concrete_function)r6   r>   r   r2   )r.   r0   )r?   r   trace_py_function   s    z=StructuredFunctionWrapper.__init__.<locals>.trace_py_functionc                s,   t jt jd| d fdd}|jS )NF)r8   r   r9   c                 s$   |  }t  j|}dd |D S )Nc             S   s   g | ]}t |qS r   )r   r:   )r;   r<   r   r   r   r=      s    zeStructuredFunctionWrapper.__init__.<locals>.trace_tf_function.<locals>.wrapped_fn.<locals>.<listcomp>)r   r1   r&   )r)   r+   )r.   r0   r   r   r2      s    zQStructuredFunctionWrapper.__init__.<locals>.trace_tf_function.<locals>.wrapped_fn)r@   rA   r   rB   r$   rC   )r6   r2   )r.   r0   r   r   trace_tf_function   s    z=StructuredFunctionWrapper.__init__.<locals>.trace_tf_function	func_nameZ_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_namer   Z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_structurerR   Zuse_legacy_functionr6   Zreadable_transformation_namerF   symbolr7   rD   rE   Z
fn_factoryZouter_graph_seedr   )r-   r.   r/   r0   r   __init__P   sh    ,
$

'



z"StructuredFunctionWrapper.__init__c             C   s   | j S )N)r&   )r.   r   r   r   output_structure  s    z*StructuredFunctionWrapper.output_structurec             C   s   t dd | jS )Nc             S   s   |   S )N)Z_to_legacy_output_classes)component_specr   r   r   r3   "  r4   z:StructuredFunctionWrapper.output_classes.<locals>.<lambda>)r   map_structurer&   )r.   r   r   r   output_classes  s    z(StructuredFunctionWrapper.output_classesc             C   s   t dd | jS )Nc             S   s   |   S )N)Z_to_legacy_output_shapes)rY   r   r   r   r3   (  r4   z9StructuredFunctionWrapper.output_shapes.<locals>.<lambda>)r   rZ   r&   )r.   r   r   r   output_shapes%  s    z'StructuredFunctionWrapper.output_shapesc             C   s   t dd | jS )Nc             S   s   |   S )N)Z_to_legacy_output_types)rY   r   r   r   r3   .  r4   z8StructuredFunctionWrapper.output_types.<locals>.<lambda>)r   rZ   r&   )r.   r   r   r   output_types+  s    z&StructuredFunctionWrapper.output_typesc             C   s   | j S )N)rQ   )r.   r   r   r   r   1  s    z"StructuredFunctionWrapper.function)NNNNNTFN)__name__
__module____qualname____doc__rW   propertyrX   r[   r\   r]   r   r   r   r   r   r   M   s          
 Br   )ra   rO   Ztensorflow.python.data.utilr   r   Ztensorflow.python.eagerr   r   r   r@   Ztensorflow.python.frameworkr   Ztensorflow.python.opsr   Ztensorflow.python.utilr	   r
   r   
LazyLoaderglobalsr   r   r   r   r   r   r   r   r   r   <module>   s0   