a
    lc@                     @   s   d 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	m
Z
 ddlmZ ddlmZ dd	lmZmZ dd
lmZmZ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ZdZ dZ!dd Z"dd Z#G dd dZ$dd Z%dd Z&d ddZ'dd Z(dS )!a  
Projects are a way to handle Python projects within Jedi. For simpler plugins
you might not want to deal with projects, but if you want to give the user more
flexibility to define sys paths and Python interpreters for a project,
:class:`.Project` is the perfect way to allow for that.

Projects can be saved to disk and loaded again, to allow project definitions to
be used across repositories.
    N)Path)chain)debug)get_cached_default_environmentcreate_environment)WrongVersion)search_in_module)split_search_stringget_module_names)load_module_from_pathload_namespace_from_pathiter_module_names)discover_buildout_paths)%inference_state_as_method_param_cache)%recurse_find_python_folders_and_filessearch_in_file_ios)FolderIOz.jedi)zsetup.pyz.gitz.hgzrequirements.txtzMANIFEST.inzpyproject.toml   c                    s    fdd}|S )Nc                  ?   sv   g }g } | i |D ]Z}|j j}|d ur4||v r4q|jdkr`|jd ur`|j|v rTq||j |V  || qd S )Nmodule)_name	tree_nametypemodule_pathappend)argskwargsZfound_tree_nodesZfound_modulesZ
definition	tree_nodefunc L/var/www/html/django/DPS/env/lib/python3.9/site-packages/jedi/api/project.pywrapper"   s    
z(_try_to_skip_duplicates.<locals>.wrapperr   )r   r!   r   r   r    _try_to_skip_duplicates!   s    r"   c                 c   s.   t  }| D ]}||v rq
|| |V  q
d S N)setadd)pathusedpr   r   r    _remove_duplicates_from_path2   s    
r)   c                   @   s   e Zd ZdZdZedd Zedd Zedd Z	d	d
 Z
ddddddddddZedd Zedd Zedd Zedd Ze dd Ze d)ddZdd Zdd d!d"Zd#d$ Zed*d%d&Zd'd( ZdS )+Projectz
    Projects are a simple way to manage Python folders and define how Jedi does
    import resolution. It is mostly used as a parameter to :class:`.Script`.
    Additionally there are functions to search a whole project.
    Nc                 C   s
   |  tS r#   )joinpath_CONFIG_FOLDER	base_pathr   r   r    _get_config_folder_pathC   s    zProject._get_config_folder_pathc                 C   s   t | dS )Nzproject.json)r*   r/   r+   r-   r   r   r    _get_json_pathG   s    zProject._get_json_pathc                 C   sp   t |trt|}t| |}t|\}}W d   n1 sD0    Y  |dkrd| f i |S tddS )z
        Loads a project from a specific path. You should not provide the path
        to ``.jedi/project.json``, but rather the path to the project folder.

        :param path: The path of the directory you want to use as a project.
        Nr   zEThe Jedi version of this project seems newer than what we can handle.)
isinstancestrr   openr0   jsonloadr   )clsr&   fversiondatar   r   r    r5   K   s    
,zProject.loadc                 C   s   t | j}|dd |dd dd | D }t|d |d< | | jjddd t| 	| jd	 }t
t|f|W  d   S 1 s0    Y  dS )
z[
        Saves the project configuration in the project in ``.jedi/project.json``.
        _environmentN_djangoc                 S   s   i | ]\}}| d |qS )_)lstrip).0kvr   r   r    
<dictcomp>f       z Project.save.<locals>.<dictcomp>r&   T)parentsexist_okw)dict__dict__popitemsr2   r/   _pathmkdirr3   r0   r4   dump_SERIALIZER_VERSION)selfr9   r7   r   r   r    save_   s    
zProject.saveFr   T)environment_pathload_unsafe_extensionssys_pathadded_sys_pathsmart_sys_path)returnc                C   sd   t |trt| }|| _|| _|dur8ttt|}|| _|| _	|| _
d| _ttt|| _dS )a$  
        :param path: The base path for this project.
        :param environment_path: The Python executable path, typically the path
            of a virtual environment.
        :param load_unsafe_extensions: Default False, Loads extensions that are not in the
            sys path and in the local directories. With this option enabled,
            this is potentially unsafe if you clone a git repository and
            analyze it's code, because those compiled extensions will be
            important and therefore have execution privileges.
        :param sys_path: list of str. You can override the sys path if you
            want. By default the ``sys.path.`` is generated by the
            environment (virtualenvs, etc).
        :param added_sys_path: list of str. Adds these paths at the end of the
            sys path.
        :param smart_sys_path: If this is enabled (default), adds paths from
            local directories. Otherwise you will have to rely on your packages
            being properly configured on the ``sys.path``.
        NF)r1   r2   r   absoluterJ   _environment_pathlistmap	_sys_path_smart_sys_path_load_unsafe_extensionsr;   rS   )rN   r&   rP   rQ   rR   rS   rT   r   r   r    __init__m   s    
zProject.__init__c                 C   s   | j S )z1
        The base path for this project.
        )rJ   rN   r   r   r    r&      s    zProject.pathc                 C   s   | j S )zz
        The sys path provided to this project. This can be None and in that
        case will be auto generated.
        )rZ   r^   r   r   r    rR      s    zProject.sys_pathc                 C   s   | j S )zu
        If the sys path is going to be calculated in a smart way, where
        additional paths are added.
        )r[   r^   r   r   r    rT      s    zProject.smart_sys_pathc                 C   s   | j S )z=
        Wheter the project loads unsafe extensions.
        )r\   r^   r   r   r    rQ      s    zProject.load_unsafe_extensionsc                 C   s4   t |j }z|d W n ty.   Y n0 |S )N )rX   environmentZget_sys_pathremove
ValueError)rN   inference_staterR   r   r   r    _get_base_sys_path   s    zProject._get_base_sys_pathc           
      C   s   t | j}g }| jdu r(t | |}n
t | j}| jr|t| j |jdur|t	tt
||j7 }|rg }|jjD ]@}|| jks| j|jvr q|s|d rqx|t| qx|t|7 }| jr|t| j || | }	t t|	S )z
        Keep this method private for all users of jedi. However internally this
        one is used like a public method.
        N__init__.py)rX   rS   rZ   rd   r[   r   r2   rJ   Zscript_pathrY   r   rC   r+   is_filereversedr;   r)   )
rN   rc   Zadd_parent_pathsZadd_init_pathssuffixedprefixedrR   Z	traversedparent_pathr&   r   r   r    _get_sys_path   s:    





zProject._get_sys_pathc                 C   s4   | j d u r.| jd ur&t| jdd| _ nt | _ | j S )NF)safe)r:   rW   r   r   r^   r   r   r    get_environment   s
    

zProject.get_environment
all_scopesc                C   s   | j ||dS )aO  
        Searches a name in the whole project. If the project is very big,
        at some point Jedi will stop searching. However it's also very much
        recommended to not exhaust the generator. Just display the first ten
        results to the user.

        There are currently three different search patterns:

        - ``foo`` to search for a definition foo in any file or a file called
          ``foo.py`` or ``foo.pyi``.
        - ``foo.bar`` to search for the ``foo`` and then an attribute ``bar``
          in it.
        - ``class foo.bar.Bar`` or ``def foo.bar.baz`` to search for a specific
          API type.

        :param bool all_scopes: Default False; searches not only for
            definitions on the top level of a module level, but also in
            functions and classes.
        :yields: :class:`.Name`
        rn   _search_func)rN   stringro   r   r   r    search   s    zProject.searchc                 K   s   | j |fddi|S )au  
        Like :meth:`.Script.search`, but completes that string. An empty string
        lists all definitions in a project, so be careful with that.

        :param bool all_scopes: Default False; searches not only for
            definitions on the top level of a module level, but also in
            functions and classes.
        :yields: :class:`.Completion`
        completeTrp   )rN   rr   r   r   r   r    complete_search  s    
zProject.complete_searchc                 #   s  ddl m} |dd}|j}| }td|| t|\}}	|	d }
|
d }ttt	j
}g }|D ]\}}|d u r| }||
ks||krj|d}zt|| }W nT ty   |d}zt|| }W n" ty    t|| }Y n0 Y n0 nqjn8|| t|jj|
d	 |
d
 fv rjt|| }nqjtd| t|||jg||	|dddE d H  qjt|||
|dD ]J t j|d} fdd|D }t|}t| |||	|ddE d H  qfdd|D }tt|||}t|||||	|ddE d H  d S )Nr   )Scriptr_   )projectz!Search for string %s, complete=%sz-stubsre   z__init__.pyiz.pyz.pyizSearch of a specific module %sT)nameswanted_typewanted_namesrt   convertignore_imports)rt   rn   c                    s   g | ]}  |qS r   )Zcreate_namer>   n)module_contextr   r    
<listcomp>T  rB   z(Project._search_func.<locals>.<listcomp>)rx   ry   rz   rt   r|   c                    s    g | ]}| t js|qS r   )
startswithr2   rJ   )r>   r(   r^   r   r    r   a  s   )rx   ry   rz   rt   r{   )jedirv   Z_inference_stateZ_get_module_contextr   Zdbgr	   r   r   r2   rJ   Zget_base_nameZget_file_ior   Z
as_contextFileNotFoundErrorr   r   r   r&   namer   r   r
   r   _remove_importsrk   rX   r   )rN   rr   rt   ro   rv   src   Zempty_module_contextry   rz   r   Zstub_folder_nameZiosZfile_iosZ	folder_ioZfile_io	file_namer7   mrx   rR   r   )r   rN   r    rq     s    





zProject._search_funcc                 C   s   d| j j| jf S )Nz<%s: %s>)	__class____name__rJ   r^   r   r   r    __repr__r  s    zProject.__repr__)TF)FF)r   
__module____qualname____doc__r:   staticmethodr/   r0   classmethodr5   rO   r]   propertyr&   rR   rT   rQ   r   rd   rk   rm   rs   ru   r"   rq   r   r   r   r   r    r*   ;   sF   


	-




	/Tr*   c              	   C   s@   t D ]6}z| | r W  dS W q ty8   Y qY q0 qdS )NTF)_CONTAINS_POTENTIAL_PROJECTr+   existsOSError)r&   r   r   r   r    _is_potential_projectv  s    r   c              
   C   sb   zBt | dd}d| v W  d   W S 1 s60    Y  W n tttfy\   Y dS 0 dS )zB Detects the path of the very well known Django library (if used) z	manage.pyrbs   DJANGO_SETTINGS_MODULENF)r3   r+   readr   IsADirectoryErrorPermissionError)	directoryr7   r   r   r    _is_django_path  s
    0r   c                 C   s  | du rt  } nt| tr$t | } |  }d}d}t|g|jD ]}zt|W   S  t	t
tfyn   Y n ty   Y qBY n0 |du r|d rqBn| s|}t|rt|}d|_|  S |du rBt|rB|}qB|durt|S |dur t|S |  r| n| j}t|S )aI  
    If a project is not defined by the user, Jedi tries to define a project by
    itself as well as possible. Jedi traverses folders until it finds one of
    the following:

    1. A ``.jedi/config.json``
    2. One of the following files: ``setup.py``, ``.git``, ``.hg``,
       ``requirements.txt`` and ``MANIFEST.in``.
    Nre   T)r   cwdr1   r2   rV   r   rC   r*   r5   r   r   r   NotADirectoryErrorr+   r   rf   r   r;   r   is_dirparent)r&   checkZprobable_pathZfirst_no_init_filedirrw   curdirr   r   r    get_default_project  s>    




r   c                 C   s   dd | D S )Nc                 S   s$   g | ]}|j d u s|jdvr|qS )N)r   	namespace)r   Zapi_typer}   r   r   r    r     s   z#_remove_imports.<locals>.<listcomp>r   )rx   r   r   r    r     s    r   )N))r   r4   pathlibr   	itertoolsr   r   r   Zjedi.api.environmentr   r   Zjedi.api.exceptionsr   Zjedi.api.completionr   Zjedi.api.helpersr	   r
   Zjedi.inference.importsr   r   r   Zjedi.inference.sys_pathr   Zjedi.inference.cacher   Zjedi.inference.referencesr   r   Zjedi.file_ior   r,   r   rM   r"   r)   r*   r   r   r   r   r   r   r   r    <module>   s4   		  =
	
5