B
    QYP!                @   s  d Z ddlmZ ddlZddlmZmZ ddlZddlmZ ddl	m
Z
mZmZmZ ddlmZ ddlmZ dd	lmZmZ dd
lmZ ddl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# ddl$m%Z% ddl&m'Z'm(Z(m)Z) ddl*m+Z+m,Z,m-Z- ddl.m/Z/ ddl0m1Z1 ddl2m3  m4Z4 ddl5m3  m6Z6 ddl7m3  m8Z8 ddl9m:Z; dZ<dZ=dZ>dZ?dZ@e<e=e>e?e@fZAG dd deBZCdd ZDd*d d!ZEd"d# ZFd$d% ZGG d&d' d'eBZHG d(d) d)eBZIdS )+z/Project class representing a project directory.    )absolute_importN)deepcopycopy)join)EnvSpec_anaconda_default_env_spec_find_importable_spec!_find_out_of_sync_importable_spec)RequirementsRegistry)EnvVarRequirement)CondaEnvRequirementCondaBootstrapEnvRequirement)DownloadRequirement)ServiceRequirement)ProjectCommandall_known_command_attributes)ProjectFile)ProjectLockFile)0_list_relative_paths_for_unignored_project_files)version)CondaLockSet)_null_frontend_new_error_recorderFrontend)	is_stringis_listis_dict)SimpleStatus)slugify)pluginsZconda_app_entryunixwindowsnotebook	bokeh_appc               @   s6   e Zd ZdZdddZedd Zdd	 Zd
d ZdS )ProjectProblemz.A possibly-autofixable problem with a project.NFc	       	      C   sZ   || _ |dkr|| _ndtj||f | _|| _|| _|| _|| _|| _	|| _
|| _dS )zCreate a project problem.Nz%s: %s)Ztext_without_filenametextospathbasename
fix_promptfix_functionno_fix_functiononly_a_suggestionZmaybe_filenameZmaybe_line_numberZmaybe_column_number)	selfr%   filenamer)   r*   r+   r,   line_numbercolumn_number r1   7lib/python3.7/site-packages/anaconda_project/project.py__init__7   s    
zProjectProblem.__init__c             C   s
   | j dk	S )z&True if the problem can be auto-fixed.N)r*   )r-   r1   r1   r2   can_fixN   s    zProjectProblem.can_fixc             C   s   | j dk	r|  |S dS dS )zPerform the auto-fix.N)r*   )r-   projectr1   r1   r2   fixS   s    

zProjectProblem.fixc             C   s   | j dk	r|  |S dS dS )z&Take an action on deciding not to fix.N)r+   )r-   r5   r1   r1   r2   no_fixZ   s    

zProjectProblem.no_fix)NNNNFNN)	__name__
__module____qualname____doc__r3   propertyr4   r6   r7   r1   r1   r1   r2   r$   4   s         
r$   c             C   s<   g }x2| D ]*}t |tr$|| q
|t|d q
W |S )N)r%   )
isinstancer$   append)problemsZnew_problemspr1   r1   r2   _make_problems_into_objectsd   s    

rA   c             C   s   |  t||j||d d S )N)r%   r.   r)   r*   )r>   r$   r.   )r?   	yaml_filer%   r)   r*   r1   r1   r2   _file_problemn   s    rC   c             C   s8   x2|  D ]&}||kr
|td| | jdd q
W d S )NzUnknown field name '%s'T)r%   r.   r,   )keysr>   r$   r.   )project_filer?   Z	yaml_dictZknown_fieldskeyr1   r1   r2   _unknown_field_suggestionsu   s
    rG   c             C   s*   x$| D ]}t |tsdS |jsdS qW dS )NTF)r=   r$   r,   )r?   r@   r1   r1   r2   _fatal_problem}   s    

rH   c               @   s   e Z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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d/d0 Zd1S )2_ConfigCachec             C   sl   || _ |d krt }|| _d | _d| _d | _t | _d | _d| _	d| _
t | _t | _d| _d | _d | _d S )N r   F)directory_pathr
   registrynamedescriptionicondictcommandsdefault_command_nameproject_file_countlock_file_count	env_specs	lock_setslocking_globally_enableddefault_env_spec_nameglobal_base_env_spec)r-   rK   rL   r1   r1   r2   r3      s     z_ConfigCache.__init__c             C   s  |j | jkr|j | jkrd S |j | _|j | _t }g }tj| j}|sX|d| j  |j	r|t
d|j |j|j|jd |j	r|t
d|j |j|j|jd |rn|j	sn|j	snt|||jd t|||jd | || | || | || | || | ||| | ||| | ||| | ||| | ||| | ||| | || || _t|| _tdd | jD | _ d S )Nz&Project directory '%s' does not exist.zSyntax error: %s)r%   r.   r/   r0   )rM   rN   rO   	variables	downloadsservicesrU   rQ   packageschannels	platformsskip_imports)rU   locking_enabledc             S   s   g | ]}|j s|jqS r1   )r,   r%   ).0r@   r1   r1   r2   
<listcomp>   s    z'_ConfigCache.update.<locals>.<listcomp>)!Zchange_countrS   rT   rP   r&   r'   isdirrK   r>   Z	corruptedr$   Zcorrupted_error_messager.   Zcorrupted_maybe_lineZcorrupted_maybe_columnrG   root_update_name_update_description_update_icon_update_lock_sets_update_env_specs_update_variables_update_downloads_update_services_update_conda_env_requirements_update_commands_verify_command_dependenciesrequirementsrA   r?   listproblem_strings)r-   rE   	lock_filerq   r?   Zproject_existsr1   r1   r2   update   sL    

z_ConfigCache.updatec                s   t j| j d|jkr@ fdd}|td|jd  |d |dd }|d k	rt	|srt
||d|  d }n t| dkrt
||d	 d }|d kr }|| _d S )
NrM   c                s   | j d  d S )NrM   )rE   	set_value)r5   )default_namer1   r2   set_name_field   s    z1_ConfigCache._update_name.<locals>.set_name_fieldzThe 'name:' field is missing.zName the project '%s'?)r%   r.   r)   r*   z-name: field should have a string value not %rr   z1name: field is an empty or all-whitespace string.)r&   r'   r(   rK   re   r>   r$   r.   	get_valuer   rC   lenstriprM   )r-   r?   rE   rx   rM   r1   )rw   r2   rf      s$    

z_ConfigCache._update_namec             C   sF   | dd }|d k	r0t|s0t||d|  d }|d kr<d}|| _d S )NrN   z4description: field should have a string value not %rrJ   )ry   r   rC   rN   )r-   r?   rE   Zdescr1   r1   r2   rg      s    z _ConfigCache._update_descriptionc             C   sp   | dd }|d k	r0t|s0t||d|  d }|d k	rftj| j|}tj|sf|d|  d }|| _	d S )NrO   z-icon: field should have a string value not %rzIcon file %s does not exist.)
ry   r   rC   r&   r'   r   rK   isfiler>   rO   )r-   r?   rE   rO   r1   r1   r2   rh      s    z_ConfigCache._update_iconc             C   s(   |j |krg ||j < ||j  | d S )N)rM   r>   )r-   rq   env_specrequirementr1   r1   r2   _add_requirement  s    

z_ConfigCache._add_requirementc       	      C   sX   | |}||||| j| x6| j D ](}| d|j|gd }|||||| q(W d S )NrU   )ry   rY   rU   valuesrM   )	r-   rq   r?   rE   Z	dict_nameZupdaterZglobal_dictr}   env_dictr1   r1   r2   _update_requirements  s
    
z!_ConfigCache._update_requirementsc             C   s   |  |||d| j d S )NrZ   )r   _update_variables_for_env_spec)r-   rq   r?   rE   r1   r1   r2   rk     s    z_ConfigCache._update_variablesc             C   s   |  |||d| j d S )Nr[   )r   _update_downloads_for_env_spec)r-   rq   r?   rE   r1   r1   r2   rl     s    z_ConfigCache._update_downloadsc             C   s   |  |||d| j d S )Nr\   )r   _update_services_for_env_spec)r-   rq   r?   rE   r1   r1   r2   rm   #  s    z_ConfigCache._update_servicesc                sj   fdd}|d krnLt |rx| D ]}||r:q,| dkrZt d| q,|| }|d krpi }	nt |rt|}	n
t|d}	t|	tstt	
|	| r,| j||	}
| |||
 q,W nt|rRx|D ]r}t|r8| dkr
t d| q||rq| jj|t d}
| |||
 qt dj|d qW nt d	j|d
 d S )Nc                s$   | dkrt  d|   dS dS d S )N)ZCONDA_DEFAULT_ENVZCONDA_ENV_PATHCONDA_PREFIXzaEnvironment variable %s is reserved for Conda's use, so it can't appear in the variables section.TF)rC   )rF   )r?   rE   r1   r2   check_conda_reserved'  s
    zI_ConfigCache._update_variables_for_env_spec.<locals>.check_conda_reservedrJ   z9Variable name cannot be empty string, found: '{}' as name)default)optionszSvariables section should contain environment variable names, {item} is not a string)itemz[variables section contains wrong value type {value}, should be dict or list of requirements)value)r   rD   r{   rC   formatr   rP   r=   AssertionErrorr   Z_parse_defaultrL   Zfind_requirement_by_env_varr   r   r   )r-   rq   r?   rE   r}   rZ   r   rF   Zraw_optionsr   r~   r   r1   )r?   rE   r2   r   &  sT    





z+_ConfigCache._update_variables_for_env_specc       
      C   s   |d krd S t |s.t||dt| d S xh| D ]\\}}| dkr`t||d| q8t|||}|d krxq8t| jf|}	| 	|||	 q8W d S )Nz5'downloads:' section should be a dictionary, found {}rJ   z9Download name cannot be empty string, found: '{}' as name)
r   rC   r   repritemsr{   r   _parserL   r   )
r-   rq   r?   rE   r}   r[   varnamer   Zdownload_kwargsr~   r1   r1   r2   r   d  s     z+_ConfigCache._update_downloads_for_env_specc             C   s   |d krd S t |s.t||dt| d S x| D ]\}}| dkr`t||d| q8t|||}|d krxq8|d }	| jj	f |s|
d||	 q8| jjf |}
t|
tstd|
jkst| |||
 q8W d S )Nz^'services:' section should be a dictionary from environment variable to service type, found {}rJ   z8Service name cannot be empty string, found: '{}' as nameservice_typez$Service {} has an unknown type '{}'.type)r   rC   r   r   r   r{   r   r   rL   Z$can_find_requirement_by_service_typer>   Z find_requirement_by_service_typer=   r   r   r   )r-   rq   r?   rE   r}   r\   r   r   Zservice_kwargsr   r~   r1   r1   r2   r   y  s.    z*_ConfigCache._update_services_for_env_specc             C   s   | |g }t|s2t||d|||f  g g fS g }g }	xN|D ]F}
t|
r\||
  q@||
rp|	|
 q@t||d|||
f  q@W ||	fS )Nz+%s: value should be a list of %ss, not '%r'z/%s: value should be a %s (as a string) not '%r')getr   rC   r   r>   r{   )r-   r?   rB   parent_dictrF   whatspecial_filterr   ZcleanedZspecialr   r1   r1   r2   _parse_string_list_with_special  s    
z,_ConfigCache._parse_string_list_with_specialc             C   s   | j |||||dd dd S )Nc             S   s   dS )NFr1   )xr1   r1   r2   <lambda>  s    z1_ConfigCache._parse_string_list.<locals>.<lambda>)r   r   )r   )r-   r?   rB   r   rF   r   r1   r1   r2   _parse_string_list  s    z_ConfigCache._parse_string_listc       	      C   sl   |  |||dd}t|\}}}x&|D ]}|td| |jdd q(W x|D ]}t||d|  qPW |S )Nr_   zplatform namezXUnusual platform name '%s' may be a typo (more usual examples: linux-64, osx-64, win-64)T)r%   r.   r,   zHPlatform name '%s' is invalid (valid examples: linux-64, osx-64, win-64))r   	conda_apiZvalidate_platform_listr>   r$   r.   rC   )	r-   r?   rB   r   r_   unknownZinvaliduir1   r1   r2   _parse_platforms  s    

z_ConfigCache._parse_platformsc          	   C   s   |  ||||ddd \}}x.|D ]&}t|}|d kr"t||d|  q"W g }	x(|D ] }
| |||
dd}|	| qVW x.|	D ]&}t|}|d krt||d|  qW ||	fS )Nzpackage namec             S   s   t | od| kS )Npip)r   )r   r1   r1   r2   r     s    z._ConfigCache._parse_packages.<locals>.<lambda>z!invalid package specification: %sr   zpip package namez!invalid pip package specifier: %s)r   r   
parse_specrC   r   extendpip_api)r-   r?   rB   rF   r   depsZ	pip_dictsZdepparsedpip_depsZpip_dictZpip_listr1   r1   r2   _parse_packages  s    




z_ConfigCache._parse_packagesc          	   C   s  t  | _d| _|dgd}t|ts8t||d|  n|| _|dgi }t|snt||dt	| d S xv|
 D ]h\}}t|st||d||f  qzt|||d |d	| j}t|tst||d
||f  qz|dd }|d k	rt|st||d||f  qz| |||}t  }	|di }
t|
sTt||d||
f  qzxp|
 D ]d}t|}| ||||
\}}t||krq^t|dkr|td| |jdd ||	|< q^W t|	||d}||_|| j|< qzW d S )NFra   Tz;Value for locking_enabled should be true or false, found %rrU   zj'env_specs:' section in lock file should be a dictionary from env spec names to lock information, found {}zEField '%s' in env_specs in lock file should be a dictionary, found %r)r]   r_   lockedenv_spec_hashr   zDValue for locked for env spec '%s' should be true or false, found %rr   zFValue for env_spec_hash for env spec '%s' should be a string, found %rr]   zR'packages:' section in env spec '%s' in lock file should be a dictionary, found %rr   zFenv spec '%s': pip dependencies are currently ignored in the lock file)r%   r.   r,   )package_specs_by_platformr_   enabled)rP   rV   rW   ry   r=   boolrC   r   r   r   r   rG   r   r   r   rD   rz   r   r>   r$   r.   r   r   )r-   r?   rt   r   rV   rM   lock_setr   r_   Zconda_packages_by_platformZpackages_by_platformplatformZprevious_problem_countr   r   Zlock_set_objectr1   r1   r2   ri     sl    




z_ConfigCache._update_lock_setsc       .         s  fdd  fdd}fdd}fdd}|j \}}|j }	|j }
jd	i d
}d }d}td |||	|
dddd_t t|rt|dkrd}xX| D ]8\}}| dkrt	d
| q|dd }|d k	rt|st	d
| qt}|dd }|d kr<g }n"t|rR| g}n |dd}t|krnq||\}}||}||}j|d }|d krtt g jdd}t||||||t|d|d	|< |d kr|}t|d qW nt	d|  t _fddx, D ] }|g  |jks0tq0W g }d}xLj D ]>}|jjr~|d7 }|jjrht|jdkrh||j qhW |dkr<t t|}||krfdd}t	d d!d" |d# nDxBt|D ]6}fd$d%}t	d&| d!d" ||d# qW xȈj D ]}|jjr^qJ|jj }|d k	r||j!krd'|j||j!f } t"| |j#dd( |j|jjkrt|jjdkrd)|jd*|jf } n"d+|jd*|jd*|jjf } t"| |j#dd( t|j$dkrJx|jjD ]}!|j%|!}"t|"dkrtd,|j|!f } t"| |j#dd( nt& }#x.|"D ]&}$t'|$}%|%d k	r|#(|%j qW |j)|# }&t|&dkr0d-t|&|j|!d*tt*|&f } t"| |j#dd( q0W qJW xDj D ]6}|jkrd.|j+f } t"| |j#dd( qW t,j j-\}'d k	rd/d0g}(|(j!krd d k	rjj})d k	r|)d k	rȈ.|)rd d k	rp|)d krd1j|'t/j0+j#f } d2jt/j0+j#f }*n0d3j|'t/j0+j#1|)f } d4j|'f }*fd5d6}+fd7d8},t"| |*|+|,d9 n8|rfd:d;}-t"d<j#d=t/j0+j# |-d> d?jkrd?_2n|_2d S )@Nc                s     | ||S )N)r   )r   rF   r   )r?   rE   r-   r1   r2   r      s    z:_ConfigCache._update_env_specs.<locals>._parse_string_listc                s    | ddS )Nr^   zchannel namer1   )r   )r   r1   r2   _parse_channels#  s    z7_ConfigCache._update_env_specs.<locals>._parse_channelsc                s     | S )N)r   )r   )r?   rE   r-   r1   r2   r   &  s    z8_ConfigCache._update_env_specs.<locals>._parse_platformsc                s     d| S )Nr]   )r   )r   )r?   rE   r-   r1   r2   r   )  s    z7_ConfigCache._update_env_specs.<locals>._parse_packagesrU   )r   FzGlobal packages and channelsr1   )rM   conda_packagespip_packagesr^   r_   rN   inherit_from_namesinherit_fromr   TrJ   zAEnvironment spec name cannot be empty string, found: '{}' as namerN   z6'description' field of environment {} must be a stringr   zenv spec name)r   r_   r   missing)	rM   r   r   r^   r_   rN   r   r   r   )r]   r^   r_   rN   r   rZ   r\   r[   zXenv_specs should be a dictionary from environment name to environment attributes, not %rc          	      s   |  kst | jkrd}| |krBtddt| d}||   |  }|s|d }xJ|D ]B}| krtd||d  qf||}|d |f |d< qfW |d d	krĈjf|d< tf |j| < j|  S )
NFzK'inherit_from' fields create circular inheritance among these env specs: {}z, Tr   z\name '{}' in 'inherit_from' field of env spec {} does not match the name of another env specrM   r   r1   )	r   rU   rC   r   r   sortedr>   rY   r   )rM   trailZ	was_cycleattrsr   parentr   )env_spec_attrsmake_env_specr?   rE   r-   r1   r2   r   {  s.    



z5_ConfigCache._update_env_specs.<locals>.make_env_spec   c                s   | j dg  d S )Nr_   )rE   rv   )r5   )default_platformsr1   r2   set_global_default_platforms  s    zD_ConfigCache._update_env_specs.<locals>.set_global_default_platformszBThe 'platforms:' field should list platforms the project supports.zSet platforms to '%s'?z, )r)   r*   c                s    fdd}|S )Nc                s   | j ddg  d S )NrU   r_   )rE   rv   )r5   )r   r   r1   r2   set_env_spec_platforms  s    zP_ConfigCache._update_env_specs.<locals>.make_fix.<locals>.set_env_spec_platformsr1   )r   r   )r   )r   r2   make_fix  s    z0_ConfigCache._update_env_specs.<locals>.make_fixz=Env spec %s does not have anything in its 'platforms:' field.zhEnv spec '%s' has changed since the lock file was last updated (env spec hash has changed from %s to %s))r%   r.   r,   zREnv spec '%s' specifies platforms '%s' but the lock file lists no platforms for it,z_Env spec '%s' specifies platforms '%s' but the lock file has locked versions for platforms '%s'z<Lock file lists no packages for env spec '%s' on platform %sz;Lock file is missing %s packages for env spec %s on %s (%s)z0Lock file lists env spec '%s' which is not in %sr`   environmentz+Environment spec '%s' from %s is not in %s.zAdd env spec %s to %s?z>Environment spec '%s' from %s is out of sync with %s. Diff:
%sz/Overwrite env spec %s with the changes from %s?c                s   | j d jg   d S )NrU   )rE   rv   rM   to_json)r5   )importable_specr1   r2   "overwrite_env_spec_from_importable(  s    zJ_ConfigCache._update_env_specs.<locals>.overwrite_env_spec_from_importablec                s   | j ddg j d S )Nr`   r   )rE   rv   logical_hash)r5   )r   r1   r2   remember_no_import_importable+  s    zE_ConfigCache._update_env_specs.<locals>.remember_no_import_importable)r%   r)   r*   r+   c                s&   t  j}| jd|jg|  d S )NrU   )r   rY   rE   rv   rM   r   )r5   Zdefault_spec)r-   r1   r2   add_default_env_spec;  s    
z<_ConfigCache._update_env_specs.<locals>.add_default_env_speczThe env_specs section is empty.zAdd an environment spec to %s?)r%   r.   r)   r*   r   )3re   ry   r   rY   rP   r   rz   r   r{   rC   r   r   r   rV   r   rW   tuplerG   rU   rD   r   r   r   r   r_   r>   rM   r   Zdefault_platforms_with_currentr   r   Zdisabledr   r   r$   r.   r   Zpackage_specs_for_platformsetr   addZconda_package_names_setrr   r(   r	   rK   Z#diff_only_removes_notebook_or_bokehr&   r'   Z	diff_fromrX   ).r-   r?   rE   rt   r   r   r   Zshared_depsZshared_pip_depsZshared_channelsZshared_platformsrU   Zfirst_env_spec_nameZenv_specs_is_empty_or_missingrM   r   rN   Zproblem_countr   r   r   r^   r_   r   Zmissing_platformsZlocked_specs_countr}   Zmissing_platform_countr   r   r   Zlocked_hashr%   r   r   Zlock_set_namespackager   Zunlocked_namesimportable_filenameZskip_spec_importoldpromptr   r   r   r1   )r   r   r   r   r   r?   rE   r-   r2   rj     sT   







&









"





z_ConfigCache._update_env_specsc             C   sX   t |rd S |  r4t| j| jd}| || j| t| j| jd}| || j| d S )N)rL   rU   )rH   has_bootstrap_env_specr   rL   rU   r   rY   r   )r-   rq   r?   rE   r~   r1   r1   r2   rn   L  s    z+_ConfigCache._update_conda_env_requirementsc          
   C   sV  d}d }t  }|dd }td}tt|  }	|d k	r\t|s\t||d|  d}n|d k	rx|	 D ]\}
}|

 dkrt||d|
 d}qr|d kr|
}t|st||d|
|f  d}qrt||||	 d	|kr
t|d	 s
t||d
|
 d}d|kr:t|d ts:t||d|
 d}d|krt|d sjt||d|
 d}n,|d | jkrt||d|d |
f  d}d|krt|d tst||d|
 d}t|}d|kr| j|d< g }t}xrtt|  D ]^}||krqn||kr"|| }|| t|| st||d|
||| f  d}qW t|dkrt||d|
  d}d|ksd|krt|dkrd|krdnd}t|}|| dd |D }t||d|
|d|f  d}|sr||
|d||
< qrW | |||| |r2t  | _d | _n|| _d| jkrLd| _n|| _d S )NFrQ   Zcommand_runzS'commands:' section should be a dictionary from command names to attributes, not %rTrJ   zACommand variable name cannot be empty string, found: '{}' as namezIcommand name '%s' should be followed by a dictionary of attributes not %rrN   z2'description' field of command {} must be a stringsupports_http_optionsz='supports_http_options' field of command {} must be a booleanr}   zJ'env_spec' field of command {} must be a string (an environment spec name)zGenv_spec '%s' for command '%s' does not appear in the env_specs sectionZregisters_fusion_functionzA'registers_fusion_function' field of command {} must be a booleanz7command '%s' attribute '%s' should be a string not '%r'r   z/command '%s' does not have a command line in itr"   r#   r   c             S   s   g | ]}d | qS )z'%s'r1   )rb   otherr1   r1   r2   rc     s    z1_ConfigCache._update_commands.<locals>.<listcomp>z?command '%s' has multiple commands in it, '%s' can't go with %sz, )rM   Z
attributesr   )rP   ry   plugins_apiZget_pluginsr   r   rD   r   rC   r   r{   r   rG   r   r=   r   rU   r   rX   r   ALL_COMMAND_TYPESr>   rz   r   remover   _verify_notebook_commandsrQ   rR   )r-   r?   rE   rq   ZfailedZfirst_command_namerQ   Zcommands_sectionr   Z%all_known_command_attributes_extendedrM   r   Zcopied_attrsZcommand_typesZProjectCommandClassattrZlabelZothersr1   r1   r2   ro   W  s    








"
z_ConfigCache._update_commandsc                s  | ddgd k	rFdkr"d S tsJt||dt d S ng tt }g }x| D ]}|| qbW t	j
||d}|d kr||  |g kstd S dd |D }dd |D }t|}fd	d
}	fdddd g }
x(|D ] }|dr|	|r|
| qW |
  t|
dkr|
d }td| |jdtj|j|f |j|dd}|| nt|
dkrfdd|
D  fdd|
D  fdd}fdd}tdd|
 |jdtj|j ||dd}|| d S )Nr`   	notebooksTz;'skip_imports: notebooks:' value should be a list, found {})frontendrq   c             S   s   g | ]}|d  dks|qS )r   .r1   )rb   fr1   r1   r2   rc     s    z:_ConfigCache._verify_notebook_commands.<locals>.<listcomp>c             S   s   g | ]}| d dqS )\/)replace)rb   r   r1   r1   r2   rc     s    c                s0   x   D ]}|j| kr
dS q
W | kr,dS dS )NFT)r   r"   )relative_namecommand)rQ   skipped_notebooksr1   r2   need_to_import_notebook  s    
zG_ConfigCache._verify_notebook_commands.<locals>.need_to_import_notebookc                s    fdd}|S )Nc                s^   g }t tjj|}g |ks(t|d k	s4t d}|| | j	dg| d S )N)r"   r}   rQ   )
notebook_analyzerextrasr&   r'   r   rK   r   ru   rE   rv   )r5   errorsr   Zcommand_dict)env_spec_namer   r-   r1   r2   add_notebook   s    

z\_ConfigCache._verify_notebook_commands.<locals>.make_add_notebook_func.<locals>.add_notebookr1   )r   r   r   )r-   )r   r   r2   make_add_notebook_func  s    zF_ConfigCache._verify_notebook_commands.<locals>.make_add_notebook_funcc                s    fdd}|S )Nc                s4   | j jddgg d}|  | j ddg| d S )Nr`   r   )r   )rE   ry   r>   rv   )r5   r   )r   r1   r2   no_add_notebook  s    
zb_ConfigCache._verify_notebook_commands.<locals>.make_no_add_notebook_func.<locals>.no_add_notebookr1   )r   r   r1   )r   r2   make_no_add_notebook_func  s    zI_ConfigCache._verify_notebook_commands.<locals>.make_no_add_notebook_funcz.ipynbr   r   zNo command runs notebook %szCreate a command in %s for %s?)r%   r.   r)   r*   r+   r,   c                s   g | ]} |j qS r1   )rX   )rb   r   )r   r-   r1   r2   rc   *  s   c                s   g | ]} |qS r1   r1   )rb   r   )r   r1   r2   rc   ,  s    c                s   x D ]}||  qW d S )Nr1   )r5   r   )	add_funcsr1   r2   add_all.  s    
z7_ConfigCache._verify_notebook_commands.<locals>.add_allc                s   x D ]}||  qW d S )Nr1   )r5   r   )no_add_funcsr1   r2   
no_add_all2  s    
z:_ConfigCache._verify_notebook_commands.<locals>.no_add_allzNo commands run notebooks %sz, z0Create commands in %s for all missing notebooks?)ry   r   rC   r   r   r   r   r   r   r   rK   Z
pop_errorsr   r   endswithr>   sortrz   r$   r.   r&   r'   r(   rX   r   )r-   rQ   r?   rq   rE   ZrecorderZflat_requirementsZreqsfilesr   Zneed_to_importr   problemr   r   r1   )r   rQ   r   r   r   r-   r   r2   r     sr    




z&_ConfigCache._verify_notebook_commandsc          
      s   x| j  D ]}| j|j  | tdkr fdd}td|j jdf |j	dd jt
j|j	f |dd}|| qW d S )	Nr   c                sd   | j d jg}|d k	st|dg }xD ]}||kr0|| q0W | j d jdg| d S )NrU   r]   )rE   ry   rM   r   r   r>   rv   )r5   r   r]   m)r}   r   r1   r2   add_packages_to_env_specE  s    
zK_ConfigCache._verify_command_dependencies.<locals>.add_packages_to_env_specz@Command %s uses env spec %s which does not have the packages: %sz, zAdd %s to env spec %s in %s?T)r%   r.   r)   r*   r,   )rQ   r   rU   rX   Zmissing_packagesrz   r$   rM   r   r.   r&   r'   r(   r>   )r-   r?   rE   r   r   r   r1   )r}   r   r2   rp   ?  s    
z)_ConfigCache._verify_command_dependenciesc             C   s
   d| j kS )z>Return True if bootstrap-env is in env_specs, False otherwise.zbootstrap-env)rU   )r-   r1   r1   r2   r   Y  s    z#_ConfigCache.has_bootstrap_env_specN)r8   r9   r:   r3   ru   rf   rg   rh   r   r   rk   rl   rm   r   r   r   r   r   r   r   ri   rj   rn   ro   r   rp   r   r1   r1   r1   r2   rI      s4   9 >M  /wqrI   c               @   s  e Zd ZdZdcddZdd Zedd Zed	d
 Zedd Z	edd Z
e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ejd!d" Zddd#d$Zed%d& Zed'd( Zed)d* Zded+d,Zed-d. Zed/d0 Zd1d2 Zed3d4 Zed5d6 Z ed7d8 Z!ed9d: Z"ed;d< Z#ed=d> Z$ed?d@ Z%dAdB Z&dCdD Z'dEdF Z(dGdH Z)edIdJ Z*dKdL Z+edMdN Z,edOdP Z-dfdQdRZ.dSdT Z/dUdV Z0dWdX Z1dYdZ Z2d[d\ Z3ed]d^ Z4d_d` Z5dadb Z6dS )gProjectzRepresents the information we've inferred about a project.

    The Project class encapsulates information from the project
    file, and also anything else we've guessed by snooping around in
    the project directory or global user configuration.
    Nc                s|   t j | _ fdd}tj |d| _t | _t j	| j| _
t| j|| _|dkrbt }t|tspt|g| _dS )a  Construct a Project with the given directory and plugin registry.

        Args:
            directory_path (str): path to the project directory
            plugin_registry (RequirementsRegistry): where to look up Requirement and Provider instances,
                                                    None for default
            frontend (Frontend): the UX using this Project instance
        c                 s*   t  \} }| d k	r| gS td dgS d S )N)Zshared_base_spec)r   r   )r   r   )rK   r1   r2   load_default_specsq  s    z,Project.__init__.<locals>.load_default_specs)Zdefault_env_specs_funcN)r&   r'   realpath_directory_pathr   Zload_for_directory_project_filer   
_lock_filer(   Z_directory_basenamerI   _config_cacher   r=   r   r   
_frontends)r-   rK   plugin_registryr   r   r1   )rK   r2   r3   f  s    	zProject.__init__c             C   s   | j | j| j | j S )N)r   ru   r   r   )r-   r1   r1   r2   _updated_cache  s    zProject._updated_cachec             C   s   | j S )z"Get path to the project directory.)r   )r-   r1   r1   r2   rK     s    zProject.directory_pathc             C   s
   | j d S )zReturn the current UX frontend.)r   )r-   r1   r1   r2   r     s    zProject.frontendc             C   s   | j S )z)Get the ``ProjectFile`` for this project.)r   )r-   r1   r1   r2   rE     s    zProject.project_filec             C   s   | j S )z-Get the ``ProjectLockFile`` for this project.)r   )r-   r1   r1   r2   rt     s    zProject.lock_filec             C   s   | j jS )z2Get the ``RequirementsRegistry`` for this project.)r   rL   )r-   r1   r1   r2   r     s    zProject.plugin_registryc             C   s.   g }x$| j  D ]}|| |j qW |S )z@Required items for ALL envs (list of ``Requirement`` instances).)rU   r   r   rq   rM   )r-   Zcombinedr}   r1   r1   r2   "union_of_requirements_for_all_envs  s    z*Project.union_of_requirements_for_all_envsc                sZ   |dkr| j }|  j  fdd}dd }| j|}|dkrDg S t|j||dS dS )zPRequired items in order to run this project (list of ``Requirement`` instances).Nc                s     | jg S )N)r   rM   )r}   )rq   r1   r2   get_reqs  s    z&Project.requirements.<locals>.get_reqsc             S   s   t | tst| jS )N)r=   r   r   env_var)reqr1   r1   r2   req_key  s    z%Project.requirements.<locals>.req_key)Zkey_func)rX   r   rq   rU   r   rr   Z_get_inherited_with_getter)r-   r   r  r  r}   r1   )rq   r2   rq     s    
zProject.requirementsc             C   s   | j |tdS )z7All requirements that are ServiceRequirement instances.)klass)find_requirementsr   )r-   r   r1   r1   r2   service_requirements  s    zProject.service_requirementsc             C   s   | j |tdS )z8All requirements that are DownloadRequirement instances.)r  )r  r   )r-   r   r1   r1   r2   download_requirements  s    zProject.download_requirementsc             C   s   | j |tdS )zAll requirements that have an associated environment variable.

        Note: this will include services, downloads, and even CondaEnvRequirement.
        )r  )r  r   )r-   r   r1   r1   r2   all_variable_requirements  s    z!Project.all_variable_requirementsc             C   s   dd |  |D S )zAll 'plain' variables (that aren't services, downloads, or a Conda environment for example).

        Use the ``all_variable_requirements`` property to get every variable.
        c             S   s   g | ]}|j tkr|qS r1   )	__class__r   )rb   r  r1   r1   r2   rc     s    z7Project.plain_variable_requirements.<locals>.<listcomp>)r	  )r-   r   r1   r1   r2   plain_variable_requirements  s    z#Project.plain_variable_requirementsc             C   s   | j t  dS )zxPush a no-op frontend overriding the currently-active one.

        This is used to disable output temporarily.
        N)r   r>   r   )r-   r1   r1   r2   push_null_frontend  s    zProject.push_null_frontendc             C   s&   t | jdkst| jdd | _dS )zPop the no-op frontend.r   Nr   )rz   r   r   )r-   r1   r1   r2   pop_null_frontend  s    zProject.pop_null_frontendc             c   s"   |    z
dV  W d|   X dS )z,Create a context with the frontend disabled.N)r  r  )r-   r1   r1   r2   null_frontend  s    
zProject.null_frontendc             C   sX   g }xN|  |D ]@}|dk	r2t|tr|j|ks2q|dk	rFt||sFq|| qW |S )a  Find requirements that match the given env var and class.

        If env_var and klass are both provided, BOTH must match.

        Args:
           env_spec_name (str): name of env spec to find requirements of
           env_var (str): if not None, filter requirements that have this env_var
           klass (class): if not None, filter requirements that are an instance of this class

        Returns:
           list of matching requirements (may be empty)
        N)rq   r=   r   r  r>   )r-   r   r  r  foundr  r1   r1   r2   r    s    zProject.find_requirementsc             C   s
   |   jS )a  List of strings describing problems with the project configuration.

        This list contains problems which keep the project from loading, such as corrupt
        config files; it does not contain missing requirements and other "expected"
        problems.
        )r   rs   )r-   r1   r1   r2   r?     s    zProject.problemsc             C   s   dd |   jD S )zTList of ProjectProblem instances describing problems with the project configuration.c             S   s   g | ]}|j s|qS r1   )r,   )rb   r   r1   r1   r2   rc     s    z+Project.problem_objects.<locals>.<listcomp>)r   r?   )r-   r1   r1   r2   problem_objects  s    zProject.problem_objectsc             C   s   dd | j D S )z8List of ProjectProblem that have associated fix prompts.c             S   s   g | ]}|j r|js|qS r1   )r4   r,   )rb   r@   r1   r1   r2   rc     s    z,Project.fixable_problems.<locals>.<listcomp>)r  )r-   r1   r1   r2   fixable_problems  s    zProject.fixable_problemsc             C   sN   t | jdkrFg }x| jD ]}|| qW |dkr8d}td||dS dS dS )zIGet a ``Status`` describing project problems, or ``None`` if no problems.r   NzUnable to load the project.F)ZsuccessrN   r   )rz   r?   r>   r   )r-   rN   r   r   r1   r1   r2   problems_status  s    zProject.problems_statusc             C   s   dd | j D S )zJList of strings describing suggested changes to the project configuration.c             S   s   g | ]
}|j qS r1   )r%   )rb   r   r1   r1   r2   rc   $  s    z'Project.suggestions.<locals>.<listcomp>)suggestion_objects)r-   r1   r1   r2   suggestions!  s    zProject.suggestionsc             C   s   dd |   jD S )z[List of ProjectProblem instances describing suggested changes to the project configuration.c             S   s   g | ]}|j r|qS r1   )r,   )rb   r   r1   r1   r2   rc   )  s    z.Project.suggestion_objects.<locals>.<listcomp>)r   r?   )r-   r1   r1   r2   r  &  s    zProject.suggestion_objectsc             C   sV   d}xL|dkrPd}x&|   jD ]}|jr||  d}qW |rF|   |d8 }qW dS )z%Fix fixable problems and suggestions.   r   FTr   N)r   r?   r4   r6   use_changes_without_saving)r-   Z
iterationsZfixed_a_thingr   r1   r1   r2   fix_problems_and_suggestions+  s    

z$Project.fix_problems_and_suggestionsc             C   s
   |   jS )zGet the project's human-readable name.

        Prefers in order: `name` field from anaconda-project.yml, `package:
        name:` from meta.yaml, then project directory name.
        )r   rM   )r-   r1   r1   r2   rM   >  s    zProject.namec             C   s
   t | jS )z$Get the project's url-friendly name.)r   rM   )r-   r1   r1   r2   url_friendly_nameG  s    zProject.url_friendly_namec             C   s
   |   jS )zGet the project description.)r   rN   )r-   r1   r1   r2   rN   L  s    zProject.descriptionc             C   s
   |   jS )zGet the project's icon as an absolute path or None if no icon.

        Prefers in order: `icon` field from anaconda-project.yml, `app:
        icon:` from meta.yaml.
        )r   rO   )r-   r1   r1   r2   rO   Q  s    zProject.iconc             C   s
   |   jS )zDGet a dictionary of environment names to CondaEnvironment instances.)r   rU   )r-   r1   r1   r2   rU   Z  s    zProject.env_specsc             C   s
   |   jS )zKGet whether locking is enabled by default for lock sets that don't specify.)r   rW   )r-   r1   r1   r2   rW   _  s    z Project.locking_globally_enabledc             C   s
   |   jS )zGet the env spec representing global packages, channels, and platforms sections.

        This env spec has no name (its name is None) and can't be used directly
        to create environments, but every other env spec inherits from it.
        )r   rY   )r-   r1   r1   r2   rY   d  s    zProject.global_base_env_specc             C   s   dd |  |D S )zRGet a list of strings with the variables names from ``all_variable_requirements``.c             S   s   g | ]
}|j qS r1   )r  )rb   rr1   r1   r2   rc   o  s    z)Project.all_variables.<locals>.<listcomp>)r	  )r-   r   r1   r1   r2   all_variablesm  s    zProject.all_variablesc             C   s   dd |  |D S )zTGet a list of strings with the variables names from ``plain_variable_requirements``.c             S   s   g | ]
}|j qS r1   )r  )rb   r  r1   r1   r2   rc   s  s    z+Project.plain_variables.<locals>.<listcomp>)r  )r-   r   r1   r1   r2   plain_variablesq  s    zProject.plain_variablesc             C   s   dd |  |D S )zTGet a list of strings with the variable names for the project services requirements.c             S   s   g | ]
}|j qS r1   )r  )rb   r  r1   r1   r2   rc   w  s    z$Project.services.<locals>.<listcomp>)r  )r-   r   r1   r1   r2   r\   u  s    zProject.servicesc             C   s   dd |  |D S )zTGet a list of strings with the variable names for the project download requirements.c             S   s   g | ]
}|j qS r1   )r  )rb   r  r1   r1   r2   rc   {  s    z%Project.downloads.<locals>.<listcomp>)r  )r-   r   r1   r1   r2   r[   y  s    zProject.downloadsc             C   s
   |   jS )a&  Get the named environment to use by default.

        This will be the one named "default" if it exists, and
        otherwise the first-listed one.

        Note that each command may have its own default, so
        this should only be used in contexts with no known
        command.
        )r   rX   )r-   r1   r1   r2   rX   }  s    zProject.default_env_spec_namec             C   s&   |dkr| j S t|tst|j S dS )zuGet the named environment to use by default for a given ProjectCommand.

        the command may be ``None``
        N)rX   r=   r   r   )r-   r   r1   r1   r2   !default_env_spec_name_for_command  s    z)Project.default_env_spec_name_for_commandc             C   s
   |   jS )zGet the dictionary of commands to run the project.

        This dictionary can be empty.

        Returns:
            dictionary of command names to ``ProjectCommand``
        )r   rQ   )r-   r1   r1   r2   rQ     s    	zProject.commandsc             C   s&   |   }|jdkrdS |j|j S dS )zGet the default ``ProjectCommand`` or None if we don't have one.

        Returns:
            the default ``ProjectCommand``
        N)r   rR   rQ   )r-   cacher1   r1   r2   default_command  s    
zProject.default_commandc             C   s$   | j }|dkrdS |j||dS dS )a  Get the information needed to run the project's default command.

        Args:
            environ (dict): the environment
            extra_args (list of str): extra args to append to the command line
        Returns:
            a CommandExecInfo instance
        N)environ
extra_args)r  Zexec_info_for_environment)r-   r  r   r   r1   r1   r2   !default_exec_info_for_environment  s    	z)Project.default_exec_info_for_environmentc             C   sB   |dkr|   j}|dkrdS ||   jkr:|   j| S dS dS )zGet the ProjectCommand for the given command name, or None if no commands.

        Args:
           command_name (str): the command name
        Returns:
           a ProjectCommand instance or None
        N)r   rR   rQ   )r-   Zcommand_namer1   r1   r2   command_for_name  s    
zProject.command_for_namec             C   sP  t  }| j|d< | j|d< | j|d< t|d< t  }x| j D ]\}}t |jd||< |jdk	rn|j|| d< |jdk	r|j|| d< |j	dk	r|j	|| d	< |j
dk	r|j
|| d
< || jkrd|| d< |j|| d< |j|| d< || |j q>W ||d< t  }x6| j D ]&\}}t t|jt|j|j|jjt|jd||< t  }t  }t  }	x| |D ]}
t|
trqnt|
trnt |
j|
j|
jd}|
j}|dk	r||d< t|
tr|
j|d< |||
j < n8t|
t!r|
j"|d< ||	|
j < nt|
trn|||
j < qnW ||| d< ||| d< |	|| d< qW ||d< |S )aq  Get JSON-serializable information to be stored as metadata when publishing the project.

        This is a "baked" version of anaconda-project.yml which also
        includes any defaults or automatic configuration.

        Before calling this, check that Project.problems is empty.

        Returns:
            A dictionary containing JSON-compatible types.
        rM   r  rN   Zanaconda_project_version)rN   Nr#   r"   r!   r    Tr   r}   r   rQ   )r]   r^   rN   r   r_   )titlerN   	encryptedurlr   r[   rZ   r\   rU   )#rP   rM   r  rN   r   rQ   r   r#   r"   Zwindows_cmd_commandlineZunix_shell_commandliner  rX   r   ru   r   rU   rr   r   r^   r   r   r_   rq   r=   r   r   r#  r$  Zdefault_as_stringr   r%  r  r   r   )r-   ZjsonrQ   rF   r   envsenvrZ   r[   r\   r  datar   r1   r1   r2   publication_info  sj    











zProject.publication_infoc             C   s   | j   | j  dS )zRevert the project configuration by reloading config from disk.

        Discards all unsaved changes.

        This isn't needed when creating a Project, just if you want to
        revert to disk. We automatically load on Project creation.
        N)rE   loadrt   )r-   r1   r1   r2   r*    s    
zProject.loadc             C   s   | j   | j  dS )zlSave any modified project configuration.

        Does nothing for config files that are not dirty.
        N)rE   savert   )r-   r1   r1   r2   r+  #  s    
zProject.savec             C   s   | j   | j  dS )zRebuild project state from in-memory changes.

        This causes the Project instance to reload from
        the in-memory (but possibly unsaved) state of
        the project file and lock file.
        N)rE   r  rt   )r-   r1   r1   r2   r  +  s    
z"Project.use_changes_without_savingc             C   s   t | jddS )z)Fullpath to bootstrap environment prefix.r&  zbootstrap-env)r   r   )r-   r1   r1   r2   bootstrap_env_prefix5  s    zProject.bootstrap_env_prefixc             C   s   t jd | jkS )zZReturn True if anaconda-project is running inside a project bootstrap env False otherwise.r   )r&   r  r,  )r-   r1   r1   r2   is_running_in_bootstrap_env:  s    z#Project.is_running_in_bootstrap_envc             C   s
   | j  S )z>Return True if bootstrap-env is in env_specs, False otherwise.)r   r   )r-   r1   r1   r2   r   >  s    zProject.has_bootstrap_env_spec)NN)NN)N)N)7r8   r9   r:   r;   r3   r   r<   rK   r   rE   rt   r   r   rq   r  r  r	  r  r  r  
contextlibcontextmanagerr  r  r?   r  r  r  r  r  r  rM   r  rN   rO   rU   rW   rY   r  r  r\   r[   rX   r  rQ   r  r!  r"  r)  r*  r+  r  r,  r-  r   r1   r1   r1   r2   r   ^  sb   
	


			
K
r   )NN)Jr;   Z
__future__r   r.  r   r   r&   os.pathr   Zanaconda_project.env_specr   r   r   r	   Z/anaconda_project.requirements_registry.registryr
   Z2anaconda_project.requirements_registry.requirementr   Z=anaconda_project.requirements_registry.requirements.conda_envr   r   Z<anaconda_project.requirements_registry.requirements.downloadr   Z;anaconda_project.requirements_registry.requirements.servicer   Z!anaconda_project.project_commandsr   r   Zanaconda_project.project_filer   Z"anaconda_project.project_lock_filer   Zanaconda_project.archiverr   Zanaconda_project.versionr   Zanaconda_project.conda_managerr   Zanaconda_project.frontendr   r   r   Z$anaconda_project.internal.py2_compatr   r   r   Z'anaconda_project.internal.simple_statusr   Z!anaconda_project.internal.slugifyr   Z+anaconda_project.internal.notebook_analyzerZinternalr   Z#anaconda_project.internal.conda_apir   Z!anaconda_project.internal.pip_apir   Zanaconda_project.internalr   r   ZCOMMAND_TYPE_CONDA_APP_ENTRYZCOMMAND_TYPE_SHELLZCOMMAND_TYPE_WINDOWSZCOMMAND_TYPE_NOTEBOOKZCOMMAND_TYPE_BOKEH_APPr   objectr$   rA   rC   rG   rH   rI   r   r1   r1   r1   r2   <module>   s\   0

       ]