U
    «ÃT_Ž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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$eräd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   ú?/tmp/pip-unpacked-wheel-8u7dkzi1/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   Úerror_messager   r   r   Ú_disassemble_key7   s    ÿýr"   ÚuserÚglobalÚ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>Ú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_filesO   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‡  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   ©r0   Úvariantr   r   r   Ú
<dictcomp>Š   s     z*Configuration.__init__.<locals>.<dictcomp>c                 S   s   i | ]
}|i “qS r   r   rB   r   r   r   rD   �   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)ÚselfrI   rJ   Ú_valid_load_only©Ú	__class__r   r   rF   t   s0    ÿÿ    ÿ
ÿÿzConfiguration.__init__c                 C   s   |   ¡  | js|  ¡  dS )zELoads configuration from configuration files and environment
        N)Ú_load_config_filesrI   Ú_load_environment_vars©rP   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   )rJ   ÚAssertionErrorÚ_get_parser_to_modifyÚ
IndexErrorrV   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ÚitemsrV   r   r   r   r]   ¦   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)r\   ÚKeyErrorr   r   )rP   Ú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_onlyrY   r"   Úhas_sectionÚadd_sectionÚsetrN   rJ   Ú_mark_as_modified)rP   r`   Ú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	| 
|¡ƒ}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.
        r^   NFz4Fatal Internal error [id=1]. Please report as a bug.)rb   rN   rJ   r   r   rY   r"   rc   Úremove_optionÚiterr]   ÚnextÚStopIterationÚremove_sectionrf   )	rP   r`   rh   ri   rj   r   Úmodified_somethingÚ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)
rb   rO   ÚloggerÚinfor   r,   r-   ÚdirnameÚopenÚwrite)rP   rh   ri   Ú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)rJ   r   rv   ÚdebugrV   r   r   r   rb     s    
z$Configuration._ensure_have_load_onlyc                 C   s$   i }| j D ]}| | j| ¡ q
|S )z<A dictionary representing the loaded configuration.
        )rK   ÚupdaterN   )rP   ÚretvalrC   r   r   r   r\   	  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_filesr8   r*   r,   Údevnullrv   r}   r]   rJ   Ú
_load_filerM   Úappend)rP   Úconfig_filesrC   Úfilesrh   ri   r   r   r   rT     s"    ÿ  ÿz Configuration._load_config_filesc                 C   sL   t  d||¡ |  |¡}| ¡ D ]&}| |¡}| j|  |  ||¡¡ q |S )Nz'For variant '%s', will try loading '%s')rv   r}   Ú_construct_parserÚsectionsr]   rN   r~   Ú_normalized_keys)rP   rC   rh   ri   rj   r]   r   r   r   rƒ   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)Úreasonrh   )Úerror)r   ÚRawConfigParserr,   r-   ÚexistsÚreadÚUnicodeDecodeErrorr   r   ÚlocaleÚgetpreferredencodingÚError)rP   rh   ri   r‹   r   r   r   r‡   =  s    ÿü
zConfiguration._construct_parserc                 C   s"   | j tj  |  d|  ¡ ¡¡ dS )z7Loads configuration from environment variables
        z:env:N)rN   r8   r+   r~   r‰   Ú_get_environ_varsrV   r   r   r   rU   T  s    ÿz$Configuration._load_environment_varsc                 C   s.   i }|D ] \}}|d t |ƒ }|||< q|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   )rP   rj   r]   Ú
normalizedr   rs   r`   r   r   r   r‰   \  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_ÚPIP_é   N)r,   Úenvironr]   r   r   rL   )rP   r`   rs   Ú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.
        ÚPIP_CONFIG_FILEN)r,   r—   Úgetr8   r*   r=   r(   rI   r-   r�   r'   r)   )rP   Úconfig_filer…   Úshould_load_user_configr   r   r   r�   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.r?   )rM   rJ   r   )rP   Úparsersr   r   r   rY   ”  s    ÿz#Configuration._get_parser_to_modifyc                 C   s"   ||f}|| j kr| j  |¡ d S )N)rO   r„   )rP   rh   ri   Úfile_parser_tupler   r   r   rf   ¢  s    
zConfiguration._mark_as_modified)N)Ú__name__Ú
__module__Ú__qualname__Ú__doc__rF   rW   r[   r]   ra   rk   rt   r|   rb   Úpropertyr\   rT   rƒ   r‡   rU   r‰   r“   r�   rY   rf   Ú__classcell__r   r   rR   r   r>   f   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Ÿ   rv   r   r"   r8   r/   r=   Úobjectr>   r   r   r   r   Ú<module>   s6   $


û	