B
    ܇\n$                 @   s   d Z ddlmZ ddlm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	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
d ZdddZdd ZG dd dejZG dd deZdS )z4 recording warnings during test function execution.     )absolute_import)division)print_functionN)PYTEST_WARNS_UNKNOWN_KWARGS)
WARNS_EXEC)yield_fixture)failc           	   c   s*   t  } |  td | V  W dQ R X dS )zReturn a :class:`WarningsRecorder` instance that records all warnings emitted by test functions.

    See http://docs.python.org/library/warnings.html for information
    on warning categories.
    defaultN)WarningsRecorderwarningssimplefilter)Zwrec r   .lib/python3.7/site-packages/_pytest/recwarn.pyrecwarn   s    
r   c             O   s*   d}| dk	r| f| }t ttff||S )aG  context manager that can be used to ensure a block of code triggers a
    ``DeprecationWarning`` or ``PendingDeprecationWarning``::

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

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

    ``deprecated_call`` 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.
    TN)warnsDeprecationWarningPendingDeprecationWarning)funcargskwargs__tracebackhide__r   r   r   deprecated_call!   s    
r   c       	   	   O   s   d}|s>| dd}|r2tjtjt|ddd t| |dS t|d trtjt	dd |\}t|tsnt
td	}|j }|| t| & tj| }t||j| W dQ R X n*|d }t|  ||d	d |S Q R X dS )
a  Assert that code raises a particular class of warning.

    Specifically, the parameter ``expected_warning`` can be a warning class or
    sequence of warning classes, and the inside the ``with`` block must issue a warning of that class or
    classes.

    This helper produces a list of :class:`warnings.WarningMessage` objects,
    one for each warning raised.

    This function can be used as a context manager, or any of the other ways
    ``pytest.raises`` can be used::

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

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

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

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

        >>> with 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... was emitted...

    TmatchN)r      )
stacklevel)
match_exprr      )popr   warnr   formatsortedWarningsChecker
isinstancestrr   AssertionErrorsys	_getframef_localscopyupdate_pytest_codeZSourcecompilesixZexec_	f_globals)	expected_warningr   r   r   r   codeframeZlocr   r   r   r   r   7   s(     




r   c                   sp   e Zd ZdZ fddZedd Zdd Zdd	 Zd
d Z	e
fddZdd Z fddZ fddZ  ZS )r
   z^A context manager to record raised warnings.

    Adapted from `warnings.catch_warnings`.
    c                s"   t t| jdd d| _g | _d S )NT)recordF)superr
   __init___entered_list)self)	__class__r   r   r4   v   s    zWarningsRecorder.__init__c             C   s   | j S )zThe list of recorded warnings.)r6   )r7   r   r   r   list{   s    zWarningsRecorder.listc             C   s
   | j | S )z Get a recorded warning by index.)r6   )r7   ir   r   r   __getitem__   s    zWarningsRecorder.__getitem__c             C   s
   t | jS )z&Iterate through the recorded warnings.)iterr6   )r7   r   r   r   __iter__   s    zWarningsRecorder.__iter__c             C   s
   t | jS )z The number of recorded warnings.)lenr6   )r7   r   r   r   __len__   s    zWarningsRecorder.__len__c             C   sD   x.t | jD ] \}}t|j|r| j|S qW d}td| dS )z>Pop the first recorded warning, raise exception if not exists.Tz%r not found in warning listN)	enumerater6   
issubclasscategoryr   r$   )r7   clsr:   wr   r   r   r   r      s
    zWarningsRecorder.popc             C   s   g | j dd< dS )z$Clear the list of recorded warnings.N)r6   )r7   r   r   r   clear   s    zWarningsRecorder.clearc                sX    j rd}td  tt   _td tj	rTd fdd	}|tj
 t_
 _ S )NTzCannot enter %r twicealwaysr   c          	      s   t | tr| j}|d krt}t|ts*tt|j}d|krn|d }d |d< z 	| ||d S ||d< X n 	| ||d S d S )NZ__warningregistry__r   )
r"   Warningr8   UserWarningrA   r$   r%   r&   r.   _saved_warn)messagerB   r   r.   Zorig)r7   r   r   r      s    
z(WarningsRecorder.__enter__.<locals>.warn)Nr   )r5   RuntimeErrorr3   r
   	__enter__r6   r   r   r-   PY2r   rI   )r7   r   r   )r8   )r7   r   rL      s    
zWarningsRecorder.__enter__c                s>   | j sd}td|  tjr$| jt_tt| j	|  d| _ d S )NTz%Cannot exit %r without entering firstF)
r5   rK   r-   rM   rI   r   r   r3   r
   __exit__)r7   exc_infor   )r8   r   r   rN      s    zWarningsRecorder.__exit__)__name__
__module____qualname____doc__r4   propertyr9   r;   r=   r?   rG   r   rE   rL   rN   __classcell__r   r   )r8   r   r
   p   s   %r
   c                   s*   e Zd Zd fdd	Z fddZ  ZS )r!   Nc                s   t t|   d}t|trFxR|D ]}t|s"t|t| q"W n*t|rX|f}n|d k	rpt|t| || _	|| _
d S )NzDexceptions must be old-style classes or derived from Warning, not %s)r3   r!   r4   r"   tupleinspectZisclass	TypeErrortyper/   r   )r7   r/   r   msgexc)r8   r   r   r4      s    



zWarningsChecker.__init__c                s   t t j|  d}tdd |D rȈ jd k	rt fdd D shd}td jdd  D  n` jd k	rxT D ],}t	|j
 jrxt jt|jrxP qxW td j jd	d  D  d S )
NTc             s   s   | ]}|d kV  qd S )Nr   ).0ar   r   r   	<genexpr>   s    z+WarningsChecker.__exit__.<locals>.<genexpr>c             3   s   | ]}t |j jV  qd S )N)rA   rB   r/   )r\   r)r7   r   r   r^      s    zVDID NOT WARN. No warnings of type {} was emitted. The list of emitted warnings is: {}.c             S   s   g | ]
}|j qS r   )rJ   )r\   eachr   r   r   
<listcomp>   s    z,WarningsChecker.__exit__.<locals>.<listcomp>zfDID NOT WARN. No warnings of type {} matching ('{}') was emitted. The list of emitted warnings is: {}.c             S   s   g | ]
}|j qS r   )rJ   )r\   r`   r   r   r   ra      s    )r3   r!   rN   allr/   anyr   r   r   rA   rB   rer,   searchr#   rJ   )r7   rO   r   r_   )r8   )r7   r   rN      s&    


zWarningsChecker.__exit__)NN)rP   rQ   rR   r4   rN   rU   r   r   )r8   r   r!      s   r!   )N)rS   Z
__future__r   r   r   rW   rd   r%   r   r-   Z_pytest._coder*   Z_pytest.deprecatedr   r   Z_pytest.fixturesr   Z_pytest.outcomesr   r   r   r   catch_warningsr
   r!   r   r   r   r   <module>   s$   
9[