B
    Wc\3                 @   s   d 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	m
Z
 ddlmZmZmZ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&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)six)configparser)ConfigurationError!ConfigurationFileCouldNotBeLoaded)legacy_config_filenew_config_filerunning_under_virtualenvsite_config_filesvenv_config_file)
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.7/site-packages/pip/_internal/configuration.py_normalize_name+   s    
r   c             C   s   |  ddS )N.   )split)r   r   r   r   _disassemble_key5   s    r#   userglobalvenvenvzenv-var)USERGLOBALVENVENVENV_VARc                   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   ).0variantr   r   r   
<dictcomp>h   s   z*Configuration.__init__.<locals>.<dictcomp>c             S   s   i | ]
}i |qS r   r   )r1   r2   r   r   r   r3   k   s   )superr-   __init__kindsr(   r)   r*   r   formatjoinmapreprisolated	load_onlyr+   r,   _override_order_ignore_env_names_parsers_config_modified_parsers)selfr;   r<   Z_valid_load_only)	__class__r   r   r5   R   s    
zConfiguration.__init__c             C   s   |    | js|   dS )zELoads configuration from configuration files and environment
        N)_load_config_filesr;   _load_environment_vars)rB   r   r   r   loadp   s    zConfiguration.loadc             C   s8   | j dk	stdy|  d S  tk
r2   dS X dS )z@Returns the file with highest priority in configuration
        Nz)Need to be specified a file to be editingr   )r<   AssertionError_get_parser_to_modify
IndexError)rB   r   r   r   get_file_to_editx   s    zConfiguration.get_file_to_editc             C   s
   | j  S )z`Returns key-value pairs like dict.items() representing the loaded
        configuration
        )_dictionaryitems)rB   r   r   r   rL      s    zConfiguration.itemsc             C   s2   y
| j | S  tk
r,   td|Y nX dS )z,Get a value from the configuration.
        zNo such key - {}N)rK   KeyErrorr   r7   )rB   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_onlyrH   r#   has_sectionZadd_sectionsetr@   r<   _mark_as_modified)rB   rN   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	|
|}y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.
        zNo such key - {}NFz4Fatal Internal error [id=1]. Please report as a bug.)rP   r@   r<   r   r7   rH   r#   rQ   Zremove_optioniterrL   r   nextStopIterationZremove_sectionrS   )	rB   rN   rU   rV   rW   r   Zmodified_somethingZsection_itervalr   r   r   unset_value   s*    


zConfiguration.unset_valuec          
   C   s\   |    xN| jD ]D\}}td| ttj| t|d}|	| W dQ R X qW dS )z)Save the currentin-memory state.
        zWriting to %swN)
rP   rA   loggerinfor   ospathdirnameopenwrite)rB   rU   rV   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)r<   r   r_   debug)rB   r   r   r   rP      s    
z$Configuration._ensure_have_load_onlyc             C   s(   i }x| j D ]}|| j|  qW |S )z<A dictionary representing the loaded configuration.
        )r=   updater@   )rB   Zretvalr2   r   r   r   rK      s    zConfiguration._dictionaryc             C   s   t |  }|tj dd tjgkr4td dS xf| D ]Z\}}xP|D ]H}| j	dk	rt|| j	krttd|| qL| 
||}| j| ||f qLW q>W 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_filesr6   r+   ra   devnullr_   rh   rL   r<   
_load_filer?   append)rB   Zconfig_filesr2   filesrU   rV   r   r   r   rD      s    

z Configuration._load_config_filesc             C   sP   t d|| | |}x2| D ]&}||}| j| | || q"W |S )Nz'For variant '%s', will try loading '%s')r_   rh   _construct_parserZsectionsrL   r@   ri   _normalized_keys)rB   r2   rU   rV   rW   rL   r   r   r   rm     s    

zConfiguration._load_filec          
   C   s   t  }tj|r|y|| W nX tk
rN   tdt	
d|dY n. t jk
rz } zt|dW d d }~X Y nX |S )Nzcontains invalid {} charactersF)reasonrU   )error)r   RawConfigParserra   rb   existsreadUnicodeDecodeErrorr   r7   localeZgetpreferredencodingError)rB   rU   rV   rs   r   r   r   rp     s    
zConfiguration._construct_parserc             C   s"   | j tj | d|   dS )z7Loads configuration from environment variables
        z:env:N)r@   r6   r,   ri   rq   _get_environ_vars)rB   r   r   r   rE   2  s    z$Configuration._load_environment_varsc             C   s2   i }x(|D ] \}}|d t | }|||< q
W |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   )rB   rW   rL   Z
normalizedr   r\   rN   r   r   r   rq   :  s
    zConfiguration._normalized_keysc             c   sV   xPt j D ]B\}}|do2|dd  | jk}|r|dd  |fV  qW dS )z@Returns a generator with all environmental vars with prefix PIP_ZPIP_   N)ra   environrL   r   r   r>   )rB   rN   r\   Zshould_be_yieldedr   r   r   rz   G  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jttfV  | j oZ|oXt j	
| }|rptjttgfV  t rtjtg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)ra   r|   getr6   r+   r)   listr	   r;   rb   ru   r(   r   r   r   r*   r
   )rB   Zconfig_fileZshould_load_user_configr   r   r   rk   S  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.r.   )r?   r<   r   )rB   Zparsersr   r   r   rH   q  s
    z#Configuration._get_parser_to_modifyc             C   s"   ||f}|| j kr| j | d S )N)rA   rn   )rB   rU   rV   Zfile_parser_tupler   r   r   rS     s    
zConfiguration._mark_as_modified)N)__name__
__module____qualname____doc__r5   rF   rJ   rL   rO   rX   r]   rg   rP   propertyrK   rD   rm   rp   rE   rq   rz   rk   rH   rS   __classcell__r   r   )rC   r   r-   D   s(   	'r-   ))r   rx   Zloggingra   Zpip._vendorr   Zpip._vendor.six.movesr   Zpip._internal.exceptionsr   r   Zpip._internal.locationsr   r   r   r	   r
   Zpip._internal.utils.miscr   r   Zpip._internal.utils.typingr   typingr   r   r   r   r   r   r   rt   strr   Z	getLoggerr   r_   r   r#   r6   objectr-   r   r   r   r   <module>   s.   $


