B
    ¢èåS   ã               @   s   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 G dd„ deƒZdd„ ZdS )é    N)Úbuiltins)Ú
exceptions)Úlibutils)Úpynames)Ú	pyobjects)Ú	resources)Úresourceobserver)Ú
taskhandle)Úimportutilsc               @   s´   e Zd ZdZd'dd„Zdd„ Zdd	„ Zd
d„ Zdd„ Zdde	 
¡ fdd„Zde	 
¡ f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#d$„ Zd%d&„ ZdS )*Ú
AutoImportzÁA class for finding the module that provides a name

    This class maintains a cache of global names in python modules.
    Note that this cache is not accurate and might be out of date.

    TFc             C   s`   || _ || _|j d¡| _| jdkr*i | _|j | j¡ tj| j	| j
| jd}|r\| |¡ dS )zÇConstruct an AutoImport object

        If `observe` is `True`, listen for project changes and update
        the cache.

        If `underlined` is `True`, underlined names are cached, too.
        ÚglobalnamesN)ZchangedZmovedZremoved)ÚprojectÚ
underlinedÚ
data_filesZ	read_dataÚnamesZadd_write_hookÚ_writer   ZResourceObserverÚ_changedÚ_movedÚ_removedZadd_observer)Úselfr   Zobserver   Zobserver© r   ú6lib/python3.7/site-packages/rope/contrib/autoimport.pyÚ__init__   s    
zAutoImport.__init__c             C   sD   g }x:| j D ]0}x*| j | D ]}| |¡r| ||f¡ qW qW |S )zReturn a list of ``(name, module)`` tuples

        This function tries to find modules that have a global name
        that starts with `starting`.
        )r   Ú
startswithÚappend)r   ZstartingÚresultÚmoduleZglobal_namer   r   r   Úimport_assist*   s    
zAutoImport.import_assistc             C   s0   g }x&| j D ]}|| j | kr| |¡ qW |S )z2Return the list of modules that have global `name`)r   r   )r   Únamer   r   r   r   r   Úget_modules8   s
    zAutoImport.get_modulesc             C   s.   t ƒ }x"| jD ]}| t | j| ƒ¡ qW |S )z*Return the list of all cached global names)Úsetr   Úupdate)r   r   r   r   r   r   Úget_all_names@   s    zAutoImport.get_all_namesc          	   C   sœ   g }x’| j D ]ˆ}|| j | kry^| j |¡}||krz|| }| ¡ \}}|dk	rz| ¡  ¡ }|dk	rz|dk	rz| ||f¡ W q tjk
r’   Y qX qW |S )z.Return a list of ``(resource, lineno)`` tuplesN)r   r   Ú
get_moduleZget_definition_locationZget_resourcer   r   ÚModuleNotFoundError)r   r   r   r   ÚpymoduleÚpynameÚlinenoÚresourcer   r   r   Úget_name_locationsG   s    
zAutoImport.get_name_locationsNc             C   sX   |dkr| j  ¡ }| dt|ƒ¡}x0|D ](}| d|j ¡ |  ||¡ | ¡  q(W dS )zßGenerate global name cache for project files

        If `resources` is a list of `rope.base.resource.File`\s, only
        those files are searched; otherwise all python modules in the
        project are cached.

        NzGeneratig autoimport cachezWorking on <%s>)r   Zget_python_filesÚcreate_jobsetÚlenÚstarted_jobÚpathÚupdate_resourceÚfinished_job)r   r   r   Útask_handleÚjob_setÚfiler   r   r   Úgenerate_cacheY   s    	

zAutoImport.generate_cachec             C   s†   |  dt|ƒ¡}xp|D ]h}| d| ¡ | d¡rj| j |dd… ¡}|rvx*t|ƒD ]}|  ||¡ qTW n|  ||¡ | 	¡  qW dS )z:Generate global name cache for modules listed in `modules`z&Generatig autoimport cache for moduleszWorking on <%s>z.*Néþÿÿÿ)
r*   r+   r,   Úendswithr   Úfind_moduleÚ
submodulesr.   Úupdate_moduler/   )r   Úmodulesr   r0   r1   ÚmodnameÚmodÚsubr   r   r   Úgenerate_modules_cachek   s    

z!AutoImport.generate_modules_cachec             C   s   | j  ¡  dS )zClear all entries in global-name cache

        It might be a good idea to use this function before
        regenerating global names.

        N)r   Úclear)r   r   r   r   Úclear_cache{   s    zAutoImport.clear_cachec       	      C   s¢   t  d|¡}|dk	r$|d| ¡ … }yt | j|¡}W n tjk
rL   dS X d}t 	|dff¡}t 
| j|¡}| |¡ | ¡ }| |¡}| dd|¡d }|S )z4Guess at what line the new import should be insertedz^(def|class)\s+Né   Z__rope_testmodule_ropeÚ
r   )ÚreÚsearchÚstartr   Zget_string_moduler   r   ÚModuleSyntaxErrorr
   ZNormalImportZget_module_importsZ
add_importZget_changed_sourceÚindexÚcount)	r   ÚcodeÚmatchr%   ZtestmodnameZ
importinfoZmodule_importsÚoffsetr'   r   r   r   Úfind_insertion_line„   s     

zAutoImport.find_insertion_linec             C   sD   y(| j  |¡}|  |¡}|  |||¡ W n tjk
r>   Y nX dS )z/Update the cache for global names in `resource`N)r   Zget_pymoduleÚ_module_nameÚ
_add_namesr   rE   )r   r(   r   r%   r:   r   r   r   r.   —   s    
zAutoImport.update_resourcec             C   s:   y| j  |¡}|  |||¡ W n tjk
r4   Y nX dS )zjUpdate the cache for global names in `modname` module

        `modname` is the name of a module.
        N)r   r#   rM   r   r$   )r   r:   r   r%   r   r   r   r8       s
    zAutoImport.update_modulec             C   s
   t  |¡S )N)r   r:   )r   r(   r   r   r   rL   «   s    zAutoImport._module_namec             C   s–   |d kr| j }g }t|tjƒr(| ¡ }n| ¡ }xV| ¡ D ]J\}}|sR| d¡rRq:t|tj	tj
fƒrn| |¡ t|tjƒr:| |¡ q:W || j|< d S )NÚ_)r   Ú
isinstancer   ZPyDefinedObjectZ_get_structural_attributesZget_attributesÚitemsr   r   ZAssignedNameZDefinedNamer   r   ZBuiltinModuler   )r   r%   r:   r   ÚglobalsZ
attributesr   r&   r   r   r   rM   ®   s    

zAutoImport._add_namesc             C   s   | j j d| j¡ d S )Nr   )r   r   Z
write_datar   )r   r   r   r   r   ¿   s    zAutoImport._writec             C   s   |  ¡ s|  |¡ d S )N)Ú	is_folderr.   )r   r(   r   r   r   r   Â   s    zAutoImport._changedc             C   s2   |  ¡ s.|  |¡}|| jkr$| j|= |  |¡ d S )N)rR   rL   r   r.   )r   r(   Znewresourcer:   r   r   r   r   Æ   s
    

zAutoImport._movedc             C   s(   |  ¡ s$|  |¡}|| jkr$| j|= d S )N)rR   rL   r   )r   r(   r:   r   r   r   r   Í   s    

zAutoImport._removed)TF)N)N)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   r   r   r"   r)   r	   ZNullTaskHandler3   r=   r?   rK   r.   r8   rL   rM   r   r   r   r   r   r   r   r   r      s(   
	
	
r   c             C   sn   t | tjƒr2| j d¡r,| jdkr,t| gƒS tƒ S |  d¡sBtƒ S t| gƒ}x|  ¡ D ]}|t|ƒO }qVW |S )Nz.pyz__init__.py)	rO   r   ZFiler   r5   r    Z	has_childZget_childrenr7   )r;   r   Zchildr   r   r   r7   Ô   s    


r7   )rB   Z	rope.baser   r   r   r   r   r   r   r	   Zrope.refactorr
   Úobjectr   r7   r   r   r   r   Ú<module>   s    G