U
    /e4[                     @  s  d dl mZ d dlZ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
mZmZmZ d dlmZ d dlZd dlZdZdae Zg Ze ZG dd deZG dd	 d	ejZdddZdd Zdd Zdd Z dddZ!dd Z"dd Z#dd Z$dS )    )annotationsN)adapter)jsonlog	messagingsockets)
componentsc                   @  s   e Zd ZU dZded< ded< ded< ded< ded	< d
ed< dd Zdd Zdd Zdd Zdd Z	dd Z
dd Zdd ZdS )
Connectionaw  A debug server that is connected to the adapter.

    Servers that are not participating in a debug session are managed directly by the
    corresponding Connection instance.

    Servers that are participating in a debug session are managed by that sessions's
    Server component instance, but Connection object remains, and takes over again
    once the session ends.
    booldisconnectedprocess_replacedzServer | Noneserverz
int | Nonepidppidzmessaging.JsonMessageChannelchannelc           	   	     s  ddl m} d _d _d  _d  _tj|t	 }t
|  _ j  z̈    jd}|dt }|dt _|dtdd	 _ jd
krd  _t	   j_|_t^  jrW 5 Q R  W d S t fddtD rt  dttdk}t  t  W 5 Q R X W n2 tk
rL   td  j  t   Y d S X |! j}|d krp|! j}|d krt"d  nt j|jkr|j}|r|j#jst$d|  j  d S z|j%&  W d S  tk
r   td  Y nX |rd S t"d  zB jdddi  jdd ji  jd  jd W n* tk
r~   td  j  Y nX d S )Nr   )sessionsFZpydevdSystemInfoprocessr   r   Toptional c                 3  s"   | ]}|j  j ko|j V  qd S N)r   r   .0connselfr   ;/tmp/pip-unpacked-wheel-dg3irmqq/debugpy/adapter/servers.py	<genexpr>c   s   z&Connection.__init__.<locals>.<genexpr>z% is already connected to this adapterz,Failed to accept incoming server connection:z2No active debug session for parent process of {0}.z!{0} is not expecting replacement.z*Failed to notify parent session about {0}:z(No clients to wait for - unblocking {0}.
initializeZ	adapterIDdebugpyattachZsubProcessIdZconfigurationDone
disconnectz&Failed to unblock orphaned subprocess:)'debugpy.adapterr   r   r   r   r   r   ZJsonIOStreamZfrom_socketstrZJsonMessageChannelr   startauthenticaterequestr   objectintr   name_lockany_connectionsKeyErrorlenappend_connections_changedset	Exceptionr   swallow_exceptionclosedont_wait_for_first_connectiongetinfo
connectionerrorclientZnotify_of_subprocess)	r   sockr   streamr7   Zprocess_infoZis_first_serverZparent_sessionZparent_serverr   r   r   __init__?   s|    







 

zConnection.__init__c                 C  s    d| j d krdnd| j  d S )NServerz[?]z[pid=]r   r   r   r   r   __str__   s    zConnection.__str__c                 C  sL   t d krtj d krd S | jddt i}|d tj krH| j  tdd S )NZpydevdAuthorizeZdebugServerAccessTokenZclientAccessTokenz6Mismatched "clientAccessToken"; server not authorized.)access_tokenr   r   r&   r4   RuntimeError)r   authr   r   r   r%      s     
zConnection.authenticatec                 C  s   | dd S Nz=Requests from the debug server to the client are not allowed.Z
isnt_validr   r&   r   r   r   r&      s    zConnection.requestc                 C  s   d S r   r   r   eventr   r   r   rI      s    zConnection.eventc                 C  s   | j   d S r   r   r4   rH   r   r   r   terminated_event   s    zConnection.terminated_eventc              	   C  sJ   t < d| _| jd k	r"| j  n| tkr<t|  t  W 5 Q R X d S NT)r*   r   r   r!   r,   remover0   r1   r   r   r   r   r!      s    

zConnection.disconnectc              	   C  s<   t . | jdk	rttd| | t|| | _W 5 Q R X dS )zAttaches this server to the specified Session as a Server component.

        Raises ValueError if the server already belongs to some session.
        NzAttaching {0} to {1})r*   r   
ValueErrorr   r7   r>   r   sessionr   r   r   attach_to_session   s
    
zConnection.attach_to_sessionN)__name__
__module____qualname____doc____annotations__r=   rA   r%   r&   rI   rK   r!   rQ   r   r   r   r   r	   #   s   

f
r	   c                      s   e Zd ZU dZejjZded< G dd dejZ fddZ	e
dd	 Ze
d
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ddZedd Zdd Z fd d!Z  ZS )"r>   z1Handles the debug server side of a debug session.r	   r8   c                   @  sJ   e Zd Zdddddddddddddddddddddddddg g g dZdS )zServer.CapabilitiesFT)ZsupportsCompletionsRequestZsupportsConditionalBreakpointsZ supportsConfigurationDoneRequestZsupportsDataBreakpointsZ supportsDelayedStackTraceLoadingZsupportsDisassembleRequestZsupportsEvaluateForHoversZsupportsExceptionInfoRequestZsupportsExceptionOptionsZsupportsFunctionBreakpointsZsupportsGotoTargetsRequestZ!supportsHitConditionalBreakpointsZsupportsLoadedSourcesRequestZsupportsLogPointsZsupportsModulesRequestZsupportsReadMemoryRequestZsupportsRestartFrameZsupportsRestartRequestZsupportsSetExpressionZsupportsSetVariableZsupportsStepBackZsupportsStepInTargetsRequestZsupportsTerminateRequestZsupportsTerminateThreadsRequestZsupportsValueFormattingOptionsZexceptionBreakpointFiltersZadditionalModuleColumnsZsupportedChecksumAlgorithmsN)rR   rS   rT   Z
PROPERTIESr   r   r   r   Capabilities   s:   rW   c              	     s   |j d kst|v |j rtt j||jd || _| jjd ksFt| jjrt| jjj| jkrtt	
d| jjj| j | j| j_| |_ W 5 Q R X d S )N)r   z6Launcher reported PID={0}, but server reported PID={1})r   AssertionErrorsuperr=   r   r8   rP   r   launcherr   r7   )r   rP   r8   	__class__r   r   r=      s    

zServer.__init__c                 C  s   | j jS )z>Process ID of the debuggee process, as reported by the server.)r8   r   r   r   r   r   r     s    z
Server.pidc                 C  s   | j jS )zEParent process ID of the debuggee process, as reported by the server.)r8   r   r   r   r   r   r     s    zServer.ppidc                 C  s@   | dst| j  | j|}|  | | |j| _	d S )Nr   )
Z
is_requestrX   r8   r%   r   	propagateZwait_for_responserW   responseZcapabilitiesrG   r   r   r   r     s
    
zServer.initializec                 C  s   | dd S rE   rF   rG   r   r   r   r&   "  s    zServer.requestc                 C  s   | j | d S r   )r:   propagate_after_startrH   r   r   r   rI   .  s    zServer.eventc                 C  s   d S r   r   rH   r   r   r   initialized_event2  s    zServer.initialized_eventc                 C  s   | j s| j| d S r   )rZ   r:   r_   rH   r   r   r   process_event7  s    zServer.process_eventc                 C  s   | j jdkr| j | d S )N)ZvisualstudioZvsformac)r:   Z	client_idr_   rH   r   r   r   continued_event=  s    zServer.continued_eventzmessaging.Event)rI   c                 C  s2   |dt dddkrd| j_n| js.| j| d S )NZpydevdReasonTr   ZprocessReplaced)r#   r8   r   rZ   r:   r_   rH   r   r   r   exited_eventU  s    
zServer.exited_eventc                 C  s   | j   d S r   rJ   rH   r   r   r   rK   b  s    zServer.terminated_eventc              	   C  sD   t 6 d| _| j| j_t| j | j_| jj_d | j_W 5 Q R X d S )NF)	r*   is_connectedr8   r   handlersr#   r)   r<   r   r   r   r   r   detach_from_sessiong  s
    
zServer.detach_from_sessionc              	     s    j jrXtd   jjr(jjs@t fdddd n j fdddd t	 t
 j  t  W 5 Q R X t   d S )Nz*{0} is waiting for replacement subprocess.c                   s   | j  j kS r   r@   )r   r   r   r   <lambda>v      z#Server.disconnect.<locals>.<lambda>   )timeoutc                     s,   j  p*j j p*t fddj jD S )Nc                 3  s   | ]}|j  j kV  qd S r   r@   r   r   r   r   r   }  s   z6Server.disconnect.<locals>.<lambda>.<locals>.<genexpr>)r:   rd   r+   Zknown_subprocessesr   rO   r   r   rg   z  s    )r8   r   r   r7   rP   r:   rd   wait_for_connectionwait_forr*   r,   rM   r0   r1   rY   r!   r   r[   rO   r   r!   n  s"     
 zServer.disconnect)rR   rS   rT   rU   r   	ComponentZmessage_handlerrV   rW   r=   propertyr   r   r   r&   rI   r`   ra   rb   rc   rK   rf   r!   __classcell__r   r   r[   r   r>      s4   
 







r>   	127.0.0.1c                 C  s   t dt| |at S )Nr>   )r   server	   listenergetsockname)hostportr   r   r   rq     s    rq   c                   C  s   t d k	S r   )rr   r   r   r   r   
is_serving  s    rv   c                   C  s>   zt d k	rt   d a W n  tk
r8   tjdd Y nX d S )Nwarning)level)rr   r4   r2   r   r3   r   r   r   r   stop_serving  s    ry   c                
   C  s$   t  ttW  5 Q R  S Q R X d S r   )r*   listr,   r   r   r   r   connections  s    r{   c              
     s   fdddk_ r8tjdd}d|_|  dkrLtd|  tH t	   fdd	t
D }t|d
}|d
k	sj r|W  5 Q R  S W 5 Q R X t  qLd
S )zWaits until there is a server matching the specified predicate connected to
    this adapter, and returns the corresponding Connection.

    If there is more than one server connection already available, returns the oldest
    one.
    c                	     s,   t   d_t t  W 5 Q R X d S rL   )timesleep	timed_outr*   r0   r1   r   )rj   wait_for_timeoutr   r   r     s    
z-wait_for_connection.<locals>.wait_for_timeoutr   z%servers.wait_for_connection() timeout)targetr)   Tz/{0} waiting for connection from debug server...c                 3  s   | ]} |r|V  qd S r   r   r   )	predicater   r   r     s      z&wait_for_connection.<locals>.<genexpr>N)r~   	threadingThreaddaemonr$   r   r7   r*   r0   clearr,   nextwait)rP   r   rj   threadZconnsr   r   )r   rj   r   r   rk     s$    
 
rk   c                	   C  s<   t   t$ t   tts,W 5 Q R  dS W 5 Q R X q dS )zBlocks until all debug servers disconnect from the adapter.

    If there are no server connections, waits until at least one is established first,
    before waiting for it to disconnect.
    N)r0   r   r*   r   r.   r,   r   r   r   r   wait_until_disconnected  s
    r   c                	   C  s   t  t  W 5 Q R X dS )zlUnblocks any pending wait_until_disconnected() call that is waiting on the
    first server to connect.
    N)r*   r0   r1   r   r   r   r   r5     s    r5   c           	   
     sD  t  \}}tjtjtjd|d t	| g}t
jd k	rH|dt
jg7 }||7 }|dt	g7 }td| ztj|dtjtjtjd W n@ tk
r } z"td td	|W 5 d }~X Y nX g d
 fdd}tj|d d jfdd   fdd}tj|d ddd  d S )Nz	--connect:z--adapter-access-tokenz--pidz/Spawning attach-to-PID debugger injector: {0!r}r   )bufsizestdinstdoutstderrz7Failed to inject debug server into process with PID={0}z<Failed to inject debug server into process with PID={0}: {1}z$--- Starting attach to pid: {0} ---
c                   s   zH|   }|sq:|dd}| td|  qtd W n6 tk
r~   t }t	j
|d  d|  Y nX d S )Nzutf-8replacezInjector[PID={0}] output: {1}zInjector[PID={0}] exited.)filer   )readlinedecoder/   r   r7   rstripr2   ioStringIO	traceback	print_excgetvalue)r<   lines)	on_outputoutput_collectedr   r   r   capture  s    
zinject.<locals>.capturezInjector[PID=z] stdoutT)r   r)   argsr   c                    s$  d} t   }t d   }|d k	r^|dkrZdd }g d|}dd| q t   | }dd|f  | s|d	krd
} tjdkrdd dd dd dd dd dd dd dd dd dd | r}g d|}|rd| qd S )NF   r   r   zAttach to PID failed.

 r   z'Attaching to PID: %s (elapsed: %.2fs).

   T)linuxZlinux2z3
The attach to PID is taking longer than expected.
z1On Linux it's possible to customize the value of
z<`PYDEVD_GDB_SCAN_SHARED_LIBRARIES` so that fewer libraries.
z4are scanned when searching for the needed symbols.

zHi.e.: set in your environment variables (and restart your editor/client
z>so that it picks up the updated environment variable value):

zCPYDEVD_GDB_SCAN_SHARED_LIBRARIES=libdl, libltdl, libc, libfreebl3

zA-- the actual library may be different (the gdb output typically
zE-- writes the libraries that will be used, so, it should be possible
z8-- to test other libraries if the above doesn't work).

)r|   r}   polljoinsysplatform)Ztaking_longer_than_expectedZinitial_time
returncodeoldcontentselapsedZinjectorr   r   r   r   r   info_on_timeout  s    

 


zinject.<locals>.info_on_timeoutz] info on timeout)r   r)   r   )rr   rs   r   
executableospathdirnamer   __file__r#   r   rB   r   r7   
subprocessPopenPIPESTDOUTr2   r3   r   ZMessageHandlingErrorformatr/   r   r   r   r$   )	r   Zdebugpy_argsr   rt   ru   Zcmdlineexcr   r   r   r   r   inject  sZ    

  


N 
 r   )rp   r   )N)%
__future__r   r   r   r   r   r|   r   r   Zdebugpy.commonr   r   r   r   r"   r   r   r   rB   rr   RLockr*   r,   Eventr0   r'   r	   rm   r>   rq   rv   ry   r{   rk   r   r5   r   r   r   r   r   <module>   s8    4 5


"