U
    f                     @   sx   d Z ddlmZ ddlmZ ddlm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
 Zdd Zdd ZdS )z Rename names in a python module.    )absolute_import)division)print_functionN)import_utils)	ast_utils)scopec                 C   sZ  t | }||jkrdS d}i }g }|j| D ] }t|jtjr||j}t|tjr||krt	||||stt
|ddd ||ddd < || n,||jjt|d  |j_|jjs|||< d}q.t|jtjr.|j|kr.t	||j||s t
|ddd ||ddd < ||j d}q.t|D ]\}	}
t|| |	|
 q<|S )a  Rename an imported name in a module.

  This will rewrite all import statements in `tree` that reference the old
  module as well as any names in `tree` which reference the imported name. This
  may introduce new import statements, but only if necessary.

  For example, to move and rename the module `foo.bar.utils` to `foo.bar_utils`:
  > rename_external(tree, 'foo.bar.utils', 'foo.bar_utils')

  - import foo.bar.utils
  + import foo.bar_utils

  - from foo.bar import utils
  + from foo import bar_utils

  - from foo.bar import logic, utils
  + from foo.bar import logic
  + from foo import bar_utils

  Arguments:
    t: (ast.Module) Module syntax tree to perform the rename in. This will be
      updated as a result of this function call with all affected nodes changed
      and potentially new Import/ImportFrom nodes added.
    old_name: (string) Fully-qualified path of the name to replace.
    new_name: (string) Fully-qualified path of the name to update to.

  Returns:
    True if any changes were made, False otherwise.
  F.   NT)r   ZanalyzeZexternal_references
isinstancenodeastaliasparent
ImportFrom_rename_name_in_importfromAssertionErrorrsplitappendnamelenZasnamesix	iteritems_rename_reads)told_namenew_nameschas_changedrenamesZalready_changedrefr   Z
rename_oldZ
rename_new r!   ;/tmp/pip-target-lpfmz8o1/lib/python/pasta/augment/rename.pyrename_external   s4    

 
 r#   c           	      C   s   ||krdS |j d}|d}|d}|d t| |kr`d||t|d   |_ dS |jD ]}|j|d krf qqfdS |d |_||d d krt|jdkrt| ||}d|d d |_ nd|d d |_ dS )NFr   Tr
   r	   )modulesplitr   joinnamesr   r   Zsplit_import)	r   r   r   r   module_partsZ	old_partsZ	new_partsZalias_to_changeZ
new_importr!   r!   r"   r   ^   s&    



r   c           	      C   s   | d}z.| j|d  }|dd D ]}|j| }q&W n tk
rN   Y dS X d}|jD ]<}t|tjtjfrZt	
| ||t|jd j d}qZ|S )ap  Updates all locations in the module where the given name is read.

  Arguments:
    sc: (scope.Scope) Scope to work in. This should be the scope of `t`.
    t: (ast.AST) The AST to perform updates in.
    old_name: (string) Dotted name to update.
    new_name: (string) Dotted name to replace it with.

  Returns:
    True if any changes were made, False otherwise.
  r   r   r	   NFT)r%   r'   attrsKeyErrorZreadsr   r   Name	Attributer   Zreplace_childr   parsebodyvalue)	r   r   r   r   Z
name_partsr   partr   Zref_noder!   r!   r"   r      s    

r   )__doc__
__future__r   r   r   r   r   Zpasta.augmentr   Z
pasta.baser   r   r#   r   r   r!   r!   r!   r"   <module>   s   A!