U
    g
%                     @   s   d dl 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 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 d dlmZ d dlmZ d dlmZ eeZG dd deZdS )    N)ABC)abstractmethod)IOBase)system)PIPE)sleep)Optional)cast)request)URLError)WebDriverException)SubprocessStdAlias)utilsc                   @   s  e Zd ZdZd#eeeejej	ej
ej
f  eddddZeeddd	Zeeje dd
dZeedddZejeddddZddddZddddZedddZddddZddddZddddZddddZedddd Zee dd!d"ZdS )$Servicea(  The abstract base class for all service objects.  Services typically
    launch a child program in a new process as an interim process to
    communicate with a browser.

    :param executable: install path of the executable.
    :param port: Port for the service to run on, defaults to 0 where the operating system will decide.
    :param log_output: (Optional) int representation of STDOUT/DEVNULL, any IO instance or String path to file.
    :param env: (Optional) Mapping of environment variables for the new process, defaults to `os.environ`.
    Nr   )executable_pathport
log_outputenvdriver_path_env_keyreturnc                 K   s   t |tr"ttt|ddd| _n`|tjkrJttj	tj
ttf  d | _n8|d ks\|tjkr|ttj	tj
ttf  tj| _n|| _|pt | _|di | _| jdd| _|ptj| _|| _|  p|| _d S )Nza+zutf-8)encodingpopen_kwcreation_flagsr   )
isinstancestrr	   r   openr   
subprocessSTDOUTtypingr   UnionintDEVNULLr   Z	free_portr   popr   r   osenvironr   DRIVER_PATH_ENV_KEYenv_path_path)selfr   r   r   r   r   kwargs r*   E/tmp/pip-unpacked-wheel-3ysq0mf8/selenium/webdriver/common/service.py__init__3   s    	

 zService.__init__)r   c                 C   s   dt d| j S )zGets the url of the Service.zhttp://	localhost)r   Zjoin_host_portr   r(   r*   r*   r+   service_urlM   s    zService.service_urlc                 C   s   t ddS )z7A List of program arguments (excluding the executable).z2This method needs to be implemented in a sub classN)NotImplementedErrorr.   r*   r*   r+   command_line_argsR   s    zService.command_line_argsc                 C   s
   | j pdS )N )r'   r.   r*   r*   r+   pathW   s    zService.path)valuer   c                 C   s   t || _d S N)r   r'   )r(   r4   r*   r*   r+   r3   [   s    c                 C   sp   | j dkrtd| | j  d}|   |  r4qlttdd|  d |d7 }|dkr"td	| j  q"dS )
zStarts the Service.

        :Exceptions:
         - WebDriverException : Raised either when it can't start the service
           or when it can't connect to the service
        NService path cannot be None.r   g{Gz?g?g      ?   F   zCan not connect to the Service )r'   r   _start_processassert_process_still_runningis_connectabler   min)r(   countr*   r*   r+   start_   s    
zService.startc                 C   s(   | j  }|r$td| j d| dS )z1Check if the underlying process is still running.zService z' unexpectedly exited. Status code was: N)processpollr   r'   )r(   Zreturn_coder*   r*   r+   r:   u   s    
z$Service.assert_process_still_runningc                 C   s   t | jS )zfEstablishes a socket connection to determine if the service running
        on the port is accessible.)r   r;   r   r.   r*   r*   r+   r;   {   s    zService.is_connectablec                 C   sT   zt | j d W n tk
r,   Y dS X tdD ]}|  sF qPtd q6dS )zcDispatch an HTTP request to the shutdown endpoint for the service in
        an attempt to stop it.z	/shutdownN   r7   )r
   urlopenr/   r   ranger;   r   )r(   _r*   r*   r+   send_remote_shutdown_command   s    z$Service.send_remote_shutdown_commandc                 C   sx   | j ttjhkr@t| j tr(| j   nt| j tr@t| j  | j	dk	rtz| 
  W n tk
rj   Y nX |   dS )zStops the service.N)r   r   r   r!   r   r   closer    r#   r?   rE   	TypeError_terminate_processr.   r*   r*   r+   stop   s    
zService.stopc              	   C   s   z| j j| j j| j j  }}}|||fD ]&}z|  W q( tk
rL   Y q(X q(| j   z| j d W n. tj	k
r   t
jddd | j   Y nX W n" tk
r   t
jddd Y nX dS )a#  Terminate the child process.

        On POSIX this attempts a graceful SIGTERM followed by a SIGKILL,
        on a Windows OS kill is an alias to terminate.  Terminating does
        not raise itself if something has gone wrong but (currently)
        silently ignores errors here.
        <   zTService process refused to terminate gracefully with SIGTERM, escalating to SIGKILL.T)exc_infoz"Error terminating service process.N)r?   stdinstdoutstderrrF   AttributeError	terminatewaitr   TimeoutExpiredloggererrorkillOSError)r(   rL   rM   rN   streamr*   r*   r+   rH      s*    

zService._terminate_processc                 C   s&   z|    W n tk
r    Y nX d S r5   )rI   	Exceptionr.   r*   r*   r+   __del__   s    zService.__del__)r3   r   c                 C   s\  |g}| |   | jdt dk}zd}t dkrVt }tjtjB |_	tj
|_tj|f| j|ttjtjttjtj f  | jttjtjttjtj f  | jt| j|d| j| _td| j| jj| j| j W nx tk
r    Y nd tk
rV } zD|jtj krD| jdkr(t!dt!dt"j#$| j d| W 5 d}~X Y nX dS )	zmCreates a subprocess by executing the command provided.

        :param cmd: full command to execute
        	close_fdsWindowsN)r   rZ   rM   rN   rL   creationflagsstartupinfozNStarted executable: `%s` in a child process with pid: %s using %s to output %sr6   'z(' executable may have wrong permissions.)%extendr1   r   r"   r   r   ZSTARTUPINFOZCREATE_NEW_CONSOLEZSTARTF_USESHOWWINDOWZdwFlagsZSW_HIDEZwShowWindowPopenr   r	   r   r   r   r    IOAnyr   r   r   r?   rS   debugr'   pidrG   rV   errnoEACCESr   r#   r3   basename)r(   r3   cmdZclose_file_descriptorsZ
start_infoerrr*   r*   r+   r9      sR    
""	zService._start_processc                 C   s   t | jd S r5   )r#   getenvr%   r.   r*   r*   r+   r&      s    zService.env_path)Nr   NNN)__name__
__module____qualname____doc__r   r    r   r   r   Mappingrb   r,   propertyr/   r   Listr1   r3   setterr>   r:   boolr;   rE   rI   rH   rY   r9   r&   r*   r*   r*   r+   r   (   s>        ,r   )re   loggingr#   r   r   abcr   r   ior   platformr   r   timer   r   r	   urllibr
   urllib.errorr   Zselenium.common.exceptionsr   Zselenium.typesr   Zselenium.webdriver.commonr   	getLoggerrk   rS   r   r*   r*   r*   r+   <module>   s&   
