
    Yh                     ~    S r SSKJrJrJr  SSKr " S S\R                  5      r\S:X  a  \R                  " 5         gg)a  
Tests for greenlets interacting with the CPython trash can API.

The CPython trash can API is not designed to be re-entered from a
single thread. But this can happen using greenlets, if something
during the object deallocation process switches greenlets, and this second
greenlet then causes the trash can to get entered again. Here, we do this
very explicitly, but in other cases (like gevent) it could be arbitrarily more
complicated: for example, a weakref callback might try to acquire a lock that's
already held by another greenlet; that would allow a greenlet switch to occur.

See https://github.com/gevent/gevent/issues/1909

This test is fragile and relies on details of the CPython
implementation (like most of the rest of this package):

    - We enter the trashcan and deferred deallocation after
      ``_PyTrash_UNWIND_LEVEL`` calls. This constant, defined in
      CPython's object.c, is generally 50. That's basically how many objects are required to
      get us into the deferred deallocation situation.

    - The test fails by hitting an ``assert()`` in object.c; if the
      build didn't enable assert, then we don't catch this.

    - If the test fails in that way, the interpreter crashes.
    )print_functionabsolute_importdivisionNc                        \ rS rSrS rS rSrg)TestTrashCanReEnter!   c                      SSK Jn  [        S5       H  nU R                  5         M     g ! [         a-    SS KnUR                  S S S:  d   eU R                  S5         NYf = f)Nr   get_tstate_trash_delete_nesting   )      z1get_tstate_trash_delete_nesting is not available.
   )greenlet._greenletr   ImportErrorsysversion_infoskipTestrangecheck_it)selfr   r   _s       T/var/www/html/env/lib/python3.13/site-packages/greenlet/tests/test_greenlet_trash.pytest_itTestTrashCanReEnter.test_it#   sb    	OJ rAMMO   	O##BQ'7222MMMN		Os   + 4A"!A"c                 2  ^^^^^^	^
 SS K mSSKJn  TR                  5       m	U" 5       S:X  d   eSmSm " UUUUU	4S jS5      mU
4S jmUU4S jm
T
" 5       nU R	                  TR
                  T5        U R	                  TR                  S5        AU R	                  SU" 5       5        S Tl        U R	                  SU" 5       5        U R                  TR                  S5        U R                  TR                  T	5        U R                  TR                  5        U R	                  TR                  TR                  5        U R	                  TR
                  TR                  5        U R	                  TR
                  TS	-  5        SS KnUR!                  5         g )
Nr   r
   2   i  c                   R   > \ rS rSrSrSrSrSrSrSr	Sr
U 4S jrU UUUU4S jrSrg)	-TestTrashCanReEnter.check_it.<locals>.DeallocB   a  
An object with a ``__del__`` method. When it starts getting deallocated
from a deferred trash can run, it switches greenlets, allocates more objects
which then also go in the trash can. If we don't save state appropriately,
nesting gets out of order and we can crash the interpreter.
FNr   c                 <   > Xl         T=R                  S-  sl        g)z
:param sequence_number: The ordinal of this object during
   one particular creation run. This is used to detect (guess, really)
   when we have entered the trash can's deferred deallocation.
   N)iCREATED)r   sequence_numberDeallocs     r   __init__6TestTrashCanReEnter.check_it.<locals>.Dealloc.__init__`   s     )1$    c                 &  > U R                   T:X  aX  U R                  (       dG  TR                  5       Tl        TR                  T5      =nTl        UR                  5       nUS:X  d   eAO<U R                   S:X  a,  TR                  5       TLa  STl         TR                  S5        T=R                  S-  sl	        TR                  5       TLa  T=R                  S-  sl
        g g ! TR                   a  n[        U5      Tl        A S nANeS nAff = f)N*   (   Tr"   )r#   SPAWNED
getcurrentgreenletBG_GLETswitchBG_RANGreenletExittype	DESTROYEDDESTROYED_BG)	r   otherxexr&   TRASH_UNWIND_LEVELbackground_greenletr/   mains	       r   __del__5TestTrashCanReEnter.check_it.<locals>.Dealloc.__del__i   s    66//&.&9&9&;GO.6.?.?@S.TTEGOA7N7 VVr\h&9&9&;4&G%)GNB !!Q&!&&(4((A-( 5 $00  *.bs   C% %D5DD)r#   )__name__
__module____qualname____firstlineno____doc__r-   r2   r0   r$   r5   r6   r'   r=   __static_attributes__)r&   r:   r;   r/   r<   s   r   r&   r   B   s?     G FG G I L%. .r)   r&   c                     > T" 5       n A g )N )t	make_somes    r   r;   9TestTrashCanReEnter.check_it.<locals>.background_greenlet   s    
 Ar)   c                  N   > Sn TnU(       a  T" U5      U 4n US-  nU(       a  M  U $ )NrF   r"   rF   )rG   r#   r&   OBJECTS_PER_CONTAINERs     r   rH   /TestTrashCanReEnter.check_it.<locals>.make_some   s6    A%A QZOQ	 !
 Hr)   r   )r/   r   r   r.   assertEqualr$   r5   r0   assertGreaterr6   assertIsr-   
assertTruer2   r3   gccollect)r   r   somerQ   r&   rK   r:   r;   r/   r<   rH   s       @@@@@@@r   r   TestTrashCanReEnter.check_it2   sW   F""$.0A555   !$C	. C	. C	.L		 {*?@**A.  	;=> ;=> 	7//3 	goot,')>)>?'*;*;=*?!*CD


r)   rF   N)r?   r@   rA   rB   r   r   rD   rF   r)   r   r   r   !   s    Er)   r   __main__)
rC   
__future__r   r   r   unittestTestCaser   r?   r<   rF   r)   r   <module>rY      sC   4 A @ V(++ Vr zMMO r)   