3
;p_#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j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*   | j  jdd} | j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-ofl94hr3/pip/pip/_internal/configuration.py_normalize_name*   s    
r   c             C   s&   d| krdj | }t|| jddS )N.zbKey does not contain dot separated section and key. Perhaps you wanted to use 'global.{}' instead?   )formatr   split)r   error_messager   r   r   _disassemble_key4   s
    r"   userglobalsiteenvzenv-var)USERGLOBALSITEENVENV_VARzpip.inizpip.confc              C   sp   dd t jdD } tjjtjt}tjjtdt	r8dndt}tjjt j
dt}tj| tj|gtj||giS )Nc             S   s   g | ]}t jj|tqS r   )ospathjoinCONFIG_BASENAME).0r-   r   r   r   
<listcomp>O   s   z+get_configuration_files.<locals>.<listcomp>pip~z.pip)r   site_config_dirsr,   r-   r.   sysprefixr/   r   r   user_config_dirkindsr(   r)   r'   )global_config_filessite_config_filelegacy_config_filenew_config_filer   r   r   get_configuration_filesL   s    
r=   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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| j  tjtjtjd g}||krJtdjdj	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, r   versionhelpc             S   s   i | ]
}g |qS r   r   )r0   variantr   r   r   
<dictcomp>   s   z*Configuration.__init__.<locals>.<dictcomp>c             S   s   i | ]
}i |qS r   r   )r0   rA   r   r   r   rB      s   )superr>   __init__r8   r'   r(   r)   r   r   r.   mapreprisolated	load_onlyr*   r+   _override_order_ignore_env_names_parsers_config_modified_parsers)selfrH   rI   _valid_load_only)	__class__r   r   rE   q   s    
zConfiguration.__init__c             C   s   | j   | js| j  dS )zELoads configuration from configuration files and environment
        N)_load_config_filesrH   _load_environment_vars)rO   r   r   r   load   s    zConfiguration.loadc             C   s8   | j dk	stdy| j 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   )rI   AssertionError_get_parser_to_modify
IndexError)rO   r   r   r   get_file_to_edit   s    zConfiguration.get_file_to_editc             C   s
   | j j S )z`Returns key-value pairs like dict.items() representing the loaded
        configuration
        )_dictionaryitems)rO   r   r   r   rZ      s    zConfiguration.itemsc             C   s2   y
| j | S  tk
r,   tdj|Y nX dS )z,Get a value from the configuration.
        zNo such key - {}N)rY   KeyErrorr   r   )rO   keyr   r   r   	get_value   s    
zConfiguration.get_valuec             C   st   | j   | jst| j \}}|dk	rTt|\}}|j|sF|j| |j||| || j| j |< | j	|| dS )z-Modify a value in the configuration.
        N)
_ensure_have_load_onlyrI   rU   rV   r"   has_sectionadd_sectionsetrM   _mark_as_modified)rO   r\   valuefnameparsersectionr   r   r   r   	set_value   s    


zConfiguration.set_valuec             C   s   | j   | jst|| j| j kr0tdj|| j \}}|dk	rt|\}}|j|od|j	||sntd|j
|s|j| | j|| | j| j |= dS )z#Unset a value in the configuration.zNo such key - {}Nz4Fatal Internal error [id=1]. Please report as a bug.)r^   rI   rU   rM   r   r   rV   r"   r_   remove_optionrZ   remove_sectionrb   )rO   r\   rd   re   rf   r   r   r   r   unset_value   s    



zConfiguration.unset_valuec          
   C   s\   | j   xN| jD ]D\}}tjd| ttjj| t|d}|j	| W dQ R X qW dS )z*Save the current in-memory state.
        zWriting to %swN)
r^   rN   loggerinfor   r,   r-   dirnameopenwrite)rO   rd   re   fr   r   r   save   s    zConfiguration.savec             C   s$   | j d krtdtjd| j  d S )Nz'Needed a specific file to be modifying.z$Will be working with %s variant only)rI   r   rl   debug)rO   r   r   r   r^      s    
z$Configuration._ensure_have_load_onlyc             C   s(   i }x| j D ]}|j| j|  qW |S )z<A dictionary representing the loaded configuration.
        )rJ   updaterM   )rO   retvalrA   r   r   r   rY      s    zConfiguration._dictionaryc             C   s   t | j }|tj dd tjgkr4tjd dS xf|j D ]Z\}}xP|D ]H}| j	dk	rt|| j	krttjd|| qL| j
||}| j| 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_filesr8   r*   r,   devnullrl   rs   rZ   rI   
_load_filerL   append)rO   config_filesrA   filesrd   re   r   r   r   rR   	  s    

z Configuration._load_config_filesc             C   sP   t jd|| | j|}x2|j D ]&}|j|}| j| j| j|| q"W |S )Nz'For variant '%s', will try loading '%s')rl   rs   _construct_parsersectionsrZ   rM   rt   _normalized_keys)rO   rA   rd   re   rf   rZ   r   r   r   ry   $  s    

zConfiguration._load_filec             C   s   t j }tjj|r|y|j| W nX tk
rN   tdjt	j
d|dY n. t jk
rz } zt|dW Y d d }~X nX |S )Nzcontains invalid {} charactersF)reasonrd   )error)r   RawConfigParserr,   r-   existsreadUnicodeDecodeErrorr   r   localegetpreferredencodingError)rO   rd   re   r   r   r   r   r}   /  s    
zConfiguration._construct_parserc             C   s"   | j tj j| jd| j  dS )z7Loads configuration from environment variables
        z:env:N)rM   r8   r+   rt   r   get_environ_vars)rO   r   r   r   rS   F  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   )rO   rf   rZ   
normalizedr   valr\   r   r   r   r   N  s
    zConfiguration._normalized_keysc             c   sV   xPt jj D ]B\}}|jdo2|dd j | jk}|r|dd j |fV  qW dS )z@Returns a generator with all environmental vars with prefix PIP_PIP_   N)r,   environrZ   r   r   rK   )rO   r\   r   should_be_yieldedr   r   r   r   [  s
    
zConfiguration.get_environ_varsc             c   s   t j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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.
        PIP_CONFIG_FILEN)r,   r   getr8   r*   r=   r(   rH   r-   r   r'   r)   )rO   config_filer{   should_load_user_configr   r   r   rw   g  s    	zConfiguration.iter_config_filesc             C   s
   | j | S )z#Get values present in a config file)rM   )rO   rA   r   r   r   get_values_in_config  s    z"Configuration.get_values_in_configc             C   s*   | j s
t| j| j  }|s"td|d S )Nz4Fatal Internal error [id=2]. Please report as a bug.r   rC   )rI   rU   rL   r   )rO   parsersr   r   r   rV     s    
z#Configuration._get_parser_to_modifyc             C   s"   ||f}|| j kr| j j| d S )N)rN   rz   )rO   rd   re   file_parser_tupler   r   r   rb     s    
zConfiguration._mark_as_modifiedc             C   s   dj | jj| jS )Nz{}({!r}))r   rQ   __name__rY   )rO   r   r   r   __repr__  s    zConfiguration.__repr__)N)r   
__module____qualname____doc__rE   rT   rX   rZ   r]   rg   rj   rr   r^   propertyrY   rR   ry   r}   rS   r   r   rw   r   rV   rb   r   __classcell__r   r   )rQ   r   r>   c   s,   	r>   ))r   r   loggingr,   r5   Zpip._vendor.six.movesr   pip._internal.exceptionsr   r   Zpip._internal.utilsr   pip._internal.utils.compatr   r   pip._internal.utils.miscr   r	   pip._internal.utils.typingr
   typingr   r   r   r   r   r   r   r   strr   	getLoggerr   rl   r   r"   r8   r/   r=   objectr>   r   r   r   r   <module>   s4   $


