a
    ,=ic3                     @   s   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Zddlm	Z	 ddl
mZ ddl
mZ dd
dZdd ZdddZdd ZdddZdS )z-Functions for dealing with import statements.    )absolute_import)division)print_functionN)errors)	ast_utils)scopeTc                    s  t | |jv r:tdd j| D d}|r:|jjS d}d}fdd}|rd|v r|dd\ }	||	|}
|rt fdd| jD d}|r|j	|
 |
j
p|
jS tj |
gd	d
}|s|||d}
tj|
gd}| jt| rdnd	| |
j
p|
jS )a9  Adds an import to the module.
  
  This function will try to ensure not to create duplicate imports. If name_to_import is
  already imported, it will return the existing import. This is true even if asname is set
  (asname will be ignored, and the existing name will be returned).
  
  If the import would create a name that already exists in the scope given by tree, this
  function will "import as", and append "_x" to the asname where x is the smallest positive
  integer generating a unique name.

  Arguments:
    tree: (ast.Module) Module AST to modify.
    name_to_import: (string) The absolute name to import.
    asname: (string) The alias for the import ("import name_to_import as asname")
    from_import: (boolean) If True, import the name using an ImportFrom node.
    merge_from_imports: (boolean) If True, merge a newly inserted ImportFrom
      node into an existing ImportFrom node, if applicable.

  Returns:
    The name (as a string) that can be used to reference the imported name. This
      can be the fully-qualified name, the basename, or an alias name.
  c                 s   s   | ]}|j d ur|V  qd S )N)name_ref).0ref r   k/home/droni/.local/share/virtualenvs/DPS-5Je3_V2c/lib/python3.9/site-packages/pasta/augment/import_utils.py	<genexpr>9   s   
zadd_import.<locals>.<genexpr>Nc                    sH   t j| |d}|p| }d}| jv rD|d7 }d|p4| |f  }|_q|S )N)nameasnamer      z%s_%d)astaliasnamesr   )
alias_namer   	new_aliasZimported_namecounter)scr   r   make_safe_alias_nodeA   s    
z(add_import.<locals>.make_safe_alias_node.r   c                 3   s2   | ]*}t |tjr|j kr|jd kr|V  qdS )r   N)
isinstancer   
ImportFrommodulelevel)r	   node)from_moduler   r   r   U   s   r   )r   r   r   )r   r   )r   )r   analyzeZexternal_referencesnextr   idrsplitbodyr   appendr   r   r   r   Importinsertr   Zhas_docstring)treeZname_to_importr   Zfrom_importZmerge_from_importsZexisting_refimport_nodeZ
added_namer   r   r   Zexisting_from_importr   )r   r   r   
add_import   s:    


r*   c                 C   s   |  |}d}dD ]*}t||r|t||v rt||} qPqtd||f ||}t|}|g|_|j	| |
|d | |S )a  Split an import node by moving the given imported alias into a new import.

  Arguments:
    sc: (scope.Scope) Scope computed on whole tree of the code being modified.
    node: (ast.Import|ast.ImportFrom) An import node to split.
    alias_to_remove: (ast.alias) The import alias node to remove. This must be a
      child of the given `node` argument.

  Raises:
    errors.InvalidAstError: if `node` is not appropriately contained in the tree
      represented by the scope `sc`.
  N)r$   orelse	finalbodyz:Unable to find list containing import %r on parent node %rr   )parenthasattrgetattrr   ZInvalidAstErrorindexcopydeepcopyr   remover'   )r   r   Zalias_to_remover-   Zparent_listaidxZ
new_importr   r   r   split_importi   s    



r6   c                 C   s   |du rt | }t }t| D ]X}t|tjr"|jdurB|jn|j}||j	v rn|j	| }|j
sz|| q"td| q"|S )a.  Get the import aliases that aren't used.

  Arguments:
    tree: (ast.AST) An ast to find imports in.
    sc: A scope.Scope representing tree (generated from scratch if not
    provided).

  Returns:
    A list of ast.alias representing imported aliases that aren't referenced in
    the given tree.
  NzGImported name %s not found in scope (perhaps it's imported dynamically))r   r    setr   walkr   r   r   r   r   Zreadsaddloggingwarning)r(   r   Zunused_aliasesr   Zstr_namer   r   r   r   get_unused_import_aliases   s    


r<   c                 C   s@   |  |}t|jdkr0|  |}t|| nt|| dS )zRemove an alias and if applicable remove their entire import.

  Arguments:
    sc: (scope.Scope) Scope computed on whole tree of the code being modified.
    node: (ast.Import|ast.ImportFrom|ast.alias) The node to remove.
  r   N)r-   lenr   r   Zremove_child)r   r   r)   Zimport_parentr   r   r   remove_import_alias_node   s
    

r>   c                 C   s   |du rt | }d}t }| jD ]}t|tjtjfr"t|j	D ]}|
|}t|tjrd|j}n4|jrdd|j |j|jf }ndd|j |jf }|d|jp|j 7 }||v rt|| d}qB|| qBq"|S )a3  Remove duplicate imports, where it is safe to do so.

  This does NOT remove imports that create new aliases

  Arguments:
    tree: (ast.AST) An ast to modify imports in.
    sc: A scope.Scope representing tree (generated from scratch if not
    provided).

  Returns:
    Whether any changes were made.
  NFz%s%s.%sr   z%s%s:T)r   r    r7   r$   r   r   r&   r   listr   r-   r   r   r   r   r>   r9   )r(   r   modifiedZ
seen_namesr   r   r)   Z	full_namer   r   r   remove_duplicates   s*    




rB   )NTT)N)N)__doc__
__future__r   r   r   r   r1   r:   Zpasta.augmentr   Z
pasta.baser   r   r*   r6   r<   r>   rB   r   r   r   r   <module>   s   
K 
