
    Te'                         d dl Z d dlZd dlZd dlmZmZmZ d dlmZ ddl	m
Z
mZmZmZ  e j                  e      ZdZdZ G d d	      Zy)
    N)AnyDictMapping)futures   )JsonRpcExceptionJsonRpcRequestCancelledJsonRpcInternalErrorJsonRpcMethodNotFoundz2.0z$/cancelRequestc            	           e Zd Zd dfdZd ZddZddZd Zd	 Zd
 Z	e
d        Zd Ze
deeef   dedeeef   fd       Zd Zd ZddZy)Endpointc                  <    t        t        j                               S N)struuiduuid4     8/usr/lib/python3/dist-packages/pylsp_jsonrpc/endpoint.py<lambda>zEndpoint.<lambda>   s    #djjlBS r      c                     || _         || _        || _        i | _        i | _        t        j                  |      | _        y)a  A JSON RPC endpoint for managing messages sent to/from the client.

        Args:
            dispatcher (dict): A dictionary of method name to handler function.
                The handler functions should return either the result or a callable that will be used to asynchronously
                compute the result.
            consumer (fn): A function that consumes JSON RPC message dicts and sends them to the client.
            id_generator (fn, optional): A function used to generate request IDs.
                Defaults to the string value of :func:`uuid.uuid4`.
            max_workers (int, optional): The number of workers in the asynchronous executor pool.
        )max_workersN)_dispatcher	_consumer_id_generator_client_request_futures_server_request_futuresr   ThreadPoolExecutor_executor_service)self
dispatcherconsumerid_generatorr   s        r   __init__zEndpoint.__init__   s>     &!)')$')$!(!;!;!Tr   c                 8    | j                   j                          y r   )r    shutdown)r!   s    r   r'   zEndpoint.shutdown(   s    '')r   Nc                 t    t         j                  d||       t        |d}|||d<   | j                  |       y)zSend a JSON RPC notification to the client.

         Args:
             method (str): The method name of the notification to send
             params (any): The payload of the notification
         zSending notification: %s %s)jsonrpcmethodNparams)logdebugJSONRPC_VERSIONr   )r!   r*   r+   messages       r   notifyzEndpoint.notify+   sB     			/@ '
  &GHwr   c                     | j                         }t        j                  d|||       t        ||d}|||d<   t	        j
                         }|j                  | j                  |             || j                  |<   | j                  |       |S )a  Send a JSON RPC request to the client.

        Args:
            method (str): The method name of the message to send
            params (any): The payload of the message

        Returns:
            Future that will resolve once a response has been received
        z!Sending request with id %s: %s %s)r)   idr*   r+   )
r   r,   r-   r.   r   Futureadd_done_callback_cancel_callbackr   r   )r!   r*   r+   msg_idr/   request_futures         r   requestzEndpoint.request=   s     ##%		5vvvN '

  &GH )(()>)>v)FG/=$$V,wr   c                       fd}|S )z;Construct a cancellation callback for the given request ID.c                     | j                         r2j                  t        di       | j                  t	                      y y )Nr2   )	cancelledr0   CANCEL_METHODset_exceptionr	   )future
request_idr!   s    r   callbackz+Endpoint._cancel_callback.<locals>.callback\   s9    !MD*+=>$$%<%>? "r   r   r!   r?   r@   s   `` r   r5   zEndpoint._cancel_callbackZ   s    	@ r   c           	         d|vs|d   t         k7  rt        j                  d|       yd|vr;t        j                  d|       | j	                  |d   |j                  d             yd|vrKt        j                  d|       | j                  |d   |j                  d	      |j                  d
             y	 t        j                  d|       | j                  |d   |d   |j                  d             y# t        $ rM}t        j                  d|d          | j                  t         |d   |j                         d       Y d}~yd}~wt        $ rk t        j                  d|d          | j                  t         |d   t        j                  t        j                                j                         d       Y yw xY w)zConsume a JSON RPC message from the client.

        Args:
            message (dict): The JSON RPC message sent by the client
        r)   zUnknown message type %sNr2   z$Handling notification from client %sr*   r+   z Handling response from client %sresulterrorzHandling request from client %sFailed to handle request %s)r)   r2   rD   )r.   r,   warningr-   _handle_notificationget_handle_response_handle_requestr   	exceptionr   to_dict	Exceptionr
   ofsysexc_info)r!   r/   es      r   consumezEndpoint.consumeb   sy    G#wy'9_'LKK17;wII<gF%%gh&7X9NOW$II8'B!!'$-X1FT[H\]		;WE$$WT]GH4Ew{{S[G\]# ;WT]K.!$-YY[   
  ;WT]K.!$-144S\\^DLLN  s    7>C6 6	F>?AEA4F>=F>c                    |t         k(  r| j                  |d          y	 | j                  |   }	  ||      }t        |      rSt        j                  d|       | j                  j                  |      }|j                  | j                  ||             yy# t        $ r t        j                  d|       Y yw xY w# t        $ r t        j                  d||       Y yw xY w)z&Handle a notification from the client.r2   Nz+Ignoring notification for unknown method %sz$Failed to handle notification %s: %sz'Executing async notification handler %s)r<   _handle_cancel_notificationr   KeyErrorr,   rF   rM   rK   callabler-   r    submitr4   _notification_callback)r!   r*   r+   handlerhandler_resultnotification_futures         r   rG   zEndpoint._handle_notification   s    ]",,VD\:	&&v.G
	$V_N
 N#II?P"&"8"8"?"?"O11$2M2MfV\2]^ $  	KKEvN	  	MM@&&Q	s"   B B< B98B9< CCc                       fd}|S )z;Construct a notification callback for the given request ID.c                     	 | j                          t        j                  d       y # t        $ r t        j	                  d       Y y w xY w)Nz-Successfully handled async notification %s %sz)Failed to handle async notification %s %s)rC   r,   r-   rM   rK   )r>   r*   r+   s    r   r@   z1Endpoint._notification_callback.<locals>.callback   sG    [		I6SYZ [I6SYZ[s   '+  AAr   )r*   r+   r@   s   `` r   rX   zEndpoint._notification_callback   s    	[ r   c                     | j                   j                  |d      }|st        j                  d|       y|j	                         rt        j                  d|       yy)z-Handle a cancel notification from the client.Nz6Received cancel notification for unknown message id %szCancelled request with id %s)r   popr,   rF   cancelr-   )r!   r6   r7   s      r   rT   z$Endpoint._handle_cancel_notification   sR    5599&$GKKPRXY   "II4f= #r   headerrC   returnc                 |    t        |       }t        |t               rd|v sd|v r|j                  |       |S ||d<   |S )NrC   rD   )dict
isinstanceupdate)ra   rC   responses      r   _make_response_payloadzEndpoint._make_response_payload   sI     <fd#V);w&?POOF#  "(HXr   c                    	 | j                   |   } ||      }t	        |      rat
        j                  d|       | j                  j                  |      }|| j                  |<   |j                  | j                  |             yt        |t        j                        rFt
        j                  d|       || j                  |<   |j                  | j                  |             yt
        j                  d|       | j                  t         |d|      }| j#                  |       y# t        $ r}t        j                  |      |d}~ww xY w)z!Handle a request from the client.Nz"Executing async request handler %sz&Request handler is already a future %sz/Got result from synchronous request handler: %sr)   r2   )r   rU   r   rN   rV   r,   r-   r    rW   r   r4   _request_callbackre   r   r3   rh   r.   r   )	r!   r6   r*   r+   rY   rQ   rZ   r7   rg   s	            r   rJ   zEndpoint._handle_request   s    	:&&v.G !N#II:NK!33::>JN3AD((0,,T-C-CF-KL7II>O3AD((0,,T-C-CF-KLIIGX22.  H NN8$/  	:'**629	:s   D& &	E
/EE
c                       fd}|S )z6Construct a request callback for the given request ID.c                 8   j                   j                  d        | j                         r| j                  t	                      t
        d}	 | j                         }j                  ||      }j#                  |       y # t        $ r3}t        j                  d       |j                         |d<   Y d }~Id }~wt        $ rQ t        j                  d       t        j                  t        j                                j                         |d<   Y w xY w)Nrj   rE   rD   )r   r_   r;   r=   r	   r.   rC   rh   r   r,   rK   rL   rM   r
   rN   rO   rP   r   )r>   r/   rC   rQ   r?   r!   s       r   r@   z,Endpoint._request_callback.<locals>.callback   s    ((,,Z>!$$%<%>? + G
U55gvF NN7# $ /;ZH#$99;  U;ZH#7#:#:3<<>#J#R#R#T Us   "B 	D)B<<ADDr   rA   s   `` r   rk   zEndpoint._request_callback   s    	$0 r   c                 :   | j                   j                  |d      }|st        j                  d|       y|<t        j	                  d||       |j                  t        j                  |             yt        j	                  d||       |j                  |       y)z"Handle a response from the client.Nz*Received response to unknown message id %sz)Received error response to message %s: %sz"Received result for message %s: %s)	r   r_   r,   rF   r-   r=   r   	from_dict
set_result)r!   r6   rC   rD   r7   s        r   rI   zEndpoint._handle_response   s    5599&$GKKDfMIIA65Q(()9)C)CE)JK		6G!!&)r   r   )NN)__name__
__module____qualname__r%   r'   r0   r8   r5   rR   rG   staticmethodrX   rT   r   r   r   r   rh   rJ   rk   rI   r   r   r   r   r      s    :Sab U(* $:!F_.  
> tCH~ s wsTWxGX  %:8*r   r   )loggingr   rO   typingr   r   r   
concurrentr   
exceptionsr   r	   r
   r   	getLoggerrq   r,   r.   r<   r   r   r   r   <module>rz      sO      
 % % F F g!!s* s*r   