B
    âÖÓY‚V  ã            	   @   sŽ  d Z ddlmZ ddlmZ ddlmZ ddlm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mZ yddlmZ W n  ek
rœ   ddlmZ Y nX yddlmZ W n  ek
rÎ   ddlmZ Y nX d	Zd
Zee Zdd„ ZedddgƒZeddƒeddƒeddƒeddƒeddƒeddƒeddƒfZG dd„ deƒZG dd„ deƒZ G dd„ deƒZ!G dd „ d eƒZ"d!d"„ Z#G d#d$„ d$eƒZ$dS )%z3Class representing a command from the project file.é    )Úabsolute_import)Úcopy)Ú
namedtupleN)Ú_verbose_logger)Ú	conda_apiÚlogged_subprocessÚ
py2_compat)Úquote)ÚdescriptionÚenv_specÚsupports_http_optionsÚ	bokeh_appÚnotebookÚunixÚwindowsÚconda_app_entry)Zregisters_fusion_functionc               C   s   t  ¡ dkS )NZWindows)ÚplatformÚsystem© r   r   ú@lib/python3.7/site-packages/anaconda_project/project_commands.pyÚ_is_windows&   s    r   Ú_ArgSpecÚoptionÚ	has_valuez--anaconda-project-hostTz--anaconda-project-addressz--anaconda-project-portz--anaconda-project-url-prefixz--anaconda-project-no-browserFz--anaconda-project-iframe-hostsz--anaconda-project-use-xheadersc               @   s,   e Zd Zdd„ Zdd„ Zdd„ Zdd„ Zd	S )
Ú_ArgsTransformerc             C   s
   || _ d S )N)Úspecs)Úselfr   r   r   r   Ú__init__5   s    z_ArgsTransformer.__init__c             C   s.  |sg S |d }|dkr|S xö| j D ]ì}|jræ|jd }||jkrªt|ƒdks\|d  d¡r€||j  d¡ |  ||dd … ¡S ||j  |d ¡ |  ||dd … ¡S n:| |¡rä||j  |t|ƒd … ¡ |  ||dd … ¡S q$||jkr$dg||j< |  ||dd … ¡S q$W |g|  ||dd … ¡ S )	Nr   z--ú=é   ú-Ú é   T)r   r   r   ÚlenÚ
startswithÚappendÚ_parse_args_removing_known)r   ÚresultsÚargsÚargÚspecZwith_equalsr   r   r   r&   8   s*    



z+_ArgsTransformer._parse_args_removing_knownc             C   s<   dd„ | j D ƒ}|  ||¡}t| ¡ dd„ d}|  ||¡S )Nc             S   s   i | ]}g |j “qS r   )r   )Ú.0r*   r   r   r   ú
<dictcomp>[   s    z3_ArgsTransformer.transform_args.<locals>.<dictcomp>c             S   s   | d S )Nr   r   )Úxr   r   r   Ú<lambda>^   s    z1_ArgsTransformer.transform_args.<locals>.<lambda>)Úkey)r   r&   ÚsortedÚitemsÚadd_args)r   r(   r'   Zwith_removedZresults_listr   r   r   Útransform_argsZ   s    z_ArgsTransformer.transform_argsc             C   s   t dƒ‚d S )Nznot implemented)ÚRuntimeError)r   r'   r(   r   r   r   r2   a   s    z_ArgsTransformer.add_argsN)Ú__name__Ú
__module__Ú__qualname__r   r&   r3   r2   r   r   r   r   r   4   s   "r   c                   s$   e Zd Z‡ fdd„Zdd„ Z‡  ZS )Ú_BokehArgsTransformerc                s   t t| ƒ t¡ d S )N)Úsuperr8   r   Ú_http_specs)r   )Ú	__class__r   r   r   f   s    z_BokehArgsTransformer.__init__c             C   sÌ   g }x¾|D ]¶\}}|dkrFx¤|D ] }|  | dd¡¡ |  |¡ q W q
|dkrrxp|D ]}|  d¡ |  |¡ qTW q
|dkrŠ|sÀ|  d¡ q
|dkr®|rÀ|d	 d
krÀ|  d¡ q
|dkr¸q
tdƒ‚q
W || S )N)z--anaconda-project-hostz--anaconda-project-portz--anaconda-project-addresszanaconda-project-r!   z--anaconda-project-url-prefixz--prefixz--anaconda-project-no-browserz--showz--anaconda-project-use-xheadersr   Tz--use-xheadersz--anaconda-project-iframe-hostsz"unhandled http option for notebook)r%   Úreplacer4   )r   r'   r(   Úaddedr   ÚvaluesÚvr   r   r   r2   i   s(    


z_BokehArgsTransformer.add_args)r5   r6   r7   r   r2   Ú__classcell__r   r   )r;   r   r8   e   s   r8   c                   s$   e Zd Z‡ fdd„Zdd„ Z‡  ZS )Ú_NotebookArgsTransformerc                s   t t| ƒ t¡ || _d S )N)r9   rA   r   r:   Úcommand)r   rB   )r;   r   r   r   „   s    z!_NotebookArgsTransformer.__init__c             C   sp  g }t j | jj¡}dt|ƒ }| |¡ x:|D ]0\}}|dkrFq2|dkrzx(|D ] }| | dd¡¡ | |¡ qTW q2|dkr¦xà|D ]}| d¡ | |¡ qˆW q2|dkrÊ|rÈ|d	 d
krÈ| d¡ q2|dkrðx|D ]}| d| ¡ qØW q2|dkr2t|ƒd	krddd 	|¡ }	d|	 d }
| d|
 ¡ q2|dkr\|rd|d	 d
krd| d¡ q2t
dƒ‚q2W || S )Nz'--NotebookApp.default_url=/notebooks/%sz--anaconda-project-hostz--anaconda-project-portzanaconda-project-r!   z--anaconda-project-addressz--ipz--anaconda-project-no-browserr   Tz--no-browserz--anaconda-project-url-prefixz--NotebookApp.base_url=z--anaconda-project-iframe-hostsz'self' ú z;{ 'headers': { 'Content-Security-Policy': "frame-ancestors z" } }z--NotebookApp.tornado_settings=z--anaconda-project-use-xheadersz!--NotebookApp.trust_xheaders=Truez#unhandled http option for notebooks)ÚosÚpathÚbasenamerB   r   Ú	url_quoter%   r<   r#   Újoinr4   )r   r'   r(   r=   ÚfilenameZdefault_url_argr   r>   r?   Z	full_listZpython_dict_literalr   r   r   r2   ˆ   s>    






z!_NotebookArgsTransformer.add_args)r5   r6   r7   r   r2   r@   r   r   )r;   r   rA   ƒ   s   rA   c               @   sZ   e Zd ZdZd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S )ÚCommandExecInfoz'Class describing an executable command.Nc             C   s4   || _ || _|| _|| _|dks0t|ƒdks0t‚dS )zConstruct a CommandExecInfo.Fr   N)Ú_cwdÚ_argsÚ_shellÚ_envr#   ÚAssertionError)r   Úcwdr(   ÚshellÚenvr   r   r   r   r   r   Â   s
    zCommandExecInfo.__init__c             C   s   | j S )z(Working directory to run the command in.)rK   )r   r   r   r   rP   Ê   s    zCommandExecInfo.cwdc             C   s   | j S )z»Command line argument vector to run the command.

        If the ``shell`` property is True, then pass args[0] as a string to Popen,
        rather than this entire list of args.
        )rL   )r   r   r   r   r(   Ï   s    zCommandExecInfo.argsc             C   s   | j S )z2Whether the command should be run with shell=True.)rM   )r   r   r   r   rQ   Ø   s    zCommandExecInfo.shellc             C   s   | j S )z"Environment to run the command in.)rN   )r   r   r   r   rR   Ý   s    zCommandExecInfo.envc             K   sP   | j r$t| jƒdkst‚| jd }n| j}tjf |t | j¡| j	| j dœ|—ŽS )z¡Convenience method runs the command using Popen.

        Args:
            kwargs: passed through to Popen

        Returns:
            Popen instance
        r   r   )r(   rR   rP   rQ   )
rM   r#   rL   rO   r   ÚPopenr   Zenv_without_unicoderN   rK   )r   Úkwargsr(   r   r   r   Úpopenâ   s    	

zCommandExecInfo.popenc          	   C   s¬   t | jƒ}| jrFt|ƒdks t‚tƒ r:|  ¡  t d¡ nddg| }zTt	 
¡ }t	 | j¡ tj ¡  tj ¡  tƒ  dd |¡¡ t	 |d || j¡ W dt	 |¡ X dS )z™Convenience method exec's the command replacing the current process.

        Returns:
            Does not return. May raise an OSError though.
        r   r   z/bin/shz-cz$ %srC   N)r   rL   rM   r#   rO   r   rU   ÚsysÚexitrD   ÚgetcwdÚchdirrK   ÚstderrÚflushÚstdoutr   ÚinforH   ÚexecvperN   )r   r(   Zold_dirr   r   r   r^      s    


zCommandExecInfo.execvpe)NN)r5   r6   r7   Ú__doc__r   ÚpropertyrP   r(   rQ   rR   rU   r^   r   r   r   r   rJ   ¿   s   
	rJ   c             C   s`   |d kr| S t ƒ r6ddlm}m} || ƒ}||| ƒS | }x|D ]}|d t|ƒ }q@W |S d S )Nr   )Úwindows_split_command_lineÚwindows_join_command_linerC   )r   Z)anaconda_project.internal.windows_cmdlinera   rb   r	   )rB   Ú
extra_argsra   rb   r(   Znew_commandr)   r   r   r   Ú"_append_extra_args_to_command_line"  s    
rd   c               @   sÀ   e Zd Z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edd„ ƒZedd„ ƒZedd„ ƒZdd„ Zedd„ ƒZedd„ ƒZd#dd„Zd$dd „Zd!d"„ ZdS )%ÚProjectCommandz+Represents a command from the project file.c             C   s   d|kst ‚|| _|| _dS )z±Construct a command with the given attributes.

        Args:
            name (str): name of the command
            attributes (dict): named attributes of the command
        r   N)rO   Ú_nameÚ_attributes)r   ÚnameZ
attributesr   r   r   r   5  s    zProjectCommand.__init__c             C   s   | j S )zGet name of the command.)rf   )r   r   r   r   rh   @  s    zProjectCommand.namec             C   s"   | j dk	p| jdk	}| j d|¡S )z=Can accept the --anaconda-project-* options for HTTP servers.Nr   )r   r   rg   Úget)r   Údefaultr   r   r   r   E  s    z$ProjectCommand.supports_http_optionsc             C   s   | j  dd¡S )z9Notebook filename relative to project directory, or None.r   N)rg   ri   )r   r   r   r   r   K  s    zProjectCommand.notebookc             C   s   | j  dd¡S )z:Bokeh app filename relative to project directory, or None.r   N)rg   ri   )r   r   r   r   r   P  s    zProjectCommand.bokeh_appc             C   s   | j  dd¡S )zìUnix shell command line string, or None.

        This property is here to support displaying the command in
        a UI, but shouldn't be used to execute the command; use
        ``exec_info_for_environment()`` for executing.
        r   N)rg   ri   )r   r   r   r   Úunix_shell_commandlineU  s    z%ProjectCommand.unix_shell_commandlinec             C   s   | j  dd¡S )zécmd.exe command line string, or None.

        This property is here to support displaying the command in
        a UI, but shouldn't be used to execute the command; use
        ``exec_info_for_environment()`` for executing.
        r   N)rg   ri   )r   r   r   r   Úwindows_cmd_commandline_  s    z&ProjectCommand.windows_cmd_commandlinec             C   s   | j  dd¡S )zÃArgv to exec directly, or None.

        This isn't allowed in the config file but we do generate
        it on the fly when we run stuff that isn't a configured
        project command.
        r(   N)rg   ri   )r   r   r   r   r(   i  s    zProjectCommand.argsc             C   s   | j  dd¡S )zéConda "app entry" style command line.

        This property is here to support displaying the command in
        a UI, but shouldn't be used to execute the command; use
        ``exec_info_for_environment()`` for executing.
        r   N)rg   ri   )r   r   r   r   r   s  s    zProjectCommand.conda_app_entryc             C   s   | j  d¡S )zTGet the environment spec name used for this command unless user specified otherwise.r   )rg   ri   )r   r   r   r   Údefault_env_spec_name}  s    z$ProjectCommand.default_env_spec_namec             C   s   t ƒ r
dS dS d S )Nr   r   )r   )r   r   r   r   Ú_shell_field‚  s    zProjectCommand._shell_fieldc             C   s¬   | j  dd¡}|dkr*| jdk	r*d| j }|dkrF| jdk	rFd| j }|dkr\| j  dd¡}|dkrr| j  dd¡}|dkrˆ| j  dd¡}|dkrœt| ddƒ}|dk	s¨t‚|S )	z+Helpful string showing what the command is.r
   NzBokeh app %szNotebook %sr   r   r   rB   )rg   ri   r   r   ÚgetattrrO   )r   r
   r   r   r   r
   ˆ  s"    



zProjectCommand.descriptionc             C   s4   t ƒ }x(| j ¡ D ]}|tkr| j| ||< qW |S )z©Dictionary of extra attributes not covered by other properties.

        These are typically 'plugin specific' (only for notebook, only for bokeh,
        etc.)
        )Údictrg   ÚkeysÚextra_command_attributes)r   ÚresultÚkr   r   r   Úextras¢  s
    zProjectCommand.extrasNc       
      C   sj  |d kst |tƒst‚d }d}| jd k	rXtj |d | j¡}d|g}| jrXt| ƒ 	|¡}| j
d k	r’tj |d | j
¡}dd|g}| jr’tƒ  	|¡}| jd k	r¢| j}|d k	rÂ|d k	rº|| }|dfS | j |  ¡ d ¡}|d k	rìt||ƒg}d}|d krb| j dd ¡}|d k	rb| ¡ }g }x4|D ],}	d|	kr@|	 dt |¡¡}	| |	¡ q W |d k	rb|| }||fS )	NFÚPROJECT_DIRzjupyter-notebookÚbokehZserveTr   z	${PREFIX})Ú
isinstanceÚlistrO   r   rD   rE   rH   r   rA   r3   r   r8   r(   rg   ri   rn   rd   Úsplitr<   r   Zenviron_get_prefixr%   )
r   Úenvironrc   r(   rQ   rE   rB   Z	app_entryZparsedr)   r   r   r   Ú_choose_args_and_shell¯  sF    








z%ProjectCommand._choose_args_and_shellc       	      C   s¤   t  ¡ }x&|ddfD ]}||krtd| ƒ‚qW |  ||¡\}}|dkrLdS tj |d |d g¡}|st |d |¡}|dk	rtj	 
|¡|d< t|d |||dS )a(  Get a ``CommandExecInfo`` ready to be executed.

        Args:
            environ (dict): the environment containing a CONDA_PREFIX, PATH, and PROJECT_DIR
            extra_args (list of str): extra args to append to the command line
        Returns:
            argv as list of strings
        ÚPATHrv   z6To get a runnable command for the app, %s must be set.Nr   )rP   r(   rR   rQ   )r   Zconda_prefix_variableÚ
ValueErrorr|   rD   ÚpathseprH   ÚspawnZfind_executablerE   ÚabspathrJ   )	r   r{   rc   Z	conda_varrh   r(   rQ   rE   Ú
executabler   r   r   Úexec_info_for_environmentá  s    	
z(ProjectCommand.exec_info_for_environmentc             C   sN   g }d|j krJ| jdk	r,d|j kr,| d¡ | jdk	rJd|j krJ| d¡ |S )zæList packages required by this command which are not in the env spec.

        This is used to be sure if you add a notebook command you depend on
        notebook, and if you add a Bokeh command you depend on bokeh, etc.
        ZanacondaNrw   r   )Zconda_package_names_setr   r%   r   )r   r   Zmissingr   r   r   Úmissing_packages  s    


zProjectCommand.missing_packages)N)N)r5   r6   r7   r_   r   r`   rh   r   r   r   rk   rl   r(   r   rm   rn   r
   ru   r|   rƒ   r„   r   r   r   r   re   2  s"   




2
/re   )%r_   Z
__future__r   r   Úcollectionsr   Zdistutils.spawnr€   rD   r   rV   Zanaconda_project.verboser   Zanaconda_project.internalr   r   r   Zshlexr	   ÚImportErrorZpipesZurllib.parserG   ZurllibZstandard_command_attributesrr   Zall_known_command_attributesr   r   r:   Úobjectr   r8   rA   rJ   rd   re   r   r   r   r   Ú<module>   s@   1<c