U
    L»{jQ<  ã                   @   sœ   d dl Z d dlZd dlmZmZ d dlZd dlZd dlZd dlZzd dlm	Z	 W n e
k
rh   eZ	Y nX G dd„ deƒZejejB dfdd„Zdd	„ ZdS )
é    N)ÚLockÚThread)ÚJSONDecodeErrorc                   @   s¾   e Zd ZdZdZdZdZedd„ ƒZd#dd„Z	d	d
„ Z
edd„ ƒZdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zedd„ ƒZedd„ ƒZejdd„ ƒZedd„ ƒZejdd„ ƒZdd „ Zd!d"„ ZdS )$Ú	BaseScopeN© )ú--disable-gpuz--allow-file-access-from-filesz--disable-breakpadz--disable-dev-shm-usagec                 C   s   | j | j S )a~  
        Get tuple containing the default chromium arguments that will be passed to chromium if not overridden.

        chromium arguments can be overridden in the Scope constructor using the chromium_args argument, or they
        can be overridden by assigning a tuple to the chromium_args property of an already constructed Scope instance

        :return: tuple of str
        )Ú_default_chromium_argsÚ_scope_chromium_args©Úclsr   r   úR/var/www/html/bwave/python/venv/lib/python3.8/site-packages/kaleido/scopes/base.pyÚdefault_chromium_args    s    
zBaseScope.default_chromium_argsTc                 C   s`   |dkr|   ¡ }n|dkrd}|dkr4dd„ |D ƒ}t|ƒ| _t ¡ | _d | _d | _tƒ | _	d S )NTFr   c                 S   s   g | ]}|d kr|‘qS ©r   r   ©Ú.0Úargr   r   r   Ú
<listcomp>9   s      z&BaseScope.__init__.<locals>.<listcomp>)
r   ÚtupleÚ_chromium_argsÚioÚBytesIOÚ
_std_errorÚ_std_error_threadÚ_procr   Ú
_proc_lock)ÚselfÚdisable_gpuÚchromium_argsr   r   r   Ú__init__,   s    


zBaseScope.__init__c                 C   s   |   ¡  d S ©N)Ú_shutdown_kaleido©r   r   r   r   Ú__del__C   s    zBaseScope.__del__c              	   C   s~   t j t j t j t j t¡¡¡dd¡}t j |¡r:|}n@tdƒ}|d krzt j 	dt j
¡}| t jd¡}tdj||d�ƒ‚|S )NÚ
executableZkaleidoÚPATHz
    aC  
The kaleido executable is required by the kaleido Python library, but it was not included
in the Python package and it could not be found on the system PATH.

Searched for included kaleido executable at:
    {vendored_executable_path} 

Searched for executable 'kaleido' on the following system PATH:
    {formatted_path}
)Úvendored_executable_pathÚformatted_path)ÚosÚpathÚjoinÚdirnameÚabspathÚ__file__ÚexistsÚwhichÚenvironÚgetÚdefpathÚreplaceÚpathsepÚ
ValueErrorÚformat)r   r%   Úexecutable_pathr(   r&   r   r   r   r6   F   s$    ý	öÿzBaseScope.executable_pathc                 C   sŒ   |   ¡ | jg}| jD ]f}t| |ƒ}|dkr<d| dd¡ }n4|dks|dkrPqn d| dd¡ d tt|ƒƒ }| |¡ q| | j	¡ |S )zÆ
        Build list of kaleido command-line arguments based on current values of
        the properties specified by self._scope_flags and self.chromium_args

        :return: list of flags
        Tz--Ú_ú-FNú=)
r6   Ú
scope_nameÚ_scope_flagsÚgetattrr2   ÚreprÚstrÚappendÚextendr   )r   Ú	proc_argsÚkÚvÚflagr   r   r   Ú_build_proc_argsj   s    

 zBaseScope._build_proc_argsc                 C   s.   | j dk	r$| j j ¡ }| j |¡ q dS q dS )z‘
        Write standard-error of subprocess to the _std_error StringIO buffer.
        Intended to be called once in a background thread
        N)r   ÚstderrÚreadliner   Úwrite©r   Úvalr   r   r   Ú_collect_standard_errorƒ   s    
z!BaseScope._collect_standard_errorc              	   C   s.  | j dks| j  ¡ dk	�r*| j�� | j dks>| j  ¡ dk	�r | j dk	rR| j  ¡  t ¡ | _|  ¡ }tj	|tj
tj
tj
tjdkd�| _ | jdksš| j ¡ s¾t| jd�| _| j d¡ | j ¡  | j j ¡  d¡}|sêd|  ¡  }t|ƒ‚n6t |¡}| dd	¡d	k�r | j  ¡  t| d
d¡ƒ‚W 5 Q R X dS )z`
        Launch the kaleido subprocess if it is not already running and in a good state
        NÚwin32)ÚstdinÚstdoutrF   Úshell)ÚtargetTúutf-8z3Failed to start Kaleido subprocess. Error stream:

Úcoder   Úmessagez"Failed to start Kaleido subprocess)r   Úpollr   Úwaitr   r   r   rE   Ú
subprocessÚPopenÚPIPEÚsysÚplatformr   Úis_aliver   rK   Ú	setDaemonÚstartrN   rG   ÚdecodeÚ_get_decoded_std_errorr4   ÚjsonÚloadsr0   )r   rA   Zstartup_response_stringrS   Zstartup_responser   r   r   Ú_ensure_kaleido’   s:    



û	
ÿÿ


zBaseScope._ensure_kaleidoc                 C   s‚   d}zt jj}| j ¡  |¡}W n tk
r4   Y nX |dkrrzt d¡}| j ¡  |¡}W n tk
rp   Y nX |dkr~d}|S )zK
        Attempt to decode standard error bytes stream to a string
        NFz1Failed to decode Chromium's standard error stream)	rY   rF   Úencodingr   Úgetvaluer^   Ú	ExceptionÚlocaleÚgetpreferredencoding)r   Zstd_err_strrc   r   r   r   r_   Ã   s    
z BaseScope._get_decoded_std_errorc              	   C   sj   | j dk	rf| j�P | j dk	r\| j  ¡ dkr6| j j ¡  z| j jdd� W n   Y nX d| _ W 5 Q R X dS )z_
        Shut down the kaleido subprocess, if any, and self the _proc property to None
        Ng       @)Útimeout)r   r   rT   rM   ÚcloserU   r!   r   r   r   r    Ú   s    

zBaseScope._shutdown_kaleidoc                 C   s   t ‚d S r   )ÚNotImplementedErrorr!   r   r   r   r:   ô   s    zBaseScope.scope_namec                 C   s
   d| j kS )zT If True, asks chromium to disable GPU hardware acceleration with --disable-gpu flagr   )r   r!   r   r   r   r   ù   s    zBaseScope.disable_gpuc                 C   s,   dd„ | j D ƒ}|r| d¡ t|ƒ| _ d S )Nc                 S   s   g | ]}|d kr|‘qS r   r   r   r   r   r   r      s      z)BaseScope.disable_gpu.<locals>.<listcomp>r   )r   r?   r   )r   rJ   Únew_argsr   r   r   r   þ   s    
c                 C   s   | j S r   )r   r!   r   r   r   r     s    zBaseScope.chromium_argsc                 C   s   t |ƒ| _|  ¡  d S r   )r   r   r    rI   r   r   r   r   	  s    
c              	   K   sØ   |   ¡  tjt||d�| jd� d¡}| j�J t ¡ | _	| j
j |¡ | j
j d d¡¡ | j
j ¡  | j
j ¡ }W 5 Q R X | d¡}|sžd|  ¡  }t|ƒ‚zt |¡}W n& tk
rÒ   tdt|ƒ ƒ ‚ Y nX |S )aS  
        Transform input data using the current scope, returning dict response with error code
        whether successful or not.

        :param data: JSON-serializable object to be converted
        :param kwargs: Transform arguments for scope
        :return: Dict of response from Kaleido executable, whether successful or not
        )Údatar
   rQ   Ú
z!Transform failed. Error stream:

zInvalid JSON: )rb   r`   ÚdumpsÚdictÚ_json_encoderÚencoder   r   r   r   r   rM   rH   ÚflushrN   rG   r^   r_   r4   ra   r   Úprintr=   )r   rl   ÚkwargsZexport_specÚresponseZresponse_stringrS   r   r   r   Ú_perform_transform  s4    

þþ

ÿÿzBaseScope._perform_transformc                 K   sT   | j |f|Ž}| dd¡}|dkr@| dd¡}tdj||d�ƒ‚| dd¡}| ¡ S )a  
        Transform input data using the current scope

        Subclasses should provide a more helpful docstring

        :param data: JSON-serializable object to be converted
        :param kwargs: Transform arguments for scope
        :return: Transformed value as bytes
        rR   r   rS   Nz2Transform failed with error code {code}: {message})rR   rS   Úresult)rv   Úpopr0   r4   r5   rq   )r   rl   rt   ru   rR   rS   Z
img_stringr   r   r   Ú	transform:  s    
 ÿÿzBaseScope.transform)TT)Ú__name__Ú
__module__Ú__qualname__rp   r;   r   r	   Úclassmethodr   r   r"   r6   rE   rK   rb   r_   r    Úpropertyr:   r   Úsetterr   rv   ry   r   r   r   r   r      s:   
  ý

#1




,r   c                    s"  dd„ }t j ˆ ¡r&|ˆ |ƒr"ˆ S dS |dkr>t j dt j¡}|sFdS | t j¡}tj	dkr¼t j
|krt| dt j
¡ t j dd¡ t j¡}t‡ fd	d
„|D ƒƒr¨ˆ g}qÂ‡ fdd„|D ƒ}nˆ g}tƒ }|D ]P}t j |¡}||krÌ| |¡ |D ](}	t j ||	¡}
||
|ƒrò|
    S qòqÌdS )a«  
    Backport (unmodified) of shutil.which command from Python 3.6
    Remove this when Python 2 support is dropped

    Given a command, mode, and a PATH string, return the path which
    conforms to the given mode on the PATH, or None if there is no such
    file.

    `mode` defaults to os.F_OK | os.X_OK. `path` defaults to the result
    of os.environ.get("PATH"), or can be overridden with a custom search
    path.
    c                 S   s&   t j | ¡o$t  | |¡o$t j | ¡ S r   )r'   r(   r-   ÚaccessÚisdir)ÚfnÚmoder   r   r   Ú_access_checke  s    z which_py2.<locals>._access_checkNr$   rL   r   ÚPATHEXTÚ c                 3   s    | ]}ˆ   ¡  |  ¡ ¡V  qd S r   )ÚlowerÚendswith©r   Úext©Úcmdr   r   Ú	<genexpr>�  s     zwhich_py2.<locals>.<genexpr>c                    s   g | ]}ˆ | ‘qS r   r   r‰   r‹   r   r   r   „  s     zwhich_py2.<locals>.<listcomp>)r'   r(   r*   r/   r0   r1   Úsplitr3   rY   rZ   ÚcurdirÚinsertÚanyÚsetÚnormcaseÚaddr)   )rŒ   rƒ   r(   r„   ÚpathextÚfilesÚseenÚdirÚnormdirÚthefileÚnamer   r‹   r   Ú	which_py2U  s8    




rœ   c                 C   s(   t jdkrddl}| | ¡S t| ƒS dS )aÉ  
    Return the absolute path of the input executable string, based on the
    user's current PATH variable.

    This is a wrapper for shutil.which that is compatible with Python 2.

    Parameters
    ----------
    cmd: str
        String containing the name of an executable on the user's path.

    Returns
    -------
    str or None
        String containing the absolute path of the executable, or None if
        the executable was not found.

    )é   r   r   N)rY   Úversion_infoÚshutilr.   rœ   )rŒ   rŸ   r   r   r   r.   –  s    

r.   )rV   r`   Ú	threadingr   r   r   r'   rY   rf   r   ÚImportErrorr4   Úobjectr   ÚF_OKÚX_OKrœ   r.   r   r   r   r   Ú<module>   s   
  HA