U
    nuf'                     @   s   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mZ d dlmZ d dlmZ d d	lmZ d d
lmZ dZedddZdd Zdd Zeg ddd Zdd Zdd ZedddZedddZd d! Zd"d# ZdS )$    N)Path)all_suffixes)inference_state_method_cache)ContextualizedNode)	is_stringget_str_or_none)get_cached_code_lines)FileIO)settings)debug
   )str_pathc                 C   s<   t |}| r|S |  }|d kr(d S |j}|| S N)r   is_absoluteZ
py__file__parentjoinpathabsolute)module_contextr   pathmodule_pathbase_dir r   ;/tmp/pip-unpacked-wheel-ol4ehs9f/jedi/inference/sys_path.py	_abs_path   s    r   c           
   	   c   s  t |jddd |jddd D ]\}}z||dks8t|jdkrPt|jdksTt|j}|d jdkrv|d jdkszt|d }|jd d	kr|jd jd
kstW n tk
r   Y q"Y nX t| ||}| 	|D ]6}| D ](}t
|rt| | }	|	dk	r|	V  qqq"dS )a  
    Extracts the assigned strings from an assignment that looks as follows::

        sys.path[0:0] = ['module/path', 'another/module/path']

    This function is in general pretty tolerant (and therefore 'buggy').
    However, it's not a big issue usually to add more paths to Jedi's sys_path,
    because it will only affect Jedi in very random situations and by adding
    more paths than necessary, it usually benefits the general user.
    N      )=z+=powerZ	atom_exprr   namesys.r   )zipchildrenAssertionErrortypelenvaluer   create_contextZinferZiterater   r   Zget_safe_value)
r   	expr_stmtZassigneeoperatorctrailerZcnZ
lazy_valuer'   abs_pathr   r   r   _paths_from_assignment    s(    *
 "
r.   c                 c   s   |j dkr>|jd dkr>|j dkr>|jd dkr>t|jdksBdS |jd j}|dkrZdS |jd }|d	krt|jd
kr|jd }| ||D ].}t|}|dkrqt| |}|dk	r|V  qdS )zE extract the path from either "sys.path.append" or "sys.path.insert" r,   r   r!   (   Nr   )insertappendr1   )r0      r   )r%   r#   r&   r'   r(   Z
infer_noder   r   )r   Ztrailer1Ztrailer2r   argr'   pr-   r   r   r   _paths_from_list_modificationsK   s*    


r6   )defaultc                 C   s   dd }| j dkrg S g }z| j  d }W n tk
r@   Y njX ||D ]^\}}|j}t|jdkr|t| f|jdd   qJ|dk	rJ|jdkrJ|t	| | qJ|S )z6
    Detect sys.path modifications within module.
    c                 s   s   | D ]z}|j j }|d k	r|jdkr|j}|d jdkr|d jdkr|d jdkr|d jd }|jdkr|jdkr||fV  qd S )Nr   r   r   r    r   r,   r   )r   r%   r#   r'   )namesr   r   r+   nr   r   r   get_sys_path_powersi   s    z9check_sys_path_modifications.<locals>.get_sys_path_powersNr   r3   r   r)   )
Z	tree_nodeZget_used_namesKeyErrorr   r&   r#   extendr6   r%   r.   )r   r:   addedZpossible_namesr   r   r)   r   r   r   check_sys_path_modificationsd   s*    
r>   c                 C   sB   t  }t|D ].}t| |D ]}|| t|tkr qqq|S r   )set_get_buildout_script_paths_get_paths_from_buildout_scriptaddr&   _BUILDOUT_PATH_INSERTION_LIMIT)inference_stateZscript_pathZbuildout_script_pathsbuildout_script_pathr   r   r   r   discover_buildout_paths   s    
rF   c                 c   s   t t|}z| j|dtjd}W n" tk
rD   td| Y d S X ddlm	} || ||d t
| j|d }t|E d H  d S )NT)file_iocache
cache_pathz(Error trying to read buildout_script: %sr   )ModuleValue)rG   Zstring_namesZ
code_lines)r	   strparser
   Zcache_directoryIOErrorr   warningZjedi.inference.valuerJ   r   ZgrammarZ
as_contextr>   )rD   rE   rG   Zmodule_noderJ   r   r   r   r   rA      s&    
 

rA   )r   c              	   C   sF   | j D ]:}z|| r$|W   S W q tk
r>   Y qY qX qd S r   )parentsr   is_fileOSError)r   filenamer   r   r   r   _get_parent_dir_with_file   s    
rS   )search_pathc                 c   s   t | d}|sdS |d}| s(dS t|D ]}zD||}t|d&}| }|drnd|krn|V  W 5 Q R X W q2 tt	fk
r } zt
t| W Y q2W 5 d}~X Y q2X q2dS )z
    if there is a 'buildout.cfg' file in one of the parent directories of the
    given module it will return a list of all files in the buildout bin
    directory that look like python files.

    :param search_path: absolute path to the module.
    zbuildout.cfgNbinrz#!python)rS   r   existsoslistdiropenreadline
startswithUnicodeDecodeErrorrM   r   rN   rK   )rT   Zproject_rootZbin_pathrR   filepathf	firstlineer   r   r   r@      s     


r@   c                 C   s0   t  dg D ]}| j|kr| | j}  q,q| S )Nz.pyi)r   suffix	with_namestem)r   rc   r   r   r   remove_python_path_suffix   s
    
rf   c                    sd   t    jdrdS  jdk}|r, j  fdd}t| }|sLdS t|dd dd	 |fS )
aK  
    Returns the dotted path inside a sys.path as a list of names. e.g.

    >>> transform_path_to_dotted([str(Path("/foo").absolute())], Path('/foo/bar/baz.py').absolute())
    (('bar', 'baz'), False)

    Returns (None, False) if the path doesn't really resolve to anything.
    The second return part is if it is a package.
    r!   )NF__init__c                  3   s   D ]~} t  | rt  t| d  }|tjjsB|drN|dd  }|r|tjj}t|sn d S tdd |D V  qd S )N/r   c                 s   s   | ]}t d d|V  qdS )z-stubs$ N)resub).0sr   r   r   	<genexpr>  s     zMtransform_path_to_dotted.<locals>.iter_potential_solutions.<locals>.<genexpr>)	rK   r]   r&   rY   r   sepsplitalltuple)r5   restrp   r   sys_pathr   r   iter_potential_solutions   s    z:transform_path_to_dotted.<locals>.iter_potential_solutionsc                 S   s   t | S r   )r&   )r5   r   r   r   <lambda>      z*transform_path_to_dotted.<locals>.<lambda>)keyr   )rf   r   r]   r   rr   sorted)ru   r   
is_packagerv   Zpotential_solutionsr   rt   r   transform_path_to_dotted   s    

r|   ) rY   rj   pathlibr   Zimportlib.machineryr   Zjedi.inference.cacher   Zjedi.inference.base_valuer   Zjedi.inference.helpersr   r   Zjedi.parser_utilsr   Zjedi.file_ior	   Zjedir
   r   rC   rK   r   r.   r6   r>   rF   rA   rS   r@   rf   r|   r   r   r   r   <module>   s,   +
%
