B
    Uvg3                 @   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   </tmp/pip-install-r_9ig3yj/pip/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<   _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   rM      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)rL   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_onlyrI   r#   has_sectionadd_sectionsetr@   r<   _mark_as_modified)rB   rO   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.)rQ   r@   r<   r   r7   rI   r#   rR   remove_optioniterrM   r   nextStopIterationremove_sectionrU   )	rB   rO   rW   rX   rY   r   modified_something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)
rQ   rA   loggerinfor   ospathdirnameopenwrite)rB   rW   rX   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   re   debug)rB   r   r   r   rQ      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   retvalr2   r   r   r   rL      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+   rg   devnullre   rn   rM   r<   
_load_filer?   append)rB   config_filesr2   filesrW   rX   r   r   r   rE      s    

z Configuration._load_config_filesc             C   sP   t d|| | |}x2| D ]&}||}| j| | || q"W |S )Nz'For variant '%s', will try loading '%s')re   rn   _construct_parsersectionsrM   r@   ro   _normalized_keys)rB   r2   rW   rX   rY   rM   r   r   r   rt     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)reasonrW   )error)r   RawConfigParserrg   rh   existsreadUnicodeDecodeErrorr   r7   localegetpreferredencodingError)rB   rW   rX   r|   r   r   r   rx     s    
zConfiguration._construct_parserc             C   s"   | j tj | d|   dS )z7Loads configuration from environment variables
        z:env:N)r@   r6   r,   ro   rz   _get_environ_vars)rB   r   r   r   rF   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   rY   rM   
normalizedr   rb   rO   r   r   r   rz   :  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_PIP_   N)rg   environrM   r   r   r>   )rB   rO   rb   should_be_yieldedr   r   r   r   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.
        PIP_CONFIG_FILEN)rg   r   getr6   r+   r)   listr	   r;   rh   r~   r(   r   r   r   r*   r
   )rB   config_fileshould_load_user_configr   r   r   rr   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   parsersr   r   r   rI   q  s
    z#Configuration._get_parser_to_modifyc             C   s"   ||f}|| j kr| j | d S )N)rA   ru   )rB   rW   rX   file_parser_tupler   r   r   rU     s    
zConfiguration._mark_as_modified)N)__name__
__module____qualname____doc__r5   rG   rK   rM   rP   rZ   rc   rm   rQ   propertyrL   rE   rt   rx   rF   rz   r   rr   rI   rU   __classcell__r   r   )rD   r   r-   D   s(   	'r-   ))r   r   loggingrg   pip._vendorr   Zpip._vendor.six.movesr   pip._internal.exceptionsr   r   pip._internal.locationsr   r   r   r	   r
   pip._internal.utils.miscr   r   pip._internal.utils.typingr   typingr   r   r   r   r   r   r   r}   strr   	getLoggerr   re   r   r#   r6   objectr-   r   r   r   r   <module>   s.   $


