B
    һd"                 @   s  d Z ddlZddlZddlZddlZddl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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$ a%dZ&e 'ej(e 'ej)e 'ej*fZ+dd Z,e-ddd Z.dd Z/dd Z0dd  Z1G d!d" d"e2Z3e#d#e&d$ddfd%d&Z4e#d'd(d) Z5dS )*z>Dumping op callbacks: Enables dump-based features in tfdbg v2.    N)
tensor_pb2)debug_event_pb2)graph_debug_info_pb2)debug_events_writer)op_callbacks_common)source_utils)function)constant_op)dtypes)op_callbacks)ops)tensor_util)	array_ops)gen_debug_ops)
tf_logging)compat)tf_stack)	tf_export	NO_TENSORc             C   s   t | tS )N)r   as_bytes
startswith_FUNCTION_PREFIXES)op_type r   ^/var/www/html/venv/lib/python3.7/site-packages/tensorflow/python/debug/lib/dumping_callback.pyis_op_type_function7   s    r   ZDebugIdentityV2c             C   s   ~ |S )z-Gradient function for the DebugIdentityV2 op.r   )opZdyr   r   r   _debug_identity_v2_grad;   s    r   c               C   s   t t d d S )N   )struuiduuid4r   r   r   r   _get_tfdbg_run_idB   s    r"   c               C   s   t t S )zGet a short unique ID.)r   r    r!   r   r   r   r   _get_idF   s    r#   c             C   s   t |  S )N)r   Zmake_tensor_protonumpy)tensorr   r   r   _concrete_tensor_to_protoK   s    r&   c               @   s   e Zd ZdZdd Zdd Zedd Zejdd Zed	d
 Z	e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d Zd*ddZd+d d!Zd"d# Zd$d% Zd&d' Zd(d) ZdS ),_DumpingCallbackz>An object holding the states surrounding the dumping callback.c             C   s   || _ t | _|| _|| _|| _|| _t | _	g | _
t | _t | _t | _t | _d| _t | _t | _t | _t | _t | _t | _d | _d S )Nr   )
_dump_rootr"   _tfdbg_run_id_tensor_debug_mode_circular_buffer_size	_op_regex_tensor_dtypessocketgethostname	_hostname_source_file_pathsdict_stack_frame_to_id_context_to_id_function_to_graph_id_op_type_to_context_id_symbolic_tensor_counter_tensor_aliases	threadingLock_source_file_paths_lock_stack_frame_to_id_lock_context_lock_symbolic_tensor_counter_lock_placeholder_to_debug_tensor_writer)self	dump_roottensor_debug_modecircular_buffer_sizeop_regextensor_dtypesr   r   r   __init__R   s(    




z_DumpingCallback.__init__c          	   C   s0   ~~~|  |}| j || j|< W dQ R X dS )a  A callback to be called on creation of Functions.

    Used to establish a join between function name and graph (context) ID.

    Args:
      function: The just-created Function.
      name: Name of the function.
      graph: FuncGraph, the graph containing the operations in the function.
      inputs: the tensors in the graph to be used as inputs to the function
      outputs: the tensors in the graph which will be outputs from the function
    N)_get_context_idr=   r5   )rA   r   namegraphinputsoutputsgraph_idr   r   r   function_callbackz   s    
z"_DumpingCallback.function_callbackc             C   s   | j S )N)r(   )rA   r   r   r   rB      s    z_DumpingCallback.dump_rootc             C   s   | j |kr|| _ d | _d S )N)r(   r@   )rA   rB   r   r   r   rB      s    
c             C   s   | j S )N)r)   )rA   r   r   r   tfdbg_run_id   s    z_DumpingCallback.tfdbg_run_idc             C   s   | j S )N)r*   )rA   r   r   r   rC      s    z"_DumpingCallback.tensor_debug_modec             C   s   | j S )N)r+   )rA   r   r   r   rD      s    z%_DumpingCallback.circular_buffer_sizec             C   s$   | j stj| j| j| jd| _ | j S )zCGet the debug events writer for the currently configured dump root.)rD   )r@   r   DebugEventsWriterr(   r)   r+   )rA   r   r   r   
get_writer   s    z_DumpingCallback.get_writerc          	   C   s~   || j kr| j | S d}| j$ || j kr>d}t }|| j |< W dQ R X |rt|  tj|t|dd| |d | j | S )a  Get a unique ID for an op-construction context (e.g., a graph).

    If the graph has been encountered before, reuse the same unique ID.
    When encountering a new context (graph), this methods writes a DebugEvent
    proto with the debugged_graph field to the proper DebugEvent file.

    Args:
      context: A context to get the unique ID for. Must be hashable. E.g., a
        Graph object.

    Returns:
      A unique ID for the context.
    FTNrI   )rM   
graph_nameZouter_context_id)	r4   r=   r#   rQ   ZWriteDebuggedGraphr   ZDebuggedGraphgetattr_get_outer_context_id)rA   contextZgraph_is_new
context_idr   r   r   rH      s    



z _DumpingCallback._get_context_idc             C   s$   t |dr|jr| |jS dS dS )a:  Get the ID of the immediate outer context of the input graph.

    Args:
      graph: The graph (context) in question.

    Returns:
      If an outer context exists, the immediate outer context name as a string.
      If such as outer context does not exist (i.e., `graph` is itself
      outermost), `None`.
    outer_graphN)hasattrrW   rH   )rA   rJ   r   r   r   rT      s    z&_DumpingCallback._get_outer_context_idc             C   s   || j kr| j |S | j || j krd}t|rzyt|\}}W n0 tk
rx } ztd|| W dd}~X Y nX | 	 }|
tj|| j|d | j | | j |S Q R X dS )zSend the content of a source file via debug-events writer.

    Args:
      file_path: Path to the source file.

    Returns:
      An int index for the file.
    Nz4Failed to read source code from path: %s. Reason: %s)	file_path	host_namelines)r1   indexr;   r   Z%is_extension_uncompiled_python_sourceZload_sourceIOErrorloggingwarnrQ   ZWriteSourceFiler   Z
SourceFiler0   append)rA   rY   r[   _ewriterr   r   r   _write_source_file_content   s"    	


z+_DumpingCallback._write_source_file_contentc          
   C   s   t  }g }d}x|D ]\}}}}tj|}|||f| jkrV|| j|||f  q| j~ |||f| jkrt }	|	| j|||f< | 	|}
t
jj|
||d}tj|	|d}|  }|| || j|||f  W dQ R X qW tj| j|d}|S )zProcess stack frames.

    Send the content of source-files, on a best-effort basis.

    Returns:
      A list of stack frame IDs.
    N)
file_indexlinefunc)idfile_line_col)rZ   stack_frame_ids)r   extract_stackospathabspathr3   r`   r<   r#   rd   r   ZGraphDebugInfoZFileLineColr   ZStackFrameWithIdrQ   ZWriteStackFrameWithIdZCodeLocationr0   )rA   Zstack_framesrj   rc   rY   linenorg   ra   abs_pathZstack_frame_idre   ri   Zstack_frame_with_idcode_locationr   r   r   _process_stack_frames   s2    


 z&_DumpingCallback._process_stack_framesc          	   C   s   |dkr|| j |< |S |tjjkr<|dkr<|j| j|j< |S | j d| j }W dQ R X tj	||d}|j
|j
 |j| j|j< |S dS )a  For V1 graph mode, determine what tensor to output from callback.

    Args:
      op_type: Type of the op that outputs the original symbolic tensor.
      tensor: The original output symbolic tensor.
      debug_tensor: The debugger-instrumented tensor.
      tensor_debug_mode: Debug mode used, a tfdbg TensorDebugMode enum.

    Returns:
      A symbolic tensor to be returned by the dumping op_callback.
    )PlaceholderPlaceholderWithDefaultConstztfdbg_identity_%dN)rI   )r?   r   TensorDebugModeFULL_TENSORrI   r8   r>   r7   r   identityr   _add_control_input)rA   r   r%   debug_tensorrC   Zidentity_namerx   r   r   r   _process_v1_graph_mode_tensor  s    
z._DumpingCallback._process_v1_graph_mode_tensorc          
   C   sH  | j }d| j g}t  }|r$g nd}	xt|D ]
\}
}| j d| j }W dQ R X |||
| j ||| j| jd}|t	j
jkr| ||jr|jjs|r4|	| q4|r|jjs|	| q4tjtjg tjdf|}|r|	| |||| q4|t	j
jt	j
jt	j
jt	j
jfkr|j}|t	j
jt	j
jt	j
jfkrB|jpd|t	j
jkod|jpd|jpd|j}| ||jr||s|r4|	| q4tjtj|||
 | j tjdf|}|r@|	| |||| q4|t	j
j kr2| ||jr|jjs|r4|	| q4tj|f|}|r@|	| |||| q4t!d| j  q4W |	S )a  Add debugging instrumentation for symbolic (i.e., non-eager) tensors.

    The detailed fashion in which the tensors are instrumented is determined
    by the tensor_debug_mode configured for the currently enabled dumping
    callback.

    Args:
      tensors: A tuple of Tensors to instrument. It is assumed that their
        ordering corresponds to the ordering of output tensors of an original
        op. Output slot indices (0-based) will be generated based on the
        ordering.
      op_type: Type name of the op that emits the Tensors (e.g., "MatMul").
      op_name: Name of the op that emits the Tensors (e.g., "dense_1/MatMul").
      tfdbg_context_id: A unique ID for the context that the op belongs to
        (e.g., a graph).
      tensor_ids: A list of unique ID numbers for the tensors, for tfdbg's
        internal use.

    Returns:
      Non-eager Tensors that override the `tensors` as the output of the op
      that originally generated `tensors`. In some cases (e.g., non-V1 graph
      mode), this may be `None`, as the instrumentation can simply rely on
      automatic control dependencies (see `auto_control_deps.py`) instead of
      tensor overriding.
    z	file://%sNzDebugIdentityV2_%d)tfdbg_context_idop_nameoutput_slotrC   
debug_urlsrI   rD   rO   )dtype)Z	tensor_idrC   output_dtypezDSymbolic tensor instrumentation is not implemented for debug mode %s)"r*   r(   r   #executing_eagerly_outside_functions	enumerater>   r7   r+   r)   r   rv   r   _should_dump_tensorr   is_numpy_compatibler`   r   Zdebug_identity_v2r	   Zconstantr
   Zfloat32r{   CURT_HEALTHCONCISE_HEALTHFULL_HEALTHSHAPEis_floating
is_integeris_booldebug_numeric_summary_v2float64rw   NotImplementedError)rA   tensorsr   r}   r|   
tensor_idsrC   r   is_v1_graph_modeZinstrumented_tensorsr~   r%   Zdebug_identity_nameZdebug_identity_op_kwargsrz   r   Zdtype_is_dumpabler   r   r   _instrument_symbolic_tensorsH  s    







z-_DumpingCallback._instrument_symbolic_tensorsNc          
   C   s  | j }dd |D }t|t|ks(t|tjjkrVtj||t||||||  dS |tjjtjj	tjj
tjjtjjfkrtj|t|||||||  d}x|D ]}	| ||	jr|	jjr|tjjtjj	tjj
fkr|	jj rttj|	|tjd}
nt }
nd|tjjkrV|	jjs4|	jjs4|	jjrLttj|	|tjd}
nt }
n|tjjkrlt|	}
|
r|j|
 qW |S td| j  dS )a  Dump the value of eager tensors.

    The destination of the dumping is determined by the dump_root of the
    currently enabled dumping callback. The tensors may be transformed prior to
    dumping (e.g., reduced as summary statistics such as minimum, maximum and
    arithmetic  mean). The details of this transformation (if any) depends on
    the tensor_debug_mode of the currently enabled dumping callback.

    Args:
      tensors: The EagerTensors whose values are to be dumped, with or without
        value transform.
      op_type: Type of the op that generates the tensors, as a string.
      input_tensor_ids: IDs of the input EagerTensors to the op.
      output_tensor_device_ids: Debugged-generated IDs for the devices on which
        the output tensors are allocated, as a `list` of `int`s. Must match
        `tensors` in length.
      graph_id: ID of the executed graph, applicable only to eager execution of
        a FuncGraph.

    Returns:
      A tfdbg Execution protocol buffer.
    c             S   s   g | ]
}|j qS r   )_id).0tr   r   r   
<listcomp>  s    z8_DumpingCallback._dump_eager_tensors.<locals>.<listcomp>)r   rM   num_outputsinput_tensor_idsoutput_tensor_idsoutput_tensor_device_idsrC   rq   )r   r   rM   r   r   r   rC   rq   )rC   r   z@Tensor instrumentation is not implemented for debug mode %s yet N)r*   lenAssertionErrorr   rv   r   Z	Executionrr   r   r   r   r   rw   r   r   r   r   r&   r   r   r
   r   r   ZTensorProtor   r   Ztensor_protosr`   r   )rA   r   r   r   r   rM   rC   r   Zexecution_protor%   Ztensor_protor   r   r   _dump_eager_tensors  st    




z$_DumpingCallback._dump_eager_tensorsc          
      sp  ~   |rt  } |} t|}	|dkrL|d jdd }|rx2|D ]*}
|
 jkrV|rV|d j	
 j|
 j	 qVW tj||t|dr|jnd| fdd|D t||	  d}| |rt|tjkr |||||	S nvt|}|d	krdS |tjkrdS  |}d
d |D }|rNfdd|D ng } j|||||d dS )z;Op callback for tracing (dumping) a TF program's execution.)ru   rs   rt   r   :rI   Nc                s   g | ]}  |qS r   )_lookup_tensor_name)r   input_tensor)rA   r   r   r   :  s    z-_DumpingCallback.callback.<locals>.<listcomp>)r   r}   rR   rM   Zinput_namesr   r   rq   s   DebugNumericSummaryV2c             S   s   g | ]
}|j qS r   )r   )r   r   r   r   r   r   M  s    c                s   g | ]}  |jqS r   )ZRegisterDeviceAndGetIdZdevice)r   output)rc   r   r   r   N  s   )rM   )rQ   r   r   rH   _get_symbolic_tensor_idsr   rI   splitr?   r   ry   r   ZGraphOpCreationrX   rr   ZWriteGraphOpCreationr   r   r   ZOP_CALLBACK_SKIP_OPSr   _func_graph_id_from_func_nameZWriteExecutionr   )rA   r   rK   attrsrL   r}   rJ   r   rV   r   r   Zgraph_op_creationZop_type_bytesZ	input_idsr   r   )rA   rc   r   callback  sL    







z_DumpingCallback.callbackc             C   s   | j |j|jS )a  Look up the name of a graph tensor.

    This method maps the name of a debugger-generated Identity or
    DebugIdentityV2 tensor to the name of the original instrumented tensor,
    if `tensor` is such a debugger-created tensor.
    Otherwise, it returns the name of `tensor` as is.

    Args:
      tensor: The graph tensor to look up the name for.

    Returns:
      Name of the orignal instrumented tensor as known to the debugger.
    )r8   getrI   )rA   r%   r   r   r   r   T  s    z$_DumpingCallback._lookup_tensor_namec          	   C   sv   t |}t|rn|| jkr&| j| S | j8 x0| jD ]&}|j|kr6| j| }|| j|< |S q6W W dQ R X dS dS dS )a  Attempt to get the ID of a FuncGraph based on an op type name.

    Also caches the ID for faster access later.

    Args:
      op_type: Op type string, which may be the name of a function.

    Returns:
      If the op_type name does not fit the pattern of a function name (e.g.,
      one that starts with "__inference_"), `None` is returned immediately.
      Else, if the FuncGraph is found, ID of the underlying FuncGraph is
      returned as a string.
      Else, `None` is returned.
    N)r   r   r   r6   r=   r5   rI   )rA   r   r   rM   r   r   r   r   d  s    





z._DumpingCallback._func_graph_id_from_func_namec          	   C   sJ   g }|rF| j 2 x*t|D ]}|  jd7  _|| j qW W d Q R X |S )N   )r>   ranger7   r`   )rA   Znum_tensorsr   ra   r   r   r   r     s    z)_DumpingCallback._get_symbolic_tensor_idsc                sb   d}| j r|ot| j |}| jr^t| jttfrP|oLt fdd| jD }n|o\|  }|S )a}  Determine if the given tensor's value will be dumped.

    The determination is made given the configurations such as `op_regex`,
    `tensor_dtypes`.

    Args:
      op_type: Name of the op's type, as a string (e.g., "MatMul").
      dtype: The dtype of the tensor, as a `dtypes.DType` object.

    Returns:
      A bool indicating whether the tensor's value will be dumped.
    Tc             3   s   | ]} |kV  qd S )Nr   )r   
dtype_item)r   r   r   	<genexpr>  s    z7_DumpingCallback._should_dump_tensor.<locals>.<genexpr>)r,   rematchr-   
isinstancelisttupleany)rA   r   r   Zshould_dumpr   )r   r   r     s    z$_DumpingCallback._should_dump_tensor)N)NN)__name__
__module____qualname____doc__rG   rN   propertyrB   setterrO   rC   rD   rQ   rH   rT   rd   rr   r{   r   r   r   r   r   r   r   r   r   r   r   r'   O   s,   (	#+z
] 
4#	r'   z-debugging.experimental.enable_dump_debug_infoi  c             C   s  t j }||kr"td||f t j|}|t jjt jjt jjt jjt jj	t jj
fkrntdt j| |dk	rt|ttfst|std|f t|ttfrdd |D }ttdrtjj|krtdtjj|f tjj|krBtd	tjj|tjj || f n.t| ||||t_ttjj ttjj tjj| krX| tj_td
t ! j"tjjt j| t#$t% tj& S )a  Enable dumping debugging information from a TensorFlow program.

  The debugging information is dumped to a directory on the file system
  specified as `dump_root`.

  The dumped debugging information can be ingested by debugger UIs.

  The files in the dump directory contain the following information:
    - TensorFlow Function construction (e.g., compilation of Python functions
      decorated with @tf.function), the op types, names (if available), context,
      the input and output tensors, and the associated stack traces.
    - Execution of TensorFlow operations (ops) and Functions and their stack
      traces, op types, names (if available) and contexts. In addition,
      depending on the value of the `tensor_debug_mode` argument (see Args
      section below), the value(s) of the output tensors or more concise
      summaries of the tensor values will be dumped.
    - A snapshot of Python source files involved in the execution of the
      TensorFlow program.

  Once enabled, the dumping can be disabled with the corresponding
  `disable_dump_debug_info()` method under the same Python namespace.
  Calling this method more than once with the same `dump_root` is idempotent.
  Calling this method more than once with different `tensor_debug_mode`s
  leads to a `ValueError`.
  Calling this method more than once with different `circular_buffer_size`s
  leads to a `ValueError`.
  Calling this method with a different `dump_root` abolishes the
  previously-enabled `dump_root`.

  Usage example:

  ```py
  tf.debugging.experimental.enable_dump_debug_info('/tmp/my-tfdbg-dumps')

  # Code to build, train and run your TensorFlow model...
  ```

  NOTE: If your code is running on TPUs, be sure to call
  `tf.config.set_soft_device_placement(True)` before calling
  `tf.debugging.experimental.enable_dump_debug_info()` as this API uses
  automatic outside compilation on TPUs. For example:

  ```py
  tf.config.set_soft_device_placement(True)
  tf.debugging.experimental.enable_dump_debug_info(
      logdir, tensor_debug_mode="FULL_HEALTH")

  resolver = tf.distribute.cluster_resolver.TPUClusterResolver(tpu='')
  strategy = tf.distribute.TPUStrategy(resolver)
  with strategy.scope():
    # ...
  ```

  Args:
    dump_root: The directory path where the dumping information will be written.
    tensor_debug_mode: Debug mode for tensor values, as a string.
      The currently supported options are:
      - "NO_TENSOR": (Default) Only traces the output tensors of all executed
        ops (including those executed eagerly at the Python level or as a part
        of a TensorFlow graph) and functions, while not extracting any
        information from the values of the tensors.
      - "CURT_HEALTH": For each floating-dtype tensor (e.g., tensors of dtypes
        such as `float32`, `float64` and `bfloat16`), extracts a binary bit
        indicating whether it contains any -infinity, +infinity or NaN.
      - "CONCISE_HEALTH": For each floating-dtype tensor, extract total
        element count, and counts of -infinity, +infinity and NaN elements.
      - "FULL_HEALTH": For each floating-dtype tensor, extracts the dtype,
        rank (number of dimensions), total element count, and counts of
        -infinity, +infinity and NaN elements.
      - "SHAPE": For each tensor (regardless of dtype), extracts its dtype,
        rank, total element count and shape.
    circular_buffer_size: Size of the circular buffers for execution events.
      These circular buffers are designed to reduce the overhead of debugging
      dumping. They hold the most recent debug events concerning eager execution
      of ops and `tf.function`s and traces of tensor values computed inside
      `tf.function`s. They are written to the file system only when the proper
      flushing method is called (see description of return values below).
      Expected to be an integer. If <= 0, the circular-buffer behavior will be
      disabled, i.e., the execution debug events will be written to the file
      writers in the same way as non-execution events such as op creations and
      source-file snapshots.
    op_regex: Dump data from only the tensors from op types that matches to the
      regular expression (through Python's `re.match()`).
      "Op type" refers to the names of the TensorFlow operations (e.g.,
      "MatMul", "LogSoftmax"), which may repeat in a TensorFlow
      function. It does *not* refer to the names of nodes (e.g.,
      "dense/MatMul", "dense_1/MatMul_1") which are unique within a function.
      - Example 1: Dump tensor data from only MatMul and Relu ops
        `op_regex="^(MatMul|Relu)$"`.
      - Example 2: Dump tensors from all ops *except* Relu:
        `op_regex="(?!^Relu$)"`.
      This filter operates in a logical AND relation with `tensor_dtypes`.
    tensor_dtypes: Dump data from only the tensors of which the specified
      dtypes. This optional argument can be in any of the following format:
      - a list or tuple of `DType` objects or strings that can be converted
        to `DType` objects via `tf.as_dtype()`. Examples:
        - `tensor_dtype=[tf.float32, tf.float64]`,
        - `tensor_dtype=["float32", "float64"]`,
        - `tensor_dtypes=(tf.int32, tf.bool)`,
        - `tensor_dtypes=("int32", "bool")`
      - a callable that takes a single `DType` argument and returns a Python
        `boolean` indicating whether the dtype is to be included in the data
        dumping. Examples:
        - `tensor_dtype=lambda dtype: dtype.is_integer`.
      This filter operates in a logical AND relation with `op_regex`.
  Returns:
    A DebugEventsWriter instance used by the dumping callback. The caller
    may use its flushing methods, including `FlushNonExecutionFiles()` and
    `FlushExecutionFiles()`.
  z@Invalid value in tensor_debug_mode ('%s'). Valid options are: %szFtfdbg dumping: support for tensor debug mode %s is not implemented yetNzIf specified, tensor_dtypes is expected to be a list, a tuple, or a callable that takes a DType argument and returns a boolean, but received %sc             S   s   g | ]}t |qS r   )r
   Zas_dtype)r   r   r   r   r   r   @  s    z*enable_dump_debug_info.<locals>.<listcomp>dumping_callbackzThere is already a dumping callback configured with a different circular-buffer size (%d). Therefore the newly request circular-buffer size (%d) will not be honored.zThere is already a dumping callback configured for dump root %s with a different tensor-debug mode (%s). Therefore the newly request tensor-debug mode (%s) size will not be honored.zLEnabled dumping callback in thread %s (dump root: %s, tensor debug mode: %s))'r   rv   keys
ValueErrorValuer   r   r   r   r   rw   r   Namer   r   r   callablerX   _stater   rD   rC   rB   r'   r   Zadd_op_callbackr   function_libZadd_function_callbackrN   r^   infor9   current_threadrI   atexitregisterdisable_dump_debug_inforQ   )rB   rC   rD   rE   rF   Ztensor_debug_mode_keysr   r   r   enable_dump_debug_info  sf    y




r   z.debugging.experimental.disable_dump_debug_infoc              C   sh   t tdrdtjj} tjj}t| |  t	tjj
 ttjj ttd tdt j|  dS )aI  Disable the currently-enabled debugging dumping.

  If the `enable_dump_debug_info()` method under the same Python namespace
  has been invoked before, calling this method disables it. If no call to
  `enable_dump_debug_info()` has been made, calling this method is a no-op.
  Calling this method more than once is idempotent.
  r   z6Disabled dumping callback in thread %s (dump root: %s)N)rX   r   r   rB   rO   r   rP   Closer   Zremove_op_callbackr   r   Zremove_function_callbackrN   delattrr^   r   r9   r   rI   )rB   rO   r   r   r   r   j  s    	


r   )6r   r   rl   r   r.   r9   r    Ztensorflow.core.frameworkr   Ztensorflow.core.protobufr   r   Ztensorflow.python.debug.libr   r   r   Ztensorflow.python.eagerr   r   Ztensorflow.python.frameworkr	   r
   r   r   r   Ztensorflow.python.opsr   r   Ztensorflow.python.platformr   r^   Ztensorflow.python.utilr   r   Z tensorflow.python.util.tf_exportr   localr   ZDEFAULT_TENSOR_DEBUG_MODEr   Z_FORWARD_PREFIXZ_BACKWARD_PREFIXZ_INFERENCE_PREFIXr   r   ZRegisterGradientr   r"   r#   r&   objectr'   r   r   r   r   r   r   <module>   s\   

    ` ;