U
    „~$hµ6  ã                   @   s>  d Z ddlZddlZddlZddlZddlmZmZmZm	Z	m
Z
mZmZ ddlmZmZ ddlmZ ddlmZ ddlmZ ddlmZmZ ejZe
d	eƒZer¤d
ndZdZedddddd�Zejej ej!ej"ej#fZ$ej ejej!fZ%ee&ƒZ'eedœdd„Z(ee	e dœdd„Z)eee	e f dœdd„Z*G dd„ dƒ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)ÚAnyÚDictÚIterableÚListÚNewTypeÚOptionalÚTuple)ÚConfigurationErrorÚ!ConfigurationFileCouldNotBeLoaded)Úappdirs)ÚWINDOWS)Ú	getLogger)Ú
ensure_dirÚenumÚKindzpip.inizpip.conf)ÚversionÚhelpÚuserÚglobalÚsiteÚenvzenv-var)ÚUSERÚGLOBALÚSITEÚENVÚENV_VAR)ÚnameÚreturnc                 C   s*   |   ¡  dd¡} |  d¡r&| dd… } | S )zAMake a name consistent regardless of source (environment or file)Ú_ú-z--é   N)ÚlowerÚreplaceÚ
startswith)r   © r$   ú?/tmp/pip-unpacked-wheel-g27rp152/pip/_internal/configuration.pyÚ_normalize_name2   s    
r&   c                 C   s(   d| krd| › d�}t |ƒ‚|  dd¡S )NÚ.zVKey does not contain dot separated section and key. Perhaps you wanted to use 'global.z
' instead?é   )r	   Úsplit)r   Úerror_messager$   r$   r%   Ú_disassemble_key:   s
    
ÿr+   ©r   c                  C   st   dd„ t  d¡D ƒ} tj tjt¡}tj tj d¡t	r<d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>E   s    z+get_configuration_files.<locals>.<listcomp>Úpipú~z.pip)r   Úsite_config_dirsr-   r.   r/   ÚsysÚprefixr0   Ú
expanduserr   Úuser_config_dirÚkindsr   r   r   )Úglobal_config_filesÚsite_config_fileÚlegacy_config_fileÚnew_config_filer$   r$   r%   Úget_configuration_filesD   s"    ÿ

ý   ýr?   c                       s¼  e Zd ZdZd6eee ddœ‡ fdd„Zddœdd„Zee	 dœd	d
„Z
eee	ef  dœdd„Ze	edœdd„Ze	eddœdd„Ze	ddœdd„Zddœdd„Zddœdd„Zeee	ef dœdd„ƒZddœdd„Zee	edœdd„Ze	ed œd!d"„Zddœd#d$„Ze	eee	ef  ee	ef d%œd&d'„Zeee	e	f  dœd(d)„Zeeeee	 f  dœd*d+„Zeee	ef d,œd-d.„Z ee	ef dœd/d0„Z!e	edd1œd2d3„Z"e	dœd4d5„Z#‡  Z$S )7Ú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.
    N)ÚisolatedÚ	load_onlyr   c                    sj   t ƒ  ¡  |d k	r4|tkr4td d tttƒ¡¡ƒ‚|| _|| _	dd„ t
D ƒ| _dd„ t
D ƒ| _g | _d S )Nz5Got invalid value for load_only - should be one of {}z, c                 S   s   i | ]
}|g “qS r$   r$   ©r1   Úvariantr$   r$   r%   Ú
<dictcomp>r   s     z*Configuration.__init__.<locals>.<dictcomp>c                 S   s   i | ]
}|i “qS r$   r$   rC   r$   r$   r%   rE   u   s     )ÚsuperÚ__init__ÚVALID_LOAD_ONLYr	   Úformatr/   ÚmapÚreprrA   rB   ÚOVERRIDE_ORDERÚ_parsersÚ_configÚ_modified_parsers)ÚselfrA   rB   ©Ú	__class__r$   r%   rG   e   s     
ÿÿÿÿzConfiguration.__init__r,   c                 C   s   |   ¡  | js|  ¡  dS )z<Loads configuration from configuration files and environmentN)Ú_load_config_filesrA   Ú_load_environment_vars©rP   r$   r$   r%   Úloadz   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 )z7Returns the file with highest priority in configurationNz)Need to be specified a file to be editingr   )rB   ÚAssertionErrorÚ_get_parser_to_modifyÚ
IndexErrorrU   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ÚitemsrU   r$   r$   r%   r\   ‰   s    zConfiguration.items)Úkeyr   c                 C   sH   |}t |ƒ}z| j| W S  tk
rB   t|ƒ td|› �ƒ‚Y nX dS )z#Get a value from the configuration.úNo such key - N)r&   r[   ÚKeyErrorr+   r	   )rP   r]   Úorig_keyr$   r$   r%   Ú	get_value�   s    zConfiguration.get_value)r]   Úvaluer   c                 C   s|   t |ƒ}|  ¡  | jst‚|  ¡ \}}|dk	r\t|ƒ\}}| |¡sN| |¡ | |||¡ || j	| j |< |  
||¡ dS )z$Modify a value in the configuration.N)r&   Ú_ensure_have_load_onlyrB   rW   rX   r+   Úhas_sectionÚadd_sectionÚsetrN   Ú_mark_as_modified)rP   r]   rb   ÚfnameÚparserÚsectionr   r$   r$   r%   Ú	set_value›   s    


zConfiguration.set_valuec                 C   s¬   |}t |ƒ}|  ¡  | jst‚|| j| j kr<td|› �ƒ‚|  ¡ \}}|dk	ršt|ƒ\}}| |¡rr| 	||¡sztdƒ‚| 
|¡sŽ| |¡ |  ||¡ | j| j |= dS )z#Unset a value in the configuration.r^   Nz4Fatal Internal error [id=1]. Please report as a bug.)r&   rc   rB   rW   rN   r	   rX   r+   rd   Úremove_optionr\   Úremove_sectionrg   )rP   r]   r`   rh   ri   rj   r   r$   r$   r%   Úunset_value®   s(    
ÿ
ÿÿ

zConfiguration.unset_valuec                 C   s”   |   ¡  | jD ]€\}}t d|¡ ttj |¡ƒ z$t|dƒ�}| 	|¡ W 5 Q R X W q t
k
rŒ } ztd|› d|› �ƒ‚W 5 d}~X Y qX qdS )z!Save the current in-memory state.zWriting to %sÚwz:An error occurred while writing to the configuration file z: N)rc   rO   ÚloggerÚinfor   r-   r.   ÚdirnameÚopenÚwriteÚOSErrorr	   )rP   rh   ri   ÚfÚerrorr$   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)rB   r	   rp   ÚdebugrU   r$   r$   r%   rc   ã   s    
z$Configuration._ensure_have_load_onlyc                 C   s"   i }t D ]}| | j| ¡ q|S )z3A dictionary representing the loaded configuration.)rL   ÚupdaterN   )rP   ÚretvalrD   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 )z,Loads configuration from configuration filesr   r(   zZSkipping loading configuration files due to environment's PIP_CONFIG_FILE being os.devnullNz Skipping file '%s' (variant: %s))ÚdictÚiter_config_filesr:   r   r-   Údevnullrp   ry   r\   rB   Ú
_load_filerM   Úappend)rP   Úconfig_filesrD   Úfilesrh   ri   r$   r$   r%   rS   ô   s    ÿz Configuration._load_config_files)rD   rh   r   c                 C   sL   t  d||¡ |  |¡}| ¡ D ]&}| |¡}| j|  |  ||¡¡ q |S )Nz'For variant '%s', will try loading '%s')rp   ÚverboseÚ_construct_parserÚsectionsr\   rN   rz   Ú_normalized_keys)rP   rD   rh   ri   rj   r\   r$   r$   r%   r     s    

zConfiguration._load_file)rh   r   c              
   C   sŠ   t  ¡ }tj |¡r†t d¡}z|j||d� W nT tk
rX   t	d|› d�|d�‚Y n. t j
k
r„ } zt	|d�‚W 5 d }~X Y nX |S )NF)Úencodingzcontains invalid z characters)Úreasonrh   )rw   )ÚconfigparserÚRawConfigParserr-   r.   ÚexistsÚlocaleÚgetpreferredencodingÚreadÚUnicodeDecodeErrorr
   ÚError)rP   rh   ri   Zlocale_encodingrw   r$   r$   r%   r„     s    

þ
zConfiguration._construct_parserc                 C   s"   | j tj  |  d|  ¡ ¡¡ dS )z.Loads configuration from environment variablesz:env:N)rN   r:   r   rz   r†   Úget_environ_varsrU   r$   r$   r%   rT   *  s    ÿz$Configuration._load_environment_vars)rj   r\   r   c                 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   Úvalr]   r$   r$   r%   r†   0  s
    
zConfiguration._normalized_keysc                 c   sD   t j ¡ D ]4\}}| d¡r
|dd…  ¡ }|tkr
||fV  q
dS )z@Returns a generator with all environmental vars with prefix PIP_ÚPIP_é   N)r-   Úenvironr\   r#   r!   ÚENV_NAMES_IGNORED)rP   r]   r“   r   r$   r$   r%   r‘   >  s
    
zConfiguration.get_environ_varsc                 c   s�   t j dd¡}tƒ }tj|tj fV  | j o>|o<t j |¡ }|rVtj	|tj	 fV  tj
|tj
 fV  |dk	r€tj|gfV  ntjg fV  dS )a�  Yields variant and configuration files associated with it.

        This should be treated like items of a dictionary. The order
        here doesn't affect what gets overridden. That is controlled
        by OVERRIDE_ORDER. However this does control the order they are
        displayed to the user. It's probably most ergonomic to display
        things in the same order as OVERRIDE_ORDER
        ÚPIP_CONFIG_FILEN)r-   r–   Úgetr?   r:   r   rA   r.   r‹   r   r   r   )rP   Zenv_config_filer�   Úshould_load_user_configr$   r$   r%   r}   G  s    ÿzConfiguration.iter_config_files)rD   r   c                 C   s
   | j | S )z#Get values present in a config file)rN   )rP   rD   r$   r$   r%   Úget_values_in_configg  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.éÿÿÿÿ)rB   rW   rM   r	   )rP   Úparsersr$   r$   r%   rX   k  s    
ÿz#Configuration._get_parser_to_modify)rh   ri   r   c                 C   s"   ||f}|| j kr| j  |¡ d S )N)rO   r€   )rP   rh   ri   Úfile_parser_tupler$   r$   r%   rg   y  s    
zConfiguration._mark_as_modifiedc                 C   s   | j j› d| j›d�S )Nú(ú))rR   Ú__name__r[   rU   r$   r$   r%   Ú__repr__~  s    zConfiguration.__repr__)N)%r¡   Ú
__module__Ú__qualname__Ú__doc__Úboolr   r   rG   rV   ÚstrrZ   r   r   r   r\   ra   rk   rn   rx   rc   Úpropertyr   r[   rS   rŠ   r   r„   rT   r†   r‘   r   r}   r›   rX   rg   r¢   Ú__classcell__r$   r$   rQ   r%   r@   W   s4   	
 
þ	 r@   ),r¥   r‰   rŒ   r-   r6   Útypingr   r   r   r   r   r   r   Úpip._internal.exceptionsr	   r
   Zpip._internal.utilsr   Úpip._internal.utils.compatr   Úpip._internal.utils.loggingr   Úpip._internal.utils.miscr   r   rŠ   r§   r   r0   r—   r:   r   r   r   r   r   rL   rH   r¡   rp   r&   r+   r?   r@   r$   r$   r$   r%   Ú<module>   s8   $
û
