B
    һdK5                 @   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	 ej
ej
ej
ej
ej
ej
eZej
ejZdZ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dZdS )zJClasses and functions that help to inspect Python source w.r.t. TF graphs.    N)	profilingz.py)z.pycz.pyoc             C   s   t jt j| S )N)ospathnormpathabspath)	file_path r   Z/var/www/html/venv/lib/python3.7/site-packages/tensorflow/python/debug/lib/source_utils.py_norm_abs_path'   s    r
   c             C   s   t j| \}}| tkS )N)r   r   splitextlowerUNCOMPILED_SOURCE_SUFFIXES)r   _	extensionr   r   r	   %is_extension_uncompiled_python_source+   s    r   c             C   s   t j| \}}| tkS )N)r   r   r   r   COMPILED_SOURCE_SUFFIXES)r   r   r   r   r   r	   #is_extension_compiled_python_source0   s    r   c             C   s   | d |  d S )N:)rfind)	watch_keyr   r   r	   !_convert_watch_key_to_tensor_name5   s    r   c             C   sT   t | st| sdS t| } | ts0| toR| d oRtj	dtj	| kS )a  Guess whether a Python source file is a part of the tensorflow library.

  Special cases:
    1) Returns False for unit-test files in the library (*_test.py),
    2) Returns False for files under python/debug/examples.

  Args:
    py_file_path: full path of the Python source file in question.

  Returns:
    (`bool`) Whether the file is inferred to be a part of the tensorflow
      library.
  Fz_test.pyz tensorflow/python/debug/examples)
r   r   r
   
startswith_TENSORFLOW_BASEDIR_ABSL_BASEDIRendswithr   r   r   )Zpy_file_pathr   r   r	   guess_is_tensorflow_py_library9   s    


r   c          	   C   s|   t j| r<t| d}| d}W dQ R X |d}nt| }|dkrXtd|  t	t
t
t|d }||fS )a  Load the content of a Python source code file.

  This function covers the following case:
    1. source_file_path points to an existing Python (.py) file on the
       file system.
    2. source_file_path is a path within a .par file (i.e., a zip-compressed,
       self-contained Python executable).

  Args:
    source_file_path: Path to the Python source file to read.

  Returns:
    A length-2 tuple:
      - Lines of the source file, as a `list` of `str`s.
      - The width of the string needed to show the line number in the file.
        This is calculated based on the number of lines in the source file.

  Raises:
    IOError: if loading is unsuccessful.
  rbzutf-8N
z?Source path neither exists nor can be loaded as a .par file: %s   )r   r   isfileopenreaddecodesplit_try_load_par_sourceIOErrorintnpceillog10len)source_file_pathfsource_textZsource_linesZline_num_widthr   r   r	   load_sourceR   s    r.   c          
   C   s   | }xt j|\}}|sP t jt jj| |d}|drt j|rt|X}dd |	 D }||kr|
|	 || }| d}|dS Q R X W dQ R X qW dS )a[  Try loading the source code inside a .par file.

  A .par file is a zip-compressed, self-contained Python executable.
  It contains the content of individual Python source files that can
  be read only through extracting from the zip file.

  Args:
    source_file_path: The full path to the file inside the .par file. This
      path should include the path to the .par file itself, followed by the
      intra-par path, e.g.,
      "/tmp/my_executable.par/org-tensorflow/tensorflow/python/foo/bar.py".

  Returns:
    If successful, lines of the source file as a `list` of `str`s.
    Else, `None`.
  )startz.parc             S   s   g | ]}t j|qS r   )r   r   r   ).0namer   r   r	   
<listcomp>   s    z(_try_load_par_source.<locals>.<listcomp>zutf-8r   N)r   r   r#   r   relpathr   r   zipfileZipFilenamelistr    indexr!   r"   )r+   prefix_pathbasenameZsuffix_pathzZ
norm_nameszfr-   r   r   r	   r$   w   s    r$   Fc             C   s   | j }|stdt|}i }x| D ]}xt| |jD ]\}	}
}}|dk	rZ|
|k s>|dk	rl|
|krlq>t|	|krzq>|r| |j}tt	t
t|}n|jg}|
|kr||
 | n|||
< |r>P q>W q(W |S )a  Annotate a Python source file with a list of ops created at each line.

  (The annotation doesn't change the source file itself.)

  Args:
    dump: (`DebugDumpDir`) A `DebugDumpDir` object of which the Python graph
      has been loaded.
    source_file_path: (`str`) Path to the source file being annotated.
    do_dumped_tensors: (`str`) Whether dumped Tensors, instead of ops are to be
      used to annotate the source file.
    file_stack_top: (`bool`) Whether only the top stack trace in the
      specified source file is to be annotated.
    min_line: (`None` or `int`) The 1-based line to start annotate the source
      file from (inclusive).
    max_line: (`None` or `int`) The 1-based line number to end the annotation
      at (exclusive).

  Returns:
    A `dict` mapping 1-based line number to a list of op name(s) created at
      that line, or tensor names if `do_dumped_tensors` is True.

  Raises:
    ValueError: If the dump object does not have a Python graph set.
  zUCannot perform source annotation due to a lack of set Python graph in the dump objectN)python_graph
ValueErrorr
   get_operationsreversednode_tracebackr1   debug_watch_keyslistsetmapr   extend)dumpr+   Zdo_dumped_tensorsZfile_stack_topmin_linemax_linepy_graphZline_to_op_namesopr   line_numberr   
watch_keysZitems_to_appendr   r   r	   annotate_source   s.    
rM   c                s"  | j }|stdtt}tt}i }i  |r<t|nd}|rNt|nd}t }	x2| D ]$}
|r|||
j	s|qdx
| 
|
j	D ]\}}}}t|}||	ks|r||rtj|s|	| q|| |
j	 ||kr|| |kr|||< n|||< x$|
jD ]}|j	}|| | qW | |
j	}xN|D ]F}|d\}}}d||f }| kr<t| |t|| |< q<W qW qdW i }x,|D ]$}t fdd|| D ||< qW g }xL|D ]D}||t|t||i t||i ||d|| f qW t|dd	 d
S )a@  Generate a list of source files with information regarding ops and tensors.

  Args:
    dump: (`DebugDumpDir`) A `DebugDumpDir` object of which the Python graph
      has been loaded.
    path_regex_allowlist: A regular-expression filter for source file path.
    node_name_regex_allowlist: A regular-expression filter for node names.

  Returns:
    A list of tuples regarding the Python source files involved in constructing
    the ops and tensors contained in `dump`. Each tuple is:
      (source_file_path, is_tf_library, num_nodes, num_tensors, num_dumps,
       first_line)

      is_tf_library: (`bool`) A guess of whether the file belongs to the
        TensorFlow Python library.
      num_nodes: How many nodes were created by lines of this source file.
        These include nodes with dumps and those without.
      num_tensors: How many Tensors were created by lines of this source file.
        These include Tensors with dumps and those without.
      num_dumps: How many debug Tensor dumps were from nodes (and Tensors)
        that were created by this source file.
      first_line: The first line number (1-based) that created any nodes or
        Tensors in this source file.

    The list is sorted by ascending order of source_file_path.

  Raises:
    ValueError: If the dump object does not have a Python graph set.
  zPCannot generate source list due to a lack of set Python graph in the dump objectNr   z%s:%sc             3   s   | ]}  |d V  qdS )r   N)get)r0   tensor_name)tensor_name_to_num_dumpsr   r	   	<genexpr>0  s   z1list_source_files_against_dump.<locals>.<genexpr>r   c             S   s   | d S )Nr   r   )xr   r   r	   <lambda>=      z0list_source_files_against_dump.<locals>.<lambda>)key)r<   r=   collectionsdefaultdictrC   recompiler>   matchr1   r@   r
   r   r   r   addoutputsrA   r#   r*   Zget_tensorsr&   sumappendr   rN   sorted)rF   Zpath_regex_allowlistZnode_name_regex_allowlistrI   Zpath_to_node_namesZpath_to_tensor_namesZpath_to_first_lineZ
path_regexnode_name_regexZto_skip_file_pathsrJ   r   rK   r   Zoutput_tensorrO   rL   r   	node_nameZoutput_slotZdebug_opZpath_to_num_dumpsr   outputr   )rP   r	   list_source_files_against_dump   sd    "





&



rc   c       
      C   s   t |}|rt|nd}|r(t|nd}i }x| D ]}	|	jsBq6t |	j|krRq6|dk	rd|	j|k s6|dk	rx|	j|krxq6|r||	jjsq6|r||	jsq6|	j|krt	
|	||	j< q6||	j |	 q6W |S )a  Annotate a Python source file with profiling information at each line.

  (The annotation doesn't change the source file itself.)

  Args:
    profile_data: (`list` of `ProfileDatum`) A list of `ProfileDatum`.
    source_file_path: (`str`) Path to the source file being annotated.
    node_name_filter: Regular expression to filter by node name.
    op_type_filter: Regular expression to filter by op type.
    min_line: (`None` or `int`) The 1-based line to start annotate the source
      file from (inclusive).
    max_line: (`None` or `int`) The 1-based line number to end the annotation
      at (exclusive).

  Returns:
    A `dict` mapping 1-based line number to a the namedtuple
      `profiling.LineOrFuncProfileSummary`.
  N)r
   rX   rY   r   rK   rZ   Znode_exec_statsra   Zop_typer   ZAggregateProfiler[   )
Zprofile_datar+   Znode_name_filterZop_type_filterrG   rH   r`   Zop_type_regexZline_to_profile_summaryZprofile_datumr   r   r	   annotate_source_against_profile@  s*    

rd   )FFNN)NN)NNNN)__doc__rV   r   rX   r4   Zabslnumpyr'   Ztensorflow.python.debug.libr   r   dirnamer   r   __file__r   r   r   r   r
   r   r   r   r   r.   r$   rM   rc   rd   r   r   r   r	   <module>   s<   %#   
? 
e   