o
    Pj-5                     @   s$  d dl Z d dlZd dlZd dlmZ d dlZd dlZe jdZ	e jdp'e	Z
e jdZe
p1eZe jdZep?e jdZe jdZe jd	Zd
d Zdd Zdd Zdd ZG dd deZeedrxG dd deZe e_eZndd ZG dd deZG dd deZdd ZdS )    N)wrapsGITHUB_ACTIONSTRAVISAPPVEYORGREENLET_MANYLINUXGREENLET_SKIP_LEAKCHECKS GREENLET_SKIP_FAILING_LEAKCHECKS GREENLET_ONLY_FAILING_LEAKCHECKSc                 C   s
   d| _ | S )a  
    Ignore the given object during leakchecks.

    Can be applied to a method, in which case the method will run, but
    will not be subject to leak checks.

    If applied to a class, the entire class will be skipped during leakchecks. This
    is intended to be used for classes that are very slow and cause problems such as
    test timeouts; typically it will be used for classes that are subclasses of a base
    class and specify variants of behaviour (such as pool sizes).
    T)ignore_leakcheckfunc r   M/home/thesage/.local/lib/python3.10/site-packages/greenlet/tests/leakcheck.pyignores_leakcheckJ   s   r   c                    s    fdd}|S )a  
    Return a decorator that marks the function to be ignored during
    leakchecks (see `ignores_leakcheck`) when *condition* is true.

    *message* describes why the leakcheck is ignored. When *condition*
    is false, the function is returned unchanged.
    c                    s    r	t | } | _| S N)r   ignore_leakcheck_reasonr   	conditionmessager   r   	decoratora   s   z'ignores_leakcheck_if.<locals>.decoratorr   )r   r   r   r   r   r   ignores_leakcheck_ifY   s   r   c                 C   s   d| _ trtd| } | S )z2
    Mark that the function is known to leak.
    TzSkipping known failures)fails_leakcheckSKIP_FAILING_LEAKCHECKSunittestskipr   r   r   r   r   h   s   r   c                 C   s   t jdd dkrt| S | S )z`
    Mark the function as known to leak (fails refcount leakchecks) on Python 3.14 or less.
    N   )      )sysversion_infor   r   r   r   r    fails_leakcheck_on_py314_or_lessq   s   r    c                   @   s   e Zd ZdS )LeakCheckErrorN)__name__
__module____qualname__r   r   r   r   r!   y   s    r!   
getobjectsc                   @      e Zd Zdd Zdd ZdS )_MockGCc                 C   s
   t dS )Nr   )r   r%   selfr   r   r   get_objects      
z_MockGC.get_objectsc                 C   s
   t t|S r   )getattrgc)r)   namer   r   r   __getattr__   r+   z_MockGC.__getattr__N)r"   r#   r$   r*   r/   r   r   r   r   r'          r'   c                 C   s   | S )a  
        Decorator for a function that is known to fail when running
        strict (``sys.getobjects()``) leakchecks.

        This type of leakcheck finds all objects, even those, such as
        strings, which are not tracked by the garbage collector.
        r   r   r   r   r   fails_strict_leakcheck   s   r1   c                   @   r&   )!ignores_types_in_strict_leakcheckc                 C   s
   || _ d S r   )types)r)   r3   r   r   r   __init__   r+   z*ignores_types_in_strict_leakcheck.__init__c                 C   s   | j |_|S r   )r3   leakcheck_ignore_types)r)   r   r   r   r   __call__   s   z*ignores_types_in_strict_leakcheck.__call__N)r"   r#   r$   r4   r6   r   r   r   r   r2      r0   r2   c                   @   sT   e Zd ZdZdZdd Zdd Zdd Zd	d
 Zdd Z	dd Z
dd Zdd ZdS )_RefCountCheckerr   )uop_executorc                 C   s(   || _ || _g | _i | _d| _d| _d S )Nr   F)testcasefunctiondeltas
peak_statsignored_typesneeds_setUp)r)   r9   r:   r   r   r   r4      s   
z_RefCountChecker.__init__c                 C   s   || u rdS t |}|t | jkr3z| j|}W n ty*   | j|dk}Y nw |tur3|r3dS | j D ]	}||u rA dS q8|| jv sR|| j	v sR|j
| jv rTdS dS )NFr   T)type_include_object_p__eq__AttributeError__cmp__NotImplemented__dict__valuesr=   IGNORED_TYPESr"   IGNORED_TYPE_NAMES)r)   objkindexact_method_equalsxr   r   r   r@      s(   

z"_RefCountChecker._include_object_pc                 C   s   t jd | j| jdS )N)limitr<   filter)objgraphgrowthr<   r@   r(   r   r   r   _growth   s   
z_RefCountChecker._growthc                 C   sR   |sdS g }t dd |D }|D ]\}}}|d||||f  qd|}|S )Nz<Unable to calculate growth>c                 s   s    | ]
\}}}t |V  qd S r   )len).0r.   _r   r   r   	<genexpr>   s    z0_RefCountChecker._report_diff.<locals>.<genexpr>z%-*s%9d %+9d
)maxappendjoin)r)   rP   lineswidthr.   countdeltadiffr   r   r   _report_diff   s   
z_RefCountChecker._report_diffc                 C   s   t  }t   | jr| j  d| j_z)| j| jg|R i | W | j  | j	  d| j_d| _|r<t 
  d S d S | j  | j	  d| j_d| _|rVt 
  w w )NFT)r-   	isenableddisabler>   r9   setUpskipTearDownr:   tearDown
doCleanupsenable)r)   argskwargs
gc_enabledr   r   r   	_run_test   s*   





z_RefCountChecker._run_testc                 C   s8   dt jv rt jd   dt jv rt jd   |  S )Nurlparsezurllib.parse)r   modulesclear_cacherQ   r(   r   r   r   _growth_after  s
   

z_RefCountChecker._growth_afterc                 C   sD  | j }|sdS tjrtdtjf |dd  ddgkr$t|dv r$dS |dd  g dkr0dS t|d	krBt|d
d  dkrBdS t|dkrk|d dkrk|d |d krk|d |d krk| |}td||f t|dd  dkst|d
d  dks|d
d  ddkrd}nd}t||krtd|| |f dS )NTz"Generated uncollectable garbage %rr   )r   r   F)r   r   r      r   zrefcount increased by %r
%sr         )r;   r-   garbager!   rR   sumr_   r\   )r)   rP   r;   r^   rM   r   r   r   _check_deltas  s0     8
>z_RefCountChecker._check_deltasc                 C   s   t dD ]}t  qt| jdd}|rd| j_t| jdd| _|  }z#| 	|rF| 
|| |  }| jtdd |D  | 	|s*W n tyT   |sQ Y d S w |r_td	| jf d S )
Nr   r   FTr5   r   c                 s   s    | ]}|d  V  qdS )r   Nr   )rS   statr   r   r   rU   Q  s    z,_RefCountChecker.__call__.<locals>.<genexpr>z#Expected %s to leak but it did not.)ranger-   collectr,   r:   r9   expect_greenlet_leakr=   rQ   rx   rj   rn   r;   rX   rw   r!   )r)   rg   rh   rT   expect_failurerP   r   r   r   r6   >  s,   


z_RefCountChecker.__call__N)r"   r#   r$   rG   rH   r4   r@   rQ   r_   rj   rn   rx   r6   r   r   r   r   r7      s    
*
1r7   c                    sX   t  ddstr t  dd }|rtstd j|f tjd  S t  fdd}|S )Nr
   Fr   zIgnoring leakchecks for %s: %s)filec                    s@   t | ddrtdtrt  ddstdt|  ||S )Nr
   Fz$This class ignored during leakchecksr   z(Only running tests that fail leakchecks.)r,   r   SkipTestONLY_FAILING_LEAKCHECKSr7   )r)   rg   rh   methodr   r   wrapperc  s
   

zwrap_refcount.<locals>.wrapper)r,   SKIP_LEAKCHECKSprintr"   r   stderrr   )r   reasonr   r   r   r   wrap_refcountY  s   r   )osr   r-   	functoolsr   r   rO   environgetRUNNING_ON_GITHUB_ACTIONSRUNNING_ON_TRAVISRUNNING_ON_APPVEYORRUNNING_ON_CIRUNNING_ON_MANYLINUXr   r   r   r   r   r   r    AssertionErrorr!   hasattrobjectr'   r1   r2   r7   r   r   r   r   r   <module>   s8   !	

 A