ó
    F\hq  ã                   óò   • S SK r S SKrS SKrS SKrS SKrS SKrS SKrS SKJr  S r	S r
S r\R                  SS j5       rSS jr\R                  SS j5       r " S	 S
5      rS\4S jr\" 5       rSS.S jrg)é    N)Úsupportc                  ó^   • [         R                  " 5       [        [        R                  5      4$ ©N)Ú_threadÚ_countÚlenÚ	threadingÚ	_dangling© ó    Ú4/usr/lib/python3.13/test/support/threading_helper.pyÚthreading_setupr      s   € Ü�>Š>ÓœS¤×!4Ñ!4Ó5Ð5Ð5r   c                  ól  • U u  pSn[         R                  " USS9 H8  n[        [        R                  5      n[
        R                  " 5       nXa::  d  M8    g    S[         l        [         R                  " SUS SU SU S	W S[        W5       3
5        U H  n[         R                  " S
U< 35        M     g )Ng      ð?F©ÚerrorTz2threading_cleanup() failed to clean up threads in ú.1fz  seconds
  before: thread count=z, dangling=z
  after: thread count=zDangling thread: )
r   Úsleeping_retryÚlistr	   r
   r   r   Úenvironment_alteredÚprint_warningr   )Úoriginal_valuesÚ
orig_countÚorig_ndanglingÚtimeoutÚ_Údangling_threadsÚcountÚthreads           r   Úthreading_cleanupr      sÄ   € Ø!0Ñ€Jà€GÜ×#Ò# G°5Ô9ˆô  ¤	× 3Ñ 3Ó4ÐÜ—’Ó ˆàÕÙñ :ð #'„GÔÜ×ÒðØ�cˆ]ð "Ø", ¨[¸Ð8Hð I!Ø!&  {´3Ð7GÓ3HÐ2Ið	KôLó
 #ˆÜ×ÒÐ 1°&±Ð<Ö=ò #r   c                 óF   ^ • [         R                  " T 5      U 4S j5       nU$ )z{Use this function when threads are being used.  This will
ensure that the threads are cleaned up even when the test fails.
c                  óN   >• [        5       n T" U 6 [        U6   $ ! [        U6   f = fr   )r   r   )ÚargsÚkeyÚfuncs     €r   Ú	decoratorÚreap_threads.<locals>.decorator>   s)   ø€ äÓˆð	$Ù˜�;ä˜sÒ#øÔ˜sÒ#ús   � š
$)Ú	functoolsÚwraps)r$   r%   s   ` r   Úreap_threadsr)   :   s(   ø€ ô ‡_‚_�TÓô$ó ð$ð Ðr   c              #   óÌ  #   • U c  [         R                  n [        R                  " 5       n Sv •  [        R
                  " 5       n[         R                  " U SS9 H4  n[         R                  " 5         [        R                  " 5       nXA::  d  M4    g   [        R
                  " 5       U-
  nSWU-
   SUS SU SU S	3	n[        U5      e! [        R
                  " 5       n[         R                  " U SS9 H4  n[         R                  " 5         [        R                  " 5       nXA::  d  M4    f    [        R
                  " 5       U-
  nSWU-
   SUS SU SU S	3	n[        U5      e= f7f)
a   
bpo-31234: Context manager to wait until all threads created in the with
statement exit.

Use _thread.count() to check if threads exited. Indirectly, wait until
threads exit the internal t_bootstrap() C function of the _thread module.

threading_setup() and threading_cleanup() are designed to emit a warning
if a test leaves running threads in the background. This context manager
is designed to cleanup threads started by the _thread.start_new_thread()
which doesn't allow to wait for thread exit, whereas thread.Thread has a
join() method.
NFr   z!wait_threads() failed to cleanup z threads after r   z seconds (count: z, old count: Ú))	r   ÚSHORT_TIMEOUTr   r   ÚtimeÚ	monotonicr   Ú
gc_collectÚAssertionError)r   Ú	old_countÚ
start_timer   r   ÚdtÚmsgs          r   Úwait_threads_exitr5   H   s\  é € ð �Ü×'Ñ'ˆÜ—’Ó €Ið&Ûä—^’^Ó%ˆ
Ü×'Ò'¨°uÔ=ˆAÜ×ÒÔ Ü—N’NÓ$ˆEØÕ!Ùñ	 >ô —’Ó! JÑ.ˆBØ6°u¸yÑ7HÐ6Ið J$Ø$& s 8ð ,Ø#˜W M°)°¸Að?ˆCô ! Ó%Ð%øô —^’^Ó%ˆ
Ü×'Ò'¨°uÔ=ˆAÜ×ÒÔ Ü—N’NÓ$ˆEØÕ!Ùñ	 >ô —’Ó! JÑ.ˆBØ6°u¸yÑ7HÐ6Ið J$Ø$& s 8ð ,Ø#˜W M°)°¸Að?ˆCô ! Ó%Ð%üs)   ‚)E$¬C °AE$Â:E$ÃAE!Ä':E!Å!E$c                 óš   • Uc  [         R                  nU R                  U5        U R                  5       (       a  SUS S3n[	        U5      eg)z[Join a thread. Raise an AssertionError if the thread is still alive
after timeout seconds.
Nzfailed to join the thread in r   z seconds)r   r,   ÚjoinÚis_aliver0   )r   r   r4   s      r   Újoin_threadr9   k   sM   € ð �Ü×'Ñ'ˆØ
‡K�K�ÔØ‡�×ÑØ-¨g°c¨]¸(ÐCˆÜ˜SÓ!Ð!ð r   c              #   ó.  #   •  SS K n[        U 5      n / n  U  H$  nUR                  5         UR	                  U5        M&     S v •   U(       a  U" 5         [        R                  " 5       n[        SS5       H£  nUS-  nU H4  nUR                  [        U[        R                  " 5       -
  S5      5        M6     U Vs/ s H  oDR                  5       (       d  M  UPM     nnU(       d    O4[
        R                  (       d  MŠ  [        S[        U5      U4-  5        M¥     U Vs/ s H  oDR                  5       (       d  M  UPM     nnU(       a9  Ub  UR                  [         R"                  5        [%        S[        U5      -  5      eg ! [         a    S n GNŒf = f!   [
        R                  (       a"  [        S[        U 5      [        U5      4-  5        e = fs  snf s  snf ! U Vs/ s H  oDR                  5       (       d  M  UPM     Os  snf nnU(       a9  Ub  UR                  [         R"                  5        [%        S[        U5      -  5      ef = f!  U(       a  U" 5         [        R                  " 5       n[        SS5       H©  nUS-  nU H4  nUR                  [        U[        R                  " 5       -
  S5      5        M6     U Vs/ s H  oDR                  5       (       d  M  UPM     Os  snf nnU(       d    O4[
        R                  (       d  M�  [        S[        U5      U4-  5        M«     U Vs/ s H  oDR                  5       (       d  M  UPM     Os  snf nnU(       a9  Ub  UR                  [         R"                  5        [%        S[        U5      -  5      ef ! U Vs/ s H  oDR                  5       (       d  M  UPM     Os  snf nnU(       a9  Ub  UR                  [         R"                  5        [%        S[        U5      -  5      ef = f= f7f)	Nr   z/Can't start %d threads, only %d threads startedé   é   é<   g{®Gáz„?z7Unable to join %d threads during a period of %d minuteszUnable to join %d threads)ÚfaulthandlerÚImportErrorr   ÚstartÚappendr   ÚverboseÚprintr   r-   r.   Úranger7   Úmaxr8   Údump_tracebackÚsysÚstdoutr0   )ÚthreadsÚunlockr>   ÚstartedÚtÚendtimer   s          r   Ústart_threadsrN   w   s6  é € ðÛô �7‹m€GØ€GðQð	Û�Ø—‘”	Ø—‘˜qÖ!ñ ó 	ð	QÞÙ”Ü—n’nÓ&ˆGÜ   Bž<�Ø˜2‘�Û �AØ—F‘Fœ3˜w¬¯ªÓ)9Ñ9¸4Ó@ÖAñ !á&-Ó>¢g ·±·Ÿ1¡g�Ð>ÞÙÜ—?—?‘?Üð 'Ü*-¨g«,¸Ð)@ñAö Bñ (ñ #*Ó:¢'˜Q¯Z©Z¯\—q¡'ˆGÐ:ÞØÑ+Ø ×/Ñ/´·
±
Ô;Ü$Ð%@Ä3ÀwÃ<Ñ%OÓPÐPð øôC ó à‹ðûð	Ü��ÜÐGÜ˜7“|¤S¨£\Ð2ñ3ô 4àüò ?ùò ;ø¡'Ó:¢'˜Q¯Z©Z¯\—q¢'ùÒ:ˆGÐ:ÞØÑ+Ø ×/Ñ/´·
±
Ô;Ü$Ð%@Ä3ÀwÃ<Ñ%OÓPÐPð ûð!	QÞÙ”Ü—n’nÓ&ˆGÜ   Bž<�Ø˜2‘�Û �AØ—F‘Fœ3˜w¬¯ªÓ)9Ñ9¸4Ó@ÖAñ !á&-Ó>¢g ·±·Ÿ1¢gùÒ>�Ð>ÞÙÜ—?—?‘?Üð 'Ü*-¨g«,¸Ð)@ñAö Bñ (ñ #*Ó:¢'˜Q¯Z©Z¯\—q¢'ùÒ:ˆGÐ:ÞØÑ+Ø ×/Ñ/´·
±
Ô;Ü$Ð%@Ä3ÀwÃ<Ñ%OÓPÐPð øñ #*Ó:¢'˜Q¯Z©Z¯\—q¢'ùÒ:ˆGÐ:ÞØÑ+Ø ×/Ñ/´·
±
Ô;Ü$Ð%@Ä3ÀwÃ<Ñ%OÓPÐPð ÿs  ‚P„F ˆP—*F ÁI ÁA5G Â;GÃGÃG Ã?G ÄPÄ GÄ<GÅAPÆFÆPÆFÆPÆ:GÇI ÇG ÇPÇIÇ$HÈ HÈA	IÉPÉPÉA5NË	K,
Ë%K,
Ë+$NÌNÌ0PÌ4MÍMÍA	PÎPÎ$OÏ OÏA	PÐPÐPc                   ó0   • \ rS rSrSrS rS rS rS rSr	g)	Úcatch_threading_exceptioné¢   a¼  
Context manager catching threading.Thread exception using
threading.excepthook.

Attributes set when an exception is caught:

* exc_type
* exc_value
* exc_traceback
* thread

See threading.excepthook() documentation for these attributes.

These attributes are deleted at the context manager exit.

Usage:

    with threading_helper.catch_threading_exception() as cm:
        # code spawning a thread which raises an exception
        ...

        # check the thread exception, use cm attributes:
        # exc_type, exc_value, exc_traceback, thread
        ...

    # exc_type, exc_value, exc_traceback, thread attributes of cm no longer
    # exists at this point
    # (to avoid reference cycles)
c                 óJ   • S U l         S U l        S U l        S U l        S U l        g r   )Úexc_typeÚ	exc_valueÚexc_tracebackr   Ú	_old_hook©Úselfs    r   Ú__init__Ú"catch_threading_exception.__init__Á   s&   € ØˆŒØˆŒØ!ˆÔØˆŒØˆ�r   c                 óŒ   • UR                   U l         UR                  U l        UR                  U l        UR                  U l        g r   )rS   rT   rU   r   )rX   r"   s     r   Ú_hookÚcatch_threading_exception._hookÈ   s1   € ØŸ™ˆŒØŸ™ˆŒØ!×/Ñ/ˆÔØ—k‘kˆ�r   c                 óZ   • [         R                  U l        U R                  [         l        U $ r   )r	   Ú
excepthookrV   r\   rW   s    r   Ú	__enter__Ú#catch_threading_exception.__enter__Î   s    € Ü"×-Ñ-ˆŒØ#Ÿz™zŒ	ÔØˆr   c                 ó>   • U R                   [        l        U ?U ?U ?U ?g r   )rV   r	   r_   rS   rT   rU   r   )rX   Úexc_infos     r   Ú__exit__Ú"catch_threading_exception.__exit__Ó   s#   € Ø#Ÿ~™~Œ	ÔØˆMØˆNØÐØ‰Kr   )rV   rU   rS   rT   r   N)
Ú__name__Ú
__module__Ú__qualname__Ú__firstlineno__Ú__doc__rY   r\   r`   rd   Ú__static_attributes__r   r   r   rP   rP   ¢   s   † ñò<ò"òõ
r   rP   Úreturnc                  óŠ   • [         R                  S:X  a  [         R                  R                  $ [         R                  S:X  a  gg)a]  Detect whether Python can start new threads.

Some WebAssembly platforms do not provide a working pthread
implementation. Thread support is stubbed and any attempt
to create a new thread fails.

- wasm32-wasi does not have threading.
- wasm32-emscripten can be compiled with or without pthread
  support (-s USE_PTHREADS / __EMSCRIPTEN_PTHREADS__).
Ú
emscriptenÚwasiFT)rG   ÚplatformÚ_emscripten_infoÚpthreadsr   r   r   Ú_can_start_threadrs   Û   s6   € ô ‡|�|�|Ó#Ü×#Ñ#×,Ñ,Ð,Ü	�‰˜Ó	Øð r   F)Úmodulec                 óŽ   • SnU (       a"  [         (       d  [        R                  " U5      eg[        R                  " [         U5      $ )z~Skip tests or modules that require working threading.

Can be used as a function/class decorator or to skip an entire module.
zrequires threading supportN)Úcan_start_threadÚunittestÚSkipTestÚ
skipUnless)rt   r4   s     r   Úrequires_working_threadingrz   ð   s>   € ð
 '€CÞßÒÜ×#Ò# CÓ(Ð(ð  ô ×"Ò"Ô#3°SÓ9Ð9r   r   )r   Ú
contextlibr'   rG   r	   r-   rw   Útestr   r   r   r)   Úcontextmanagerr5   r9   rN   rP   Úboolrs   rv   rz   r   r   r   Ú<module>r      s“   ðÛ Û Û Û 
Û Û Û å ò6ò>ò<ð ×Ñó&ó ð&ôD	"ð ×Ñó'Qó ð'Q÷T6ñ 6ðr˜4ô ñ& %Ó&Ð à).ö 
:r   