
    `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y)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                  V    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y)_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.
    c                `    || _         || _        i | _        t        j                         | _        y N)_passthrough_sink	_silenced	threadingLock_lock)selfpassthroughsinks      M/root/.hermes/venv/lib/python3.12/site-packages/agent/thread_scoped_output.py__init__z_ThreadRoutingStream.__init__-   s(    '
 *,^^%
    c                    | j                   j                  t        j                         d      dkD  r| j                  S | j
                  S Nr   )r   getr   	get_identr   r   r   s    r   _targetz_ThreadRoutingStream._target6   s:    >>i113Q7!;::   r   c                    | j                   5  | j                  j                  |d      dz   | j                  |<   d d d        y # 1 sw Y   y xY wNr      )r   r   r   )r   idents     r   silencez_ThreadRoutingStream.silence<   sF    ZZ 	E$(NN$6$6ua$@1$DDNN5!	E 	E 	Es   -AAc                    | j                   5  | j                  j                  |d      dz
  }|dkD  r|| j                  |<   n| j                  j                  |d        d d d        y # 1 sw Y   y xY wr   )r   r   r   pop)r   r!   depths      r   	unsilencez_ThreadRoutingStream.unsilence@   sb    ZZ 	0NN&&ua014Eqy(-u%""5$/	0 	0 	0s   AA''A0c                    	 | j                         j                  |      S # t        $ r" t        |t              rt        |      cY S dcY S w xY wr   )r   write	Exception
isinstancestrlen)r   datas     r   r(   z_ThreadRoutingStream.writeI   sE    	=<<>''-- 	= *4 53t9<1<	=s   ! $AAAc                ^    	 | j                         j                         S # t        $ r Y y w xY wr   )r   flushr)   r   s    r   r/   z_ThreadRoutingStream.flushO   s.    	<<>'')) 		s     	,,c                d    | j                         }	 |j                  |      S # t        $ r Y y w xY wr   )r   
writelinesr)   )r   linestargets      r   r1   z_ThreadRoutingStream.writelinesU   s5    	$$U++ 		s   # 	//c                p    	 t        | j                         j                               S # t        $ r Y yw xY w)NF)boolr   isattyr)   r   s    r   r6   z_ThreadRoutingStream.isatty\   s3    	--/00 		s   &) 	55c                >    | j                         j                         S r   )r   filenor   s    r   r8   z_ThreadRoutingStream.filenob   s    ||~$$&&r   c                6    t        | j                         |      S r   )getattrr   )r   names     r   __getattr__z _ThreadRoutingStream.__getattr__e   s     t||~t,,r   N)r   r   r   r   returnNone)r=   r   )r!   intr=   r>   )r=   r5   )__name__
__module____qualname____doc__r   r   r"   r&   r(   r/   r1   r6   r8   r<    r   r   r	   r	   #   s:    &!E0='-r   r	   c                   t         5  t        j                  |       }t        t        | d      }|||u r|cddd       S ||n|}t        ||      }t        t        | |       |t        | <   |cddd       S # 1 sw Y   yxY w)zGInstall (idempotently) a routing proxy as ``sys.<attr>`` and return it.N)_install_lockr   r   r:   sysr	   setattr)attrr   proxycurrentr   s        r   _ensure_installedrL   k   s    	 t$#tT*E!1	  ")!4g$$[$7T5! 
4  s   .A6-A66A?c               #    K   t        t        j                  dd      } t        j                         }t        d|       }t        d|       }|j                  |       |j                  |       	 d |j                  |       |j                  |       	 | j                          y# t        $ r Y yw xY w# |j                  |       |j                  |       	 | j                          w # t        $ r Y w w xY wxY w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   rL   r"   r&   closer)   )r   r!   	out_proxy	err_proxys       r   r   r   }   s      

C'2D!E!(D1I!(D1IeeE"E"	JJL 			 	E"E"	JJL 		sf   A+C<.B5 2"C<B& %C<&	B2/C<1B22C<5#C9C*)C9*	C63C95C66C99C<)rI   r+   r   r   r=   z'_ThreadRoutingStream')r=   zIterator[None])rC   
__future__r   
contextlibrS   rG   r   typingr   r   __all__r   rF   r   __annotations__r	   rL   contextmanagerr   rD   r   r   <module>r^      sm   $ #  	 
  #"
#	  13
- 2E- E-P$  r   