
    (Gj                        U d Z ddlmZ ddlZddlZddlZddlZddlmZm	Z	 dgZ
 ej                    Zi Zded<    G d d	          ZddZej        dd            ZdS )u!  Thread-scoped stdout/stderr silencing for background worker threads.

``contextlib.redirect_stdout``/``redirect_stderr`` reassign the *process-global*
``sys.stdout``/``sys.stderr``.  When a daemon worker thread (e.g. the background
memory/skill review) wraps its whole body in those context managers, every other
thread in the process — including a gateway's asyncio event-loop thread driving a
Telegram long-poll — sees ``sys.stdout``/``sys.stderr`` pointing at ``devnull``
for the full duration.  Any bare ``print`` / ``sys.stderr.write`` from those other
threads is silently lost during that window (see issue #55769 / #55925).

This module installs a thin proxy as ``sys.stdout``/``sys.stderr`` that routes
writes per-thread: threads registered as "silenced" go to a sink; every other
thread passes through to the *original* stream.  The proxy is installed once,
idempotently, and is never uninstalled (uninstalling would race other threads
mid-write), so the only observable effect for unregistered threads is one extra
attribute lookup per write.
    )annotationsN)IteratorTextIOthread_scoped_silencez!dict[str, '_ThreadRoutingStream']
_installedc                  X    e Zd ZdZddZddZddZddZd Zd Z	d Z
ddZd Zd ZdS )_ThreadRoutingStreama  A ``sys.stdout``/``sys.stderr`` stand-in that routes writes per-thread.

    Threads whose ident is in ``_silenced`` write to ``_sink``; all other
    threads write to ``_passthrough`` (the original stream captured at install
    time).  Attribute access for anything other than the methods we override
    is delegated to the *current* target so things like ``.encoding`` /
    ``.fileno()`` behave like the underlying stream for the calling thread.
    passthroughr   sinkreturnNonec                `    || _         || _        i | _        t          j                    | _        d S N)_passthrough_sink	_silenced	threadingLock_lock)selfr
   r   s      @/home/rurouni/.hermes/hermes-agent/agent/thread_scoped_output.py__init__z_ThreadRoutingStream.__init__-   s-    '
 *,^%%


    c                ~    | j                             t          j                    d          dk    r| j        S | j        S Nr   )r   getr   	get_identr   r   r   s    r   _targetz_ThreadRoutingStream._target6   s9    >i133Q77!;;:  r   identintc                    | j         5  | j                            |d          dz   | j        |<   d d d            d S # 1 swxY w Y   d S Nr      )r   r   r   )r   r    s     r   silencez_ThreadRoutingStream.silence<   s    Z 	E 	E$(N$6$6ua$@$@1$DDN5!	E 	E 	E 	E 	E 	E 	E 	E 	E 	E 	E 	E 	E 	E 	E 	E 	E 	Es   '<A A c                    | j         5  | j                            |d          dz
  }|dk    r|| j        |<   n| j                            |d            d d d            d S # 1 swxY w Y   d S r#   )r   r   r   pop)r   r    depths      r   	unsilencez_ThreadRoutingStream.unsilence@   s    Z 	0 	0N&&ua0014Eqyy(-u%%""5$///	0 	0 	0 	0 	0 	0 	0 	0 	0 	0 	0 	0 	0 	0 	0 	0 	0 	0s   AA  A$'A$c                    	 |                                                      |          S # t          $ r) t          |t                    rt          |          ndcY S w xY wr   )r   write	Exception
isinstancestrlen)r   datas     r   r+   z_ThreadRoutingStream.writeI   sc    	=<<>>''--- 	= 	= 	= *4 5 5<3t9991<<<	=s   &) 0AAc                r    	 |                                                                  S # t          $ r Y d S w xY wr   )r   flushr,   r   s    r   r2   z_ThreadRoutingStream.flushO   sC    	<<>>''))) 	 	 	44	s   %( 
66c                x    |                                  }	 |                    |          S # t          $ r Y d S w xY wr   )r   
writelinesr,   )r   linestargets      r   r4   z_ThreadRoutingStream.writelinesU   sJ    	$$U+++ 	 	 	44	s   + 
99boolc                    	 t          |                                                                           S # t          $ r Y dS w xY w)NF)r7   r   isattyr,   r   s    r   r9   z_ThreadRoutingStream.isatty\   sK    	--//000 	 	 	55	s   25 
AAc                N    |                                                                  S r   )r   filenor   s    r   r;   z_ThreadRoutingStream.filenob   s    ||~~$$&&&r   c                F    t          |                                 |          S r   )getattrr   )r   names     r   __getattr__z _ThreadRoutingStream.__getattr__e   s     t||~~t,,,r   N)r
   r   r   r   r   r   )r   r   )r    r!   r   r   )r   r7   )__name__
__module____qualname____doc__r   r   r%   r)   r+   r2   r4   r9   r;   r?    r   r   r	   r	   #   s         & & & &! ! ! !E E E E0 0 0 0= = =       ' ' '- - - - -r   r	   attrr.   r   r   r   '_ThreadRoutingStream'c                <   t           5  t                              |           }t          t          | d          }|||u r|cddd           S ||n|}t          ||          }t          t          | |           |t          | <   |cddd           S # 1 swxY w Y   dS )zGInstall (idempotently) a routing proxy as ``sys.<attr>`` and return it.N)_install_lockr   r   r=   sysr	   setattr)rE   r   proxycurrentr
   s        r   _ensure_installedrM   k   s   	  t$$#tT**E!1!1	        ")!4gg$$[$77T5!!! 
4                 s   8B7BBBIterator[None]c               #  N  K   t          t          j        dd          } t          j                    }t          d|           }t          d|           }|                    |           |                    |           	 dV  |                    |           |                    |           	 |                                  dS # t          $ r Y dS w xY w# |                    |           |                    |           	 |                                  w # t          $ r Y w w xY wxY w)a-  Silence ``stdout``/``stderr`` for the *current thread only*.

    Other threads keep writing to the real streams.  Use this around a worker
    thread's body instead of ``contextlib.redirect_stdout(devnull)`` when the
    process is multi-threaded and another thread must keep its console output.
    wzutf-8)encodingstdoutstderrN)
openosdevnullr   r   rM   r%   r)   closer,   )r   r    	out_proxy	err_proxys       r   r   r   }   sB      
C'222D!!E!(D11I!(D11IeeE"""E"""	JJLLLLL 	 	 	DD		 	E"""E"""	JJLLLL 	 	 	D	sB   =C ,C 
CC+D$?DD$
D!D$ D!!D$)rE   r.   r   r   r   rF   )r   rN   )rC   
__future__r   
contextlibrU   rI   r   typingr   r   __all__r   rH   r   __annotations__r	   rM   contextmanagerr   rD   r   r   <module>r`      s    $ # " " " " "     				 



     # # # # # # # #"
#	   13
 2 2 2 2E- E- E- E- E- E- E- E-P   $      r   