a
    *ñ»j½3  ã                   @  s¼  d Z ddlmZ ddlmZ ddlmZ ddlmZ ddlmZ ddl	Z	ddl
mZ dd	lmZ dd
lmZ ddlmZ ddlmZ ddlmZ er ddlmZ ddlZddlmZ ddlmZ ddlmZ ddlmZ edƒZeddœdd„ƒZeddœdddœdd„ƒZedd d dd!œd"d„ƒZd2d#d d d$d!œd%d„Zed3ddœd&dd'd(œd)d*„ƒZed&dd d dd+œd,d*„ƒZe fddœd&d dd d-d.œd/d*„ZG d0d„ dej!ƒZ"eG d1d'„ d'e"ƒƒZ#dS )4z/Record warnings during test function execution.é    )Úannotations)ÚCallable)Ú	Generator)ÚIterator©ÚpformatN)ÚTracebackType)ÚAny)Úfinal)Úoverload)ÚTYPE_CHECKING)ÚTypeVar)ÚSelf)Úcheck_ispytest)Úfixture)ÚExit)ÚfailÚTzGenerator[WarningsRecorder]©Úreturnc                  c  sB   t dd�} | �  t d¡ | V  W d  ƒ n1 s40    Y  dS )z¥Return a :class:`WarningsRecorder` instance that records all warnings emitted by test functions.

    See :ref:`warnings` for information on warning categories.
    T©Ú	_ispytestÚdefaultN)ÚWarningsRecorderÚwarningsÚsimplefilter)Zwrec© r   ú5E:\soccer\ml_env\Lib\site-packages\_pytest/recwarn.pyÚrecwarn!   s    

r   .©Úmatchústr | re.Pattern[str] | Noner   )r    r   c                 C  s   d S ©Nr   r   r   r   r   Údeprecated_call-   s    r#   zCallable[..., T]r	   )ÚfuncÚargsÚkwargsr   c                 O  s   d S r"   r   )r$   r%   r&   r   r   r   r#   3   s    zCallable[..., Any] | NonezWarningsRecorder | Anyc                 O  s4   d}| dur| g|¢R }t tttfg|¢R i |¤ŽS )a¥  Assert that code produces a ``DeprecationWarning`` or ``PendingDeprecationWarning`` or ``FutureWarning``.

    This function can be used as a context manager::

        >>> import warnings
        >>> def api_call_v2():
        ...     warnings.warn('use v3 of this api', DeprecationWarning)
        ...     return 200

        >>> import pytest
        >>> with pytest.deprecated_call():
        ...    assert api_call_v2() == 200

    It can also be used by passing a function and ``*args`` and ``**kwargs``,
    in which case it will ensure calling ``func(*args, **kwargs)`` produces one of
    the warnings types above. The return value is the return value of the function.

    In the context manager form you may use the keyword argument ``match`` to assert
    that the warning matches a text or regex.

    The context manager produces a list of :class:`warnings.WarningMessage` objects,
    one for each warning raised.
    TN)ÚwarnsÚDeprecationWarningÚPendingDeprecationWarningÚFutureWarning)r$   r%   r&   Ú__tracebackhide__r   r   r   r#   7   s    ÿÿÿú)type[Warning] | tuple[type[Warning], ...]ÚWarningsChecker)Úexpected_warningr    r   c                C  s   d S r"   r   )r.   r    r   r   r   r'   Y   s    r'   )r.   r$   r%   r&   r   c                 O  s   d S r"   r   )r.   r$   r%   r&   r   r   r   r'   a   s    zWarningsChecker | Any)r.   r%   r    r&   r   c                O  s¦   d}|s8|r*d  t|ƒ¡}td|› d�ƒ‚t| |dd�S |d }t|ƒs`t|›dt|ƒ› d�ƒ‚t| dd	��& ||d
d… i |¤ŽW  d  ƒ S 1 s˜0    Y  dS )a  Assert that code raises a particular class of warning.

    Specifically, the parameter ``expected_warning`` can be a warning class or tuple
    of warning classes, and the code inside the ``with`` block must issue at least one
    warning of that class or classes.

    This helper produces a list of :class:`warnings.WarningMessage` objects, one for
    each warning emitted (regardless of whether it is an ``expected_warning`` or not).
    Since pytest 8.0, unmatched warnings are also re-emitted when the context closes.

    This function can be used as a context manager::

        >>> import pytest
        >>> with pytest.warns(RuntimeWarning):
        ...    warnings.warn("my warning", RuntimeWarning)

    In the context manager form you may use the keyword argument ``match`` to assert
    that the warning matches a text or regex::

        >>> with pytest.warns(UserWarning, match='must be 0 or None'):
        ...     warnings.warn("value must be 0 or None", UserWarning)

        >>> with pytest.warns(UserWarning, match=r'must be \d+$'):
        ...     warnings.warn("value must be 42", UserWarning)

        >>> with pytest.warns(UserWarning):  # catch re-emitted warning
        ...     with pytest.warns(UserWarning, match=r'must be \d+$'):
        ...         warnings.warn("this is not here", UserWarning)
        Traceback (most recent call last):
          ...
        Failed: DID NOT WARN. No warnings of type ...UserWarning... were emitted...

    **Using with** ``pytest.mark.parametrize``

    When using :ref:`pytest.mark.parametrize ref` it is possible to parametrize tests
    such that some runs raise a warning and others do not.

    This could be achieved in the same way as with exceptions, see
    :ref:`parametrizing_conditional_raising` for an example.

    Tz, z5Unexpected keyword arguments passed to pytest.warns: z"
Use context-manager form instead?)Ú
match_exprr   r   z object (type: z) must be callabler   é   N)ÚjoinÚsortedÚ	TypeErrorr-   ÚcallableÚtype)r.   r    r%   r&   r+   Úargnamesr$   r   r   r   r'   j   s    /
ÿc                      s¸   e Zd ZdZddœdddœ‡ fdd„Zed	d
œdd„ƒZdddœdd„Zdd
œdd„Zdd
œdd„Z	e
fdddœdd„Zdd
œdd„Zdd
œ‡ fdd„Zd d!d"dd#œ‡ fd$d%„Z‡  ZS )&r   aF  A context manager to record raised warnings.

    Each recorded warning is an instance of :class:`warnings.WarningMessage`.

    Adapted from `warnings.catch_warnings`.

    .. note::
        ``DeprecationWarning`` and ``PendingDeprecationWarning`` are treated
        differently; see :ref:`ensuring_function_triggers`.

    Fr   ÚboolÚNone)r   r   c                  s&   t |ƒ tƒ jdd� d| _g | _d S )NT)ÚrecordF)r   ÚsuperÚ__init__Ú_enteredÚ_list)Úselfr   ©Ú	__class__r   r   r;   ·   s    zWarningsRecorder.__init__zlist[warnings.WarningMessage]r   c                 C  s   | j S )zThe list of recorded warnings.©r=   ©r>   r   r   r   Úlist½   s    zWarningsRecorder.listÚintúwarnings.WarningMessage)Úir   c                 C  s
   | j | S )z Get a recorded warning by index.rA   )r>   rF   r   r   r   Ú__getitem__Â   s    zWarningsRecorder.__getitem__z!Iterator[warnings.WarningMessage]c                 C  s
   t | jƒS )z&Iterate through the recorded warnings.)Úiterr=   rB   r   r   r   Ú__iter__Æ   s    zWarningsRecorder.__iter__c                 C  s
   t | jƒS )z The number of recorded warnings.)Úlenr=   rB   r   r   r   Ú__len__Ê   s    zWarningsRecorder.__len__ztype[Warning])Úclsr   c                 C  sˆ   d}t | jƒD ]N\}}|j|kr0| j |¡  S t|j|ƒr|du sXt|j| j| jƒs|}q|durr| j |¡S d}t|›d�ƒ‚dS )zÁPop the first recorded warning which is an instance of ``cls``,
        but not an instance of a child class of any other match.
        Raises ``AssertionError`` if there is no match.
        NTz not found in warning list)Ú	enumerater=   ÚcategoryÚpopÚ
issubclassÚAssertionError)r>   rL   Zbest_idxrF   Úwr+   r   r   r   rO   Î   s    
ÿþzWarningsRecorder.popc                 C  s   g | j dd…< dS )z$Clear the list of recorded warnings.NrA   rB   r   r   r   Úcleará   s    zWarningsRecorder.clearr   c                   sD   | j rd}td| ›d�ƒ‚tƒ  ¡ }|d us0J ‚|| _t d¡ | S )NTzCannot enter z twiceÚalways)r<   ÚRuntimeErrorr:   Ú	__enter__r=   r   r   )r>   r+   r=   r?   r   r   rV   å   s    

zWarningsRecorder.__enter__útype[BaseException] | NoneúBaseException | NoneúTracebackType | None©Úexc_typeÚexc_valÚexc_tbr   c                   s4   | j sd}td| ›d�ƒ‚tƒ  |||¡ d| _ d S )NTzCannot exit z without entering firstF)r<   rU   r:   Ú__exit__)r>   r[   r\   r]   r+   r?   r   r   r^   ð   s
    zWarningsRecorder.__exit__)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r;   ÚpropertyrC   rG   rI   rK   ÚWarningrO   rS   rV   r^   Ú__classcell__r   r   r?   r   r   ª   s   c                      s\   e Zd Zedfddœdddddœ‡ fd	d
„Zdddœdd„Zdddddœ‡ fdd„Z‡  ZS )r-   NFr   r,   r!   r7   r8   )r.   r/   r   r   c                  sŠ   t |ƒ tƒ jdd� d}t|tƒrN|D ]}t|tƒs(t|t|ƒ ƒ‚q(|}n,t|tƒrjt|tƒrj|f}nt|t|ƒ ƒ‚|| _	|| _
d S )NTr   z/exceptions must be derived from Warning, not %s)r   r:   r;   Ú
isinstanceÚtuplerP   rd   r3   r5   r.   r/   )r>   r.   r/   r   ÚmsgÚexcZexpected_warning_tupr?   r   r   r;     s    

ÿzWarningsChecker.__init__rE   )Úwarningr   c                 C  s>   | j d usJ ‚t|j| j ƒo<t| jd u p:t | jt|jƒ¡ƒS r"   )	r.   rP   rN   r7   r/   ÚreÚsearchÚstrÚmessage)r>   rj   r   r   r   Úmatches  s    ÿzWarningsChecker.matchesrW   rX   rY   rZ   c                   sò  t ƒ  |||¡ d}|d ur4t|tƒr0t|tƒr4d S ddœ‡ fdd„}�zt‡ fdd„ˆ D ƒƒs|tdˆ j› d	|ƒ › d
�ƒ n8t‡ fdd„ˆ D ƒƒs´tdˆ j› dˆ j› d|ƒ › d
�ƒ W ˆ D ]0}ˆ  	|¡sºt
j|j|j|j|j|j|jd� qºˆ D ]X}t|jƒtu�rqð|jj�sqð|jjd }t|tƒ�r,qðtd|›dt|ƒj› d�ƒ‚qðn¢ˆ D ]4}ˆ  	|¡�sPt
j|j|j|j|j|j|jd� �qPˆ D ]`}t|jƒtu�r¢�qŠ|jj�s°�qŠ|jjd }t|tƒ�rÌ�qŠtd|›dt|ƒj› d�ƒ‚�qŠ0 d S )NTrm   r   c                     s   t dd„ ˆ D ƒdd�S )Nc                 S  s   g | ]
}|j ‘qS r   )rn   )Ú.0r9   r   r   r   Ú
<listcomp>9  ó    z?WarningsChecker.__exit__.<locals>.found_str.<locals>.<listcomp>é   )Úindentr   r   rB   r   r   Ú	found_str8  s    z+WarningsChecker.__exit__.<locals>.found_strc                 3  s   | ]}t |jˆ jƒV  qd S r"   )rP   rN   r.   ©rp   rR   rB   r   r   Ú	<genexpr><  rr   z+WarningsChecker.__exit__.<locals>.<genexpr>z"DID NOT WARN. No warnings of type z" were emitted.
 Emitted warnings: Ú.c                 3  s   | ]}ˆ   |¡V  qd S r"   )ro   rv   rB   r   r   rw   A  rr   z* matching the regex were emitted.
 Regex: z
 Emitted warnings: )rn   rN   ÚfilenameÚlinenoÚmoduleÚsourcer   z$Warning must be str or Warning, got z (type ú))r:   r^   rf   Ú	Exceptionr   Úanyr   r.   r/   ro   r   Úwarn_explicitrn   rN   ry   rz   r`   r|   r5   ÚUserWarningr%   rm   r3   r_   )r>   r[   r\   r]   r+   ru   rR   rh   r?   rB   r   r^   #  s„    ÿý
ÿÿ
ÿþÿ
ú
ÿÞú

ÿzWarningsChecker.__exit__)r_   r`   ra   rd   r;   ro   r^   re   r   r   r?   r   r-     s   ýû)N).)$rb   Ú
__future__r   Úcollections.abcr   r   r   Úpprintr   rk   Útypesr   Útypingr	   r
   r   r   r   Ztyping_extensionsr   r   Z_pytest.deprecatedr   Z_pytest.fixturesr   Z_pytest.outcomesr   r   r   r   r#   r'   rd   Úcatch_warningsr   r-   r   r   r   r   Ú<module>   sV   ÿ ÿ" ÿý	ÿý@W