
    {h8*                     d   d 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m	Z	m
Z
 ddlZddlmZ ddlmZ ddlmZmZ ddlmZ  ej(                  d	      Zej,                  d
k(  rddlZddlZddlZddlZndZdZdZdZeZdedefdZ G d d      Zdej@                  dfdede!e   de"eef   dz  de	dz  deez  dz  deez  fdZ#dej@                  dfdede!e   de"eef   dz  de	dz  deez  dz  defdZ$dedz  fdZ%deez  dedz  ddfdZ&ddeez  de'ddfdZ( ed      deez  fd       Z)y)z=
Windows-specific functionality for stdio client operations.
    N)Path)BinaryIOTextIOcast)	to_thread)Process)FileReadStreamFileWriteStream)
deprecatedzclient.stdio.win32win32commandreturnc                     	 t        j                  |       x}r|S dD ]#  }|  | }t        j                  |      x}s!|c S  | S # t        $ r | cY S w xY w)aB  
    Get the correct executable command normalized for Windows.

    On Windows, commands might exist with specific extensions (.exe, .cmd, etc.)
    that need to be located for proper execution.

    Args:
        command: Base command (e.g., 'uvx', 'npx')

    Returns:
        str: Windows-appropriate command path
    )z.cmdz.batz.exez.ps1)shutilwhichOSError)r   command_pathextext_versionext_paths        W/var/www/html/hubwallet-dev/venv/lib/python3.12/site-packages/mcp/os/win32/utilities.pyget_windows_executable_commandr   $   sv    !<<00<0 4 	 C$IcU+K!<<44x4	    s!   A "A A A AAc                       e Zd ZdZdej
                  e   fdZd Zde	dz  de	dz  de
dz  d	dfd
Zd Zd ZddZed	efd       Zy)FallbackProcessa7  
    A fallback process wrapper for Windows to handle async I/O
    when using subprocess.Popen, which provides sync-only FileIO objects.

    This wraps stdin and stdout into async-compatible
    streams (FileReadStream, FileWriteStream),
    so that MCP clients expecting async streams can work properly.
    	popen_objc                 \   || _         |j                  | _        |j                  | _        |j
                  | _        | j                  r#t        t        t        | j                              nd | _        | j                  r)t        t        t        | j                              | _        y d | _        y )N)
popenstdin	stdin_rawstdout
stdout_rawstderrr
   r   r   r	   )selfr   s     r   __init__zFallbackProcess.__init__N   sr    .7
"#**&&HL_T(DNN%CD\`
IMnT(DOO%DE^b    c                    K   | S w)z$Support async context manager entry. r#   s    r   
__aenter__zFallbackProcess.__aenter__W   s     s   exc_typeNexc_valexc_tbr   c                 L  K   | j                   j                          t        j                  | j                   j                         d{    | j
                  r"| j
                  j                          d{    | j                  r"| j                  j                          d{    | j                  r| j                  j                          | j                  r| j                  j                          | j                  r| j                  j                          yy7 7 7 |w)z3Terminate and wait on process exit inside a thread.N)r   	terminater   run_syncwaitr   acloser    r   closer!   r"   )r#   r*   r+   r,   s       r   	__aexit__zFallbackProcess.__aexit__[   s      	

  111 ::**##%%%;;++$$&&&>>NN  "??OO!!#;;KK  	2 &&s7   AD$	D
-D$7D 8-D$%D"&A9D$ D$"D$c                 p   K   t        j                  | j                  j                         d{   S 7 w)z"Async wait for process completion.N)r   r/   r   r0   r(   s    r   r0   zFallbackProcess.waitq   s%     ''

8888s   -646c                 6    | j                   j                         S )z%Terminate the subprocess immediately.)r   r.   r(   s    r   r.   zFallbackProcess.terminateu   s    zz##%%r%   c                 $    | j                          y)z6Kill the subprocess immediately (alias for terminate).N)r.   r(   s    r   killzFallbackProcess.killy   s    r%   c                 .    | j                   j                  S )zReturn the process ID.)r   pidr(   s    r   r9   zFallbackProcess.pid}   s     zz~~r%   )r   N)__name__
__module____qualname____doc__
subprocessPopenbytesr$   r)   BaseExceptionobjectr3   r0   r.   r7   propertyintr9   r'   r%   r   r   r   D   s    c*"2"25"9 c $&  %  	 
 
 ,9& S  r%   r   argsenverrlogcwdc                 z  K   t               }d}	 t        j                  | g||t        t        d      rt        j
                  nd||       d{   }t        ||       |S 7 # t        $ r t        | ||||       d{  7  }Y 3t        $ r( t        j                  | g||||       d{  7  }Y bw xY ww)a  
    Creates a subprocess in a Windows-compatible way with Job Object support.

    Attempt to use anyio's open_process for async subprocess creation.
    In some cases this will throw NotImplementedError on Windows, e.g.
    when using the SelectorEventLoop which does not support async subprocesses.
    In that case, we fall back to using subprocess.Popen.

    The process is automatically added to a Job Object to ensure all child
    processes are terminated when the parent is terminated.

    Args:
        command (str): The executable to run
        args (list[str]): List of command line arguments
        env (dict[str, str] | None): Environment variables
        errlog (TextIO | None): Where to send stderr output (defaults to sys.stderr)
        cwd (Path | str | None): Working directory for the subprocess

    Returns:
        Process | FallbackProcess: Async-compatible subprocess with stdin and stdout streams
    NCREATE_NO_WINDOWr   )rF   creationflagsr"   rH   )rF   r"   rH   )
_create_job_objectanyioopen_processhasattrr>   rJ   NotImplementedError _create_windows_fallback_process	Exception_maybe_assign_process_to_job)r   rE   rF   rG   rH   jobprocesss          r   create_windows_processrV      s     8 
CG
**t z#56 %55	
 	
, !#.N/	
  Z8$VUXYYY 
**t	
 
 

s_   B;A A% A#A% B;#A% %B8 BB8B;'B8/B20B85B;7B88B;c                 `  K   	 t        j                  | g|t         j                  t         j                  |||dt        t         dd            }t        |      S # t        $ rH t        j                  | g|t         j                  t         j                  |||d      }Y t        |      S w xY ww)z
    Create a subprocess using subprocess.Popen as a fallback when anyio fails.

    This function wraps the sync subprocess.Popen in an async-compatible interface.
    r   rJ   )r   r    r"   rF   rH   bufsizerK   )r   r    r"   rF   rH   rX   )r>   r?   PIPEgetattrrR   r   )r   rE   rF   rG   rH   r   s         r   rQ   rQ      s     
$$t//??!*.@!D	
	* 9%%  

$$t//??
	 9%%

s*   B.AA B.AB+B.*B++B.c                     t         j                  dk7  st        sy	 t        j                  dd      } t        j                  | t        j
                        }|d   dxx   t        j                  z  cc<   t        j                  | t        j
                  |       | S # t        $ r"}t        j                  d|        Y d}~yd}~ww xY w)zX
    Create a Windows Job Object configured to terminate all processes when closed.
    r   N BasicLimitInformation
LimitFlagsz9Failed to create Job Object for process tree management: )sysplatformwin32jobCreateJobObjectQueryInformationJobObject!JobObjectExtendedLimitInformation"JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSESetInformationJobObjectrR   loggerwarning)rT   extended_infoes      r   rL   rL      s     ||wh	&&tR0 ::3@j@jk-.|<@k@kk<((h.X.XZgh
 RSTRUVWs   A>B 	C$CCrU   rT   c                 B   |syt         j                  dk7  st        rt        rt        sy	 t        j
                  t        j                  t        j                  z  d| j                        }|st        d      	 t	        j                  ||       || _        t        j                  |       y# t        j                  |       w xY w# t        $ rO}t        j                  d| j                   d|        t        rt        j                  |       Y d}~yY d}~yd}~ww xY w)zt
    Try to assign a process to a job object. If assignment fails
    for any reason, the job handle is closed.
    Nr   FzFailed to open process handlezFailed to assign process z to Job Object: )r_   r`   win32apiwin32conra   OpenProcessPROCESS_SET_QUOTAPROCESS_TERMINATEr9   rR   AssignProcessToJobObject_job_objectCloseHandlerg   rh   )rU   rT   process_handlerj   s       r   rS   rS      s    
 
||whhh&!--&&)C)CCUGKK
 ;<<	1--c>B"%G  0H  0 &27;;-?OPQsST  %% &s1   AC 9B, C ,CC 	DA DDtimeout_secondsc                   K   t         j                  dk7  ryt        | dd      }|r9t        r3	 t        j                  |d       t        r	 t        j                  |       	 | j                          y# t
        $ r Y 9w xY w# t
        $ r Y ,w xY w# t        r&	 t        j                  |       w # t
        $ r Y w w xY ww xY w# t
        $ r Y yw xY ww)aD  
    Terminate a process and all its children on Windows.

    If the process has an associated job object, it will be terminated.
    Otherwise, falls back to basic process termination.

    Args:
        process: The process to terminate
        timeout_seconds: Timeout in seconds before force killing (default: 2.0)
    r   Nrr      )	r_   r`   rZ   ra   TerminateJobObjectrR   rl   rs   r.   )rU   ru   rT   s      r   terminate_windows_process_treery     s      ||w
'=$
/C
x
	''Q/
 ((-
  		 !  ((-     s   *CA1 C
B   C  0C1	A=:B <A==B  	B	CBCB=B-,B=-	B96B=8B99B==C 	C	CCCzterminate_windows_process is deprecated and will be removed in a future version. Process termination is now handled internally by the stdio_client context manager.c                    K   	 | j                          t        j                  d      5  | j                          d{    ddd       y7 # 1 sw Y   yxY w# t        $ r | j                          Y yw xY ww)aB  
    Terminate a Windows process.

    Note: On Windows, terminating a process with process.terminate() doesn't
    always guarantee immediate process termination.
    So we give it 2s to exit, or we call process.kill()
    which sends a SIGKILL equivalent signal.

    Args:
        process: The process to terminate
           @N)r.   rM   
fail_afterr0   TimeoutErrorr7   )rU   s    r   terminate_windows_processr~   <  sh      c" 	!,,.  	! 	! 	! 	! s[   A8%A AAAA 
A8AAA A8A A52A84A55A8)r{   )*r=   loggingr   r>   r_   pathlibr   typingr   r   r   rM   r   	anyio.abcr   anyio.streams.filer	   r
   typing_extensionsr   	getLoggerrg   r`   
pywintypesrl   rm   ra   rD   	JobHandlestrr   r   r"   listdictrV   rQ   rL   rS   floatry   r~   r'   r%   r   <module>r      s      
  ) )    > (			/	0 <<7 HHHJ	C C @< <N "&JJ!88
s)8 
c3h$	8 TM	8
 
d	8 8| "&JJ!#&#&
s)#& 
c3h$	#& TM	#&
 
d	#& #&LC$J &&'O*C &)VZJZ &_c &: 'O2K  ^c  nr  F YW-F 	r%   