B
    nb\M                 @   sl  d 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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 dd	lmZmZmZ G d
d deZd4ddZdd Zdd Zdd Z dd Z!d5ddZ"dd Z#d6ddZ$ddg g fddZ%dd Z&d d! Z'd7d"d#Z(d$d% Z)d&d' Z*d(d) Z+d8d*d+Z,d,d- Z-d.d/ Z.d0d1 Z/d2d3 Z0dS )9zRunning programs utilities    )print_function)LooseVersion)getuserN)is_anaconda)encoding)get_python_executable)PY2is_text_stringto_text_stringc               @   s   e Zd ZdS )ProgramErrorN)__name__
__module____qualname__ r   r   4lib/python3.7/site-packages/spyder/utils/programs.pyr      s   r   c             C   sn   t  g}tjdkr |d ntt }|d|  | dk	rL||  tj	| }t
|sjt| |S )zP
    Return temporary Spyder directory, checking previously that it exists.
    ntZspyderzspyder-N)tempfileZ
gettempdirosnameappendr   Zto_unicode_from_fsr   ospjoinisdirmkdir)suffixZto_joinZusernameZtempdirr   r   r   get_temp_dir!   s    





r   c             C   s:   x4t jd t jD ]}t|| }t|r|S qW dS )zX
    Return program absolute path if installed in PATH.

    Otherwise, return None
    PATHN)r   environsplitpathsepr   r   isfile)basenamepathabspathr   r   r   is_program_installed8   s    
r$   c                sX    g}t jdkr6d} |s6 fdd|D  g }x|D ]}t|}|r<|S q<W dS )z
    Find program in PATH and return absolute path

    Try adding .exe or .bat to basename on Windows platforms
    (return None if not found)
    r   )z.exez.batz.cmdc                s   g | ]} | qS r   r   ).0Zext)r!   r   r   
<listcomp>P   s    z find_program.<locals>.<listcomp>N)r   r   endswithr$   )r!   names
extensionsr   r"   r   )r!   r   find_programD   s    


r*   c              K   s<   |  dtjdk tjdkr8d}d}||O }|  d| | S )aR  
    Given a dict, populate kwargs to create a generally
    useful default setup for running subprocess processes
    on different platforms. For example, `close_fds` is
    set on posix and creation of a new console window is
    disabled on Windows.

    This function will alter the given kwargs and return
    the modified dict.
    Z	close_fdsposixr   r   i   Zcreationflags)
setdefaultr   r   )kwargsZCONSOLE_CREATION_FLAGSZCREATE_NO_WINDOWr   r   r   #alter_subprocess_kwargs_by_platformW   s    
r.   c             K   sl   d|kr|d st dnd|d< d|kr8td|d< xdD ]}||tj q>W tf |}tj| f|S )aJ  
    Execute the given shell command.
    
    Note that *args and **kwargs will be passed to the subprocess call.

    If 'shell' is given in subprocess_kwargs it must be True,
    otherwise ProgramError will be raised.
    .
    If 'executable' is not given in subprocess_kwargs, it will
    be set to the value of the SHELL environment variable.

    Note that stdin, stdout and stderr will be set by default
    to PIPE unless specified in subprocess_kwargs.

    :str cmdstr: The string run as a shell command.
    :subprocess_kwargs: These will be passed to subprocess.Popen.
    shellzBThe "shell" kwarg may be omitted, but if provided it must be True.T
executableZSHELL)stdinstdoutstderr)r   r   getenvr,   
subprocessPIPEr.   Popen)Zcmdstrsubprocess_kwargsstreamr   r   r   run_shell_commandm   s    
r:   c             K   sr   d|kr|d rt dt| }|s0t d|  |g|p:g  }xdD ]}||tj qDW tf |}tj|f|S )a  
    Run program in a separate process.

    NOTE: returns the process object created by
    `subprocess.Popen()`. This can be used with
    `proc.communicate()` for example.

    If 'shell' appears in the kwargs, it must be False,
    otherwise ProgramError will be raised.

    If only the program name is given and not the full path,
    a lookup will be performed to find the program. If the
    lookup fails, ProgramError will be raised.

    Note that stdin, stdout and stderr will be set by default
    to PIPE unless specified in subprocess_kwargs.

    :str program: The name of the program to run.
    :list args: The program arguments.
    :subprocess_kwargs: These will be passed to subprocess.Popen.
    r/   zNThis function is only for non-shell programs, use run_shell_command() instead.zProgram %s was not found)r1   r2   r3   )r   r*   r,   r5   r6   r.   r7   )programargsr8   Zfullcmdr9   r   r   r   run_program   s    
r=   c             C   s2   ddl m} ddlm} | }||  ||S )z
    Generalized os.startfile for all platforms supported by Qt

    This function is simply wrapping QDesktopServices.openUrl

    Returns True if successfull, otherwise returns False.
    r   )QUrl)QDesktopServices)Zqtpy.QtCorer>   Z
qtpy.QtGuir?   ZsetUrlZopenUrl)filenamer>   r?   Zurlr   r   r   
start_file   s
    
rA   c             C   s|   |dk	st y6| dkr&t|d }ntt| d |d }W n tk
rV   dS X t|sj|d7 }t|rx|S dS )z
    Return absolute path if Python script exists (otherwise, return None)
    package=None -> module is in sys.path (standard library modules)
    N   z.pyw)AssertionErrorimpfind_moduler   r   ImportErrorr    )packagemoduler"   r   r   r   python_script_exists   s    

rJ   c             C   sP   |dk	st t|ttfr(t|ttfs,t t| |}ttj||g |  dS )zv
    Run Python script in a separate process
    package=None -> module is in sys.path (standard library modules)
    N)rD   
isinstancetuplelistrJ   r=   sysr0   )rH   rI   r<   p_argsr"   r   r   r   run_python_script   s     
rP   c             C   sL   t | std}g }x2t|| D ]"}| r"||dd q"W |S )ac  
    Split the string `text` using shell-like syntax

    This avoids breaking single/double-quoted strings (e.g. containing
    strings with spaces). This function is almost equivalent to the shlex.split
    function (see standard library `shlex`) except that it is supporting
    unicode strings (shlex does not support unicode until Python 2.7.3).
    z/(\s+|(?<!\\)".*?(?<!\\)"|(?<!\\)\'.*?(?<!\\)\')"')r	   rD   rer   stripr   )textpatternouttokenr   r   r   shell_split   s    	rY   c             C   s   g }|dk	r||  7 }|r&|d |r8|ddg | dk	rttjdkrj|rj|t| tjd n
||  |r|t	| |S )z&Construct Python interpreter argumentsNz-iz-mZpdbr   /)
r   r   extendr   r   r   normpathreplaceseprY   )fnamepython_argsinteractdebugZend_argsrO   r   r   r   get_python_args   s    

rc   c          	   C   s  |dkrt  }tjdkr<d|  d } |dd}d| d }|g}|t| ||||7 }tjdkrd| d| d }trt|}t|}yt	||d W nF t
k
r   d	d
lm}	 d	dlm}
 |	d|
d|
d|	j Y nX ntjdkrddddddddddddddddg}x|D ]z}t|d r&g }|d r\|r\||d |g7 }||d  ||7 }|rt|d ||d nt|d | dS q&W ntdS )zl
    Run Python script in an external system terminal.

    :str wdir: working directory, may be empty.
    Nr   rQ   rZ   \zstart cmd.exe /c "cd %s &&  )cwdr   )QMessageBox)_ZRunz<It was not possible to run this file in an external terminalr+   zgnome-terminalz--working-directoryz-x)cmdzwdir-optionzexecute-optionZkonsolez	--workdirz-ezxfce4-terminalZxtermri   zwdir-optionzexecute-option)r   r   r   r]   rc   r   r   r   Zto_fs_from_unicoder:   ZWindowsErrorZqtpy.QtWidgetsrg   Zspyder.config.baserh   ZcriticalZOkr$   r   r=   NotImplementedError)r_   Zwdirr<   ra   rb   r`   r0   rO   ri   rg   rh   Zprogramsr;   Zarglistr   r   r   run_python_script_in_terminal  s\    





rk   c             C   s4   t | ts| d} | d }td|s,dS dS dS )z
    A stable version has no letters in the final component, but only numbers.

    Stable version example: 1.2, 1.3.4, 1.0.5
    Not stable version: 1.2alpha, 1.3.4beta, 0.1.0rc1, 3.0.0dev
    .z[a-zA-Z]TFN)rK   rL   r   rS   search)versionZ	last_partr   r   r   is_stable_versionU  s    

rp   c             C   s  t | trddd | D } t|rJt| sJ| |rJ|| krJ|d }n*t| rtt|st|| rt|| krt| d } y|dkrt| t|kS |dkrt| t|kS |dkrt| t|kS |dkrt| t|k S |d	krt| t|kS d
S W n tk
r
   dS X dS )a  
    Check version string of an active module against a required version.

    If dev/prerelease tags result in TypeError for string-number comparison,
    it is assumed that the dependency is satisfied.
    Users on dev branches are responsible for keeping their own packages up to
    date.
    
    Copyright (C) 2013  The IPython Development Team

    Distributed under the terms of the BSD License.
    rl   c             S   s   g | ]}t |qS r   )str)r%   ir   r   r   r&   t  s    z!check_version.<locals>.<listcomp>Zzz>z>==<z<=FTN)rK   rL   r   rp   
startswithr   	TypeError)actverro   Zcmp_opr   r   r   check_versionf  s,    

ry   c             C   s   t | }t|dt|ddS )z<Return module version or None if version can't be retrieved.__version__ZVERSIONN)
__import__getattr)module_namemodr   r   r   get_module_version  s    r   c          	   C   sP  |r\t |rVd|krVtt}tt}tt}tt}tj	ddt
 dd}z|j}	|d |d |d ||d	  ||d	  ||d	  ||d	  |r|d
| |f  n|d|   |  t| |  yt||	g}
|
 \}}W n tjk
r*   dS X t| S |jsH|  t|	 X ndS n|dkryt| }W n
   dS n|}|dkr|dk	rdS |dkrdS d|krd}x$|dD ]}|ot| |}qW |S td|}|dk	s td|d|  }|sd}|dks0td| || d }t|||S dS )a  
    Return True if module *module_name* is installed

    If version is not None, checking module version
    (module must have an attribute named '__version__')

    version may starts with =, >=, > or < to specify the exact requirement ;
    multiple conditions may be separated by ';' (e.g. '>=0.13;<1.0')

    interpreter: check if a module is installed with a given version
    in a determined interpreter
    ZpythonZwtz.pyF)r   dirdeletez# -*- coding: utf-8 -*-

z+from distutils.version import LooseVersion
zimport re


z%print(is_module_installed('%s','%s'))z print(is_module_installed('%s'))TN;z[0-9]zInvalid version numberrt   )z>=rs   rt   ru   z<=zInvalid version condition '%s')r   r    inspectZ	getsourcery   r   rp   is_module_installedr   ZNamedTemporaryFiler   r   writeflushr   fsynccloser=   communicater5   ZCalledProcessErrorevaldecodeclosedremover   rS   rn   rD   start)r}   ro   Zinstalled_versionZinterpreterZcheckverZ
get_modverZ
stable_verZ
ismod_instfZscriptprocoutputZ_errrx   ZvermatchZsymbr   r   r   r     st    











r   c             C   s&   d}t j|| t jddkrdS dS dS )z8Check that the python interpreter file has a valid name.z.*python(\d\.?\d*)?(w)?(.exe)?$)flagsNFT)rS   r   I)r@   rV   r   r   r    is_python_interpreter_valid_name  s    r   c             C   s   t j| }t|rt| s"dS t| rt jdkrHt	|sBdS dS qt
jdkrzt rft	|rfdS t	|stdS dS qdS nt	|rdS t| S dS )z6Evaluate wether a file is a python interpreter or not.Fr   TdarwinN)r   r"   realpathr   r    r   
is_pythonwr   r   Zis_text_filerN   platformr   check_python_help)r@   Zreal_filenamer   r   r   is_python_interpreter  s&    





r   c             C   s&   d}t j|| t jddkrdS dS dS )z0Check that the python interpreter has 'pythonw'.z.*python(\d\.?\d*)?w(.exe)?$)r   NFT)rS   r   r   )r@   rV   r   r   r   r     s    r   c             C   sL   y<t | dg}t| d }d}d|kr6||kr6dS dS W n
   dS dS )z3Check that the python interpreter can execute help.z-hr   z?Options and arguments (and corresponding environment variables)zusage:TFN)r=   r
   r   )r@   r   r   Zvalidr   r   r   r     s    r   )N)N)NN)N)NNN)1__doc__Z
__future__r   Zdistutils.versionr   Zgetpassr   rE   r   r   os.pathr"   r   rS   r5   rN   r   Zspyder.config.utilsr   Zspyder.utilsr   Zspyder.utils.miscr   Zspyder.py3compatr   r	   r
   	Exceptionr   r   r$   r*   r.   r:   r=   rA   rJ   rP   rY   rc   rk   rp   ry   r   r   r   r   r   r   r   r   r   r   <module>   sJ   
#
&

D* 
W 	