B
    ãUvg»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r´d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	rÂt|ƒ\}}d}| |¡r`| ||¡}|rºt	| 
|¡ƒ}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 )z×Normalizes 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ƒ r„t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.   $


