U
    ^7                     @   s  d Z ddlZddlZddlZddlZddlmZ ddlmZm	Z	 ddl
mZ ddlmZmZ ddlmZmZ ddlmZ erdd	lmZmZmZmZmZmZmZ ejZed
eZee Z!dd Z"dd Z#eddddddZ$erdndZ%dd Z&G dd de'Z(dS )a  Configuration management setup

Some terminology:
- name
  As written in config files.
- value
  Value associated with a name
- key
  Name combined with it's section (section.name)
- variant
  A single word describing where the configuration key-value pair came from
    N)configparser)ConfigurationError!ConfigurationFileCouldNotBeLoaded)appdirs)WINDOWS
expanduser)
ensure_direnum)MYPY_CHECK_RUNNING)AnyDictIterableListNewTypeOptionalTupleKindc                 C   s*   |   dd} | dr&| dd } | S )zFMake a name consistent regardless of source (environment or file)
    _-z--   N)lowerreplace
startswith)name r   :lib/python3.8/site-packages/pip/_internal/configuration.py_normalize_name-   s    
r   c                 C   s&   d| krd | }t|| ddS )N.zbKey does not contain dot separated section and key. Perhaps you wanted to use 'global.{}' instead?   )formatr   split)r   Zerror_messager   r   r   _disassemble_key7   s    r!   userglobalZsiteenvzenv-var)USERGLOBALSITEENVENV_VARzpip.inizpip.confc                  C   sp   dd t dD } tjtjt}tjtdt	r8dndt}tjt 
dt}tj| tj|gtj||giS )Nc                 S   s   g | ]}t j|tqS r   )ospathjoinCONFIG_BASENAME).0r+   r   r   r   
<listcomp>Q   s   z+get_configuration_files.<locals>.<listcomp>Zpip~z.pip)r   Zsite_config_dirsr*   r+   r,   sysprefixr-   r   r   Zuser_config_dirkindsr&   r'   r%   )Zglobal_config_filesZsite_config_fileZlegacy_config_fileZnew_config_filer   r   r   get_configuration_filesO   s(    
    r4   c                       s   e Zd ZdZd) fdd	Zdd Zdd Zd	d
 Zdd Zdd Z	dd Z
dd Zdd Zedd Zdd Zdd Zdd Zdd Zdd  Zd!d" Zd#d$ Zd%d& Zd'd( Z  ZS )*Configurationa  Handles management of configuration.

    Provides an interface to accessing and managing configuration files.

    This class converts provides an API that takes "section.key-name" style
    keys and stores the value associated with it as "key-name" under the
    section "section".

    This allows for a clean interface wherein the both the section and the
    key-name are preserved in an easy to manage form in the configuration files
    and the data stored is also nice.
    Nc              
      s   t t|   tjtjtjd g}||krJtdd	t
t|d d || _|| _tjtjtjtjtjg| _ddg| _dd | jD | _dd | jD | _g | _d S )	Nz5Got invalid value for load_only - should be one of {}z, versionhelpc                 S   s   i | ]
}|g qS r   r   r.   variantr   r   r   
<dictcomp>   s     z*Configuration.__init__.<locals>.<dictcomp>c                 S   s   i | ]
}|i qS r   r   r9   r   r   r   r;      s     )superr5   __init__r3   r%   r&   r'   r   r   r,   mapreprisolated	load_onlyr(   r)   _override_order_ignore_env_names_parsers_config_modified_parsers)selfr@   rA   Z_valid_load_only	__class__r   r   r=   t   s0        
zConfiguration.__init__c                 C   s   |    | js|   dS )zELoads configuration from configuration files and environment
        N)_load_config_filesr@   _load_environment_varsrG   r   r   r   load   s    zConfiguration.loadc                 C   s<   | j dk	stdz|  d W S  tk
r6   Y dS X dS )z@Returns the file with highest priority in configuration
        Nz)Need to be specified a file to be editingr   )rA   AssertionError_get_parser_to_modify
IndexErrorrL   r   r   r   get_file_to_edit   s    zConfiguration.get_file_to_editc                 C   s
   | j  S )z`Returns key-value pairs like dict.items() representing the loaded
        configuration
        )_dictionaryitemsrL   r   r   r   rS      s    zConfiguration.itemsc                 C   s4   z| j | W S  tk
r.   td|Y nX dS )z,Get a value from the configuration.
        No such key - {}N)rR   KeyErrorr   r   )rG   keyr   r   r   	get_value   s    zConfiguration.get_valuec                 C   sj   |    |  \}}|dk	rJt|\}}||s<|| |||| || j| j |< | || dS )z-Modify a value in the configuration.
        N)	_ensure_have_load_onlyrO   r!   has_sectionZadd_sectionsetrE   rA   _mark_as_modified)rG   rV   valuefnameparsersectionr   r   r   r   	set_value   s    

zConfiguration.set_valuec           	      C   s   |    || j| j kr&td||  \}}|dk	rt|\}}d}||r`|||}|rt	|
|}zt|}W n tk
r   d}Y nX |dkr|| | || ntd| j| j |= dS )z,Unset a value in the configuration.
        rT   NFz4Fatal Internal error [id=1]. Please report as a bug.)rX   rE   rA   r   r   rO   r!   rY   Zremove_optioniterrS   nextStopIterationZremove_sectionr[   )	rG   rV   r]   r^   r_   r   Zmodified_somethingZsection_itervalr   r   r   unset_value   s,    


zConfiguration.unset_valuec              
   C   sX   |    | jD ]D\}}td| ttj| t|d}|	| W 5 Q R X qdS )z*Save the current in-memory state.
        zWriting to %swN)
rX   rF   loggerinfor   r*   r+   dirnameopenwrite)rG   r]   r^   fr   r   r   save   s    zConfiguration.savec                 C   s$   | j d krtdtd| j  d S )Nz'Needed a specific file to be modifying.z$Will be working with %s variant only)rA   r   rg   debugrL   r   r   r   rX     s    
z$Configuration._ensure_have_load_onlyc                 C   s$   i }| j D ]}|| j|  q
|S )z<A dictionary representing the loaded configuration.
        )rB   updaterE   )rG   Zretvalr:   r   r   r   rR   	  s    
zConfiguration._dictionaryc                 C   s   t |  }|tj dd tjgkr4td dS | D ]V\}}|D ]H}| j	dk	rp|| j	krptd|| qH| 
||}| j| ||f qHq<dS )z5Loads configuration from configuration files
        r   r   zZSkipping loading configuration files due to environment's PIP_CONFIG_FILE being os.devnullNz Skipping file '%s' (variant: %s))dict_iter_config_filesr3   r(   r*   devnullrg   rn   rS   rA   
_load_filerD   append)rG   config_filesr:   filesr]   r^   r   r   r   rJ     s"      z Configuration._load_config_filesc                 C   sL   t d|| | |}| D ]&}||}| j| | || q |S )Nz'For variant '%s', will try loading '%s')rg   rn   _construct_parserZsectionsrS   rE   ro   _normalized_keys)rG   r:   r]   r^   r_   rS   r   r   r   rs   2  s    

zConfiguration._load_filec              
   C   s   t  }tj|r|z|| W nX tk
rN   tdt	
d|dY n. t jk
rz } zt|dW 5 d }~X Y nX |S )Nzcontains invalid {} charactersF)reasonr]   )error)r   RawConfigParserr*   r+   existsreadUnicodeDecodeErrorr   r   localeZgetpreferredencodingError)rG   r]   r^   rz   r   r   r   rw   =  s    
zConfiguration._construct_parserc                 C   s"   | j tj | d|   dS )z7Loads configuration from environment variables
        z:env:N)rE   r3   r)   ro   rx   _get_environ_varsrL   r   r   r   rK   T  s    z$Configuration._load_environment_varsc                 C   s.   i }|D ] \}}|d t | }|||< q|S )zNormalizes items to construct a dictionary with normalized keys.

        This routine is where the names become keys and are made the same
        regardless of source - configuration files or environment.
        r   )r   )rG   r_   rS   Z
normalizedr   rd   rV   r   r   r   rx   \  s
    
zConfiguration._normalized_keysc                 c   sR   t j D ]B\}}|do0|dd  | jk}|r
|dd  |fV  q
dS )z@Returns a generator with all environmental vars with prefix PIP_ZPIP_   N)r*   environrS   r   r   rC   )rG   rV   rd   Zshould_be_yieldedr   r   r   r   i  s    
zConfiguration._get_environ_varsc                 c   s   t jdd}|dk	r&tj|gfV  ntjg fV  t }tj|tj fV  | j ob|o`t j	| }|rztj
|tj
 fV  tj|tj fV  dS )zYields variant and configuration files associated with it.

        This should be treated like items of a dictionary.
        ZPIP_CONFIG_FILEN)r*   r   getr3   r(   r4   r&   r@   r+   r|   r%   r'   )rG   Zconfig_fileru   Zshould_load_user_configr   r   r   rq   u  s    	z Configuration._iter_config_filesc                 C   s    | j | j }|std|d S )Nz4Fatal Internal error [id=2]. Please report as a bug.r6   )rD   rA   r   )rG   Zparsersr   r   r   rO     s    z#Configuration._get_parser_to_modifyc                 C   s"   ||f}|| j kr| j | d S )N)rF   rt   )rG   r]   r^   Zfile_parser_tupler   r   r   r[     s    
zConfiguration._mark_as_modified)N)__name__
__module____qualname____doc__r=   rM   rQ   rS   rW   r`   re   rm   rX   propertyrR   rJ   rs   rw   rK   rx   r   rq   rO   r[   __classcell__r   r   rH   r   r5   f   s*   	'
r5   ))r   r   Zloggingr*   r1   Zpip._vendor.six.movesr   Zpip._internal.exceptionsr   r   Zpip._internal.utilsr   Zpip._internal.utils.compatr   r   Zpip._internal.utils.miscr   r	   Zpip._internal.utils.typingr
   typingr   r   r   r   r   r   r   r{   strr   Z	getLoggerr   rg   r   r!   r3   r-   r4   objectr5   r   r   r   r   <module>   s6   $


	