
    Xhw                         d 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
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mZmZ ddlmZ ddlmZ  G d de      Z G d de      Z G d de      Zy)a   Language Server stdio-mode readers

Parts of this code are derived from:

> https://github.com/palantir/python-jsonrpc-server/blob/0.2.0/pyls_jsonrpc/streams.py#L83   # noqa
> https://github.com/palantir/python-jsonrpc-server/blob/45ed1931e4b2e5100cc61b3992c16d6f68af2e80/pyls_jsonrpc/streams.py  # noqa
> > MIT License   https://github.com/palantir/python-jsonrpc-server/blob/0.2.0/LICENSE
> > Copyright 2018 Palantir Technologies, Inc.
    N)ThreadPoolExecutor)ListOptionalText)run_on_executor)convert_yielded)HTTPHeaders)IOLoop)Queue)FloatInstancedefault)LoggingConfigurable   )make_non_blockingc                   n     e Zd ZdZdZ eej                  d      Z ee	d      Z
d Z fdZd Z xZS )	LspStdIoBasezGNon-blocking, queued base for communicating with stdio Language ServersNzthe stream to read/writehelpzqueue to get/putc                 b    dj                  | j                  j                  | j                        S )Nz<{}(parent={})>)format	__class____name__parentselfs    E/var/www/html/myenv/lib/python3.12/site-packages/jupyter_lsp/stdio.py__repr__zLspStdIoBase.__repr__'   s#     ''(?(?MM    c                 ~    t        |   di | | j                  j                  d|        t	        d      | _        y )Nz%s initializedr   )max_workers )super__init__logdebugr   executor)r   kwargsr   s     r   r$   zLspStdIoBase.__init__*   s2    "6"'.*q9r   c                 p    | j                   j                          | j                  j                  d|        y )Nz	%s closed)streamcloser%   r&   r   s    r   r+   zLspStdIoBase.close/   s$    {D)r   )r   
__module____qualname____doc__r'   r   io	RawIOBaser*   r   queuer   r$   r+   __classcell__)r   s   @r   r   r      s>    QH
5F U!34EN:
*r   r   c                      e Zd ZdZ ed      j                  d      Z edd      j                  d      Z edd      j                  d      Z e	d	      d
        Z
d Zd ZddZ	 ddedee   fdZdefdZedefd       Zy)LspStdIoReaderzLanguage Server stdio Reader

    Because non-blocking (but still synchronous) IO is used, rudimentary
    exponential backoff is used.
    z#maximum time to wait on idle streamr   T)configg?z#minimum time to wait on idle streamz next time to wait on idle streammax_waitc                 J    t         j                  dk(  rdS | j                  dz  S )Nntg?   )osnamemin_waitr   s    r   _default_max_waitz LspStdIoReader._default_max_wait?   s     ggos<4==1+<<r   c                    K   | j                   j                  ryt        | j                  dz  | j                        | _        	 t        j                  | j                         d{    y7 # t        $ r Y yw xY ww)z'Simple exponential backoff for sleepingNr9   )r*   closedmin	next_waitr6   asynciosleep	Exceptionr   s    r   rC   zLspStdIoReader.sleepC   s]     ;;T^^a/?	--/// 		s<   A A<"A- %A+&A- *A<+A- -	A96A<8A99A<c                 &    | j                   | _        y)zReset the wait timeN)r<   waitr   s    r   wakezLspStdIoReader.wakeM   s    MM	r   returnNc                 0  K   t        | j                         | j                  j                  sd}	 | j                          d{   }|s| j	                          d{    L| j                          t        j                         j                  | j                  j                  |       | j                  j                  syy7 7 h# t        $ rA}| j                  j                  d| ||       | j	                          d{  7   Y d}~bd}~ww xY ww)z.Read from a Language Server until it is closedNz$%s couldn't enqueue message: %s (%s))r   r*   r?   read_onerC   rG   r
   currentadd_callbackr1   
put_nowaitrD   r%   	exception)r   messagees      r   readzLspStdIoReader.readQ   s     $++&++$$G# $/**,&&IIK --djj.C.CWM ++$$ 0 '  #"":D'1 jjl""	#sq   .DC	 CC	 CC	 #D$AC	 ,DDC	 C	 		D1DDD	DDDlengthc           
         K   d}g }d}||k  rt        |      |k  r~|dkD  ryd}	 | j                  j                  ||z
        }||dz  }| j	                          d{    Y|t        |      z  }|j                  |       ||k  rt        |      |k  r|dkD  ry|rOdj                  |      }t        |      |k7  r0| j                  j                  dt        |       d| d| d|        |S # t        $ r Y w xY w7 w)	a  Read the full length of the message unless exceeding max_parts or
           max_empties empty reads occur.

        See https://github.com/jupyter-lsp/jupyterlab-lsp/issues/450

        Crucial docs or read():
            "If the argument is positive, and the underlying raw
             stream is not interactive, multiple raw reads may be issued
             to satisfy the byte count (unless EOF is reached first)"

        Args:
           - length: the content length
           - max_parts: prevent absurdly long messages (1000 parts is several MBs):
             1 part is usually sufficient but not enough for some long
             messages 2 or 3 parts are often needed.
        Nr   r   r   z%Readout and content-length mismatch: z vs z;remaining empties: z; remaining parts: )	lenr*   rQ   OSErrorrC   appendjoinr%   warning)r   rR   	max_partsmax_emptiesraw	raw_partsreceived_sizeparts           r   _read_contentzLspStdIoReader._read_contentg   s)    & !#	f$Y))CVWD{{''(>? |q jjl""SY&MT" f$Y))CVW ((9%C3x6!  ;CH:T& R**56I)V
 
#   #s;   !C>C- C>C<<C>AC>-	C96C>8C99C>c                   K   d}t               }t        | j                                d{   }|r|rU|j                         rE|j	                  |       t        | j                                d{   }|r|j                         rEt        |j                  dd            }|rZ| j                  |       d{   }|!|j                  d      j                         }|S | j                  j                  d| |       |S 7 7 7 Jw)zRead a single message Nzcontent-length0)rR   utf-8z&%s failed to read message of length %s)r	   r   	_readlinestrip
parse_lineintgetr_   decoder%   rX   )r   rO   headerslinecontent_lengthr[   s         r   rJ   zLspStdIoReader.read_one   s     -$T^^%5664::<""4(,T^^-=>> 4::< !-=s!CDN ..n.EE?!jj1779G  HH$$@& ) 7
 ?
 Fs;   )DDAD1D2D	2D;D<ADDDc                     	 | j                   j                         j                  d      j                         S # t        $ r Y yw xY w)z(Read a line (or immediately return None)rc   ra   )r*   readlineri   re   rU   r   s    r   rd   zLspStdIoReader._readline   s@    	;;'')009??AA 		s   69 	AArH   N)i     )r   r,   r-   r.   r   tagr6   r<   rA   r   r=   rC   rG   rQ   rg   r   bytesr_   r   rJ   r   rd   r"   r   r   r4   r4   4   s     ?@DDDDQHT EFJJRVJWHd!CDHHPTHUIZ= ="#. 8;++	%+Z 6 4  r   r4   c                   *    e Zd ZdZddZedd       Zy)LspStdIoWriterzLanguage Server stdio WriterNc                 :  K   | j                   j                  s| j                  j                          d{   }	 |j	                  d      }dj                  t        |      |      }t        | j                  |j	                  d                   d{    | j                  j                          | j                   j                  syy7 7 9# t        $ r  | j                  j                  d|        Y _w xY w# | j                  j                          w xY ww)z*Write to a Language Server until it closesNrc   zContent-Length: {}

{}z%s couldn't write message: %s)r*   r?   r1   rh   encoder   rT   r   
_write_onerD   r%   rN   	task_done)r   rO   bodyresponses       r   writezLspStdIoWriter.write   s     ++$$ JJNN,,G'~~g.9@@TGT%doohoog6N&OPPP 

$$& ++$$, Q T""#BD(ST 

$$&sW   4DCDAC CC 0D
DC &C96C< 8C99C< <DDc                 n    | j                   j                  |       | j                   j                          y )N)r*   r{   flush)r   rO   s     r   rw   zLspStdIoWriter._write_one   s$    '"r   ro   )r   r,   r-   r.   r{   r   rw   r"   r   r   rt   rt      s    &'  r   rt   )r.   rB   r/   r:   concurrent.futuresr   typingr   r   r   tornado.concurrentr   tornado.genr   tornado.httputilr	   tornado.ioloopr
   tornado.queuesr   	traitletsr   r   r   traitlets.configr   non_blockingr   r   r4   rt   r"   r   r   <module>r      sa     	 	 1 ' ' . ' ( !   . . 0 +*& *.A\ AH\ r   