B
    ”Ü‡\öW  ã               @   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m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
ZdZG dd„ dejƒZdd„ Zdd„ Zed$dd„ƒZG dd„ dejƒZG dd„ deƒZejdd„ ƒZdd„ Zej dddd„ ƒZ!G d d!„ d!eƒZ"G d"d#„ d#ejƒZ#dS )%z# Access and control log capturing. é    )Úabsolute_import)Údivision)Úprint_functionN)Úcontextmanager)Údummy_context_manager)Úcreate_terminal_writer)ÚPathz7%(filename)-25s %(lineno)4d %(levelname)-8s %(message)sz%H:%M:%Sc                   st   e Zd ZdZejdhejddhejdhejdhej	dhej
dhejeƒ iZe d¡Z‡ fdd	„Z‡ fd
d„Z‡  ZS )ÚColoredLevelFormatterzQ
    Colorize the %(levelname)..s part of the log format passed to __init__.
    ZredÚboldZyellowZgreenZpurplez%\(levelname\)([+-]?\d*s)c                s°   t t| ƒj||Ž tjr"| j| _n
| jj| _i | _| j	 
| j¡}|sHd S | ¡ }xZ| j ¡ D ]L\}}|dt |¡i }dd„ |D ƒ}	|j|f|	Ž}
| j	 |
| j¡| j|< q\W d S )NZ	levelnamec             S   s   i | ]
}d |“qS )T© )Ú.0Únamer   r   ú.lib/python3.7/site-packages/_pytest/logging.pyú
<dictcomp>9   s    z2ColoredLevelFormatter.__init__.<locals>.<dictcomp>)Úsuperr	   Ú__init__ÚsixÚPY2Ú_fmtÚ_original_fmtÚ_styleÚ_level_to_fmt_mappingÚLEVELNAME_FMT_REGEXÚsearchÚgroupÚLOGLEVEL_COLOROPTSÚitemsÚloggingZgetLevelNameZmarkupÚsub)ÚselfZterminalwriterÚargsÚkwargsZlevelname_fmt_matchZlevelname_fmtÚlevelZ
color_optsZformatted_levelnameZcolor_kwargsZcolorized_formatted_levelname)Ú	__class__r   r   r   &   s"    


zColoredLevelFormatter.__init__c                s8   | j  |j| j¡}tjr || _n|| j_tt	| ƒ 
|¡S )N)r   ÚgetÚlevelnor   r   r   r   r   r   r	   Úformat)r   ÚrecordZfmt)r#   r   r   r&   A   s
    zColoredLevelFormatter.format)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   ZCRITICALZERRORZWARNINGZWARNÚINFOÚDEBUGZNOTSETÚsetr   ÚreÚcompiler   r   r&   Ú__classcell__r   r   )r#   r   r	      s   

r	   c             G   s6   x0|D ](}|   |¡}|d kr&|  |¡}|r|S qW d S )N)Ú	getoptionÚgetini)ÚconfigÚnamesr   Zretr   r   r   Úget_option_iniJ   s    


r6   c          	      sæ   ˆ  d¡‰ d+‡ ‡fdd„	}|ddddd	d
dd |ddddd |ddtdd |ddtdd ˆjddd
dd |ddddd |ddddd |dd ddd |d!d"dd#d |d$d%dd&d |d'd(tdd |d)d*tdd dS ),z%Add options to control log capturing.r   Nc                s0   ˆj |||d|  d ˆ j| fd|i|—Ž d S )Nzdefault value for )ÚdefaultÚtypeÚhelpÚdest)ÚaddiniZ	addoption)Úoptionr:   r7   r8   r!   )r   Úparserr   r   Úadd_option_iniW   s    z(pytest_addoption.<locals>.add_option_iniz--no-print-logsÚ	log_printZstore_constFTÚboolz-disable printing caught logs on failed tests.)r:   ÚactionZconstr7   r8   r9   z--log-levelÚ	log_levelz(logging level used by the logging module)r:   r7   r9   z--log-formatÚ
log_formatz)log format as used by the logging module.z--log-date-formatÚlog_date_formatz.log date format as used by the logging module.Úlog_clizBenable log display during test run (also known as "live logging").)r7   r8   r9   z--log-cli-levelÚlog_cli_levelzcli logging level.z--log-cli-formatÚlog_cli_formatz--log-cli-date-formatÚlog_cli_date_formatz
--log-fileÚlog_filez/path to a file when logging will be written to.z--log-file-levelÚlog_file_levelzlog file logging level.z--log-file-formatÚlog_file_formatz--log-file-date-formatÚlog_file_date_format)NN)ZgetgroupÚDEFAULT_LOG_FORMATÚDEFAULT_LOG_DATE_FORMATr;   )r=   r>   r   )r   r=   r   Úpytest_addoptionS   s|    
rO   c          	   c   s”   t  ¡ }|dk	r|  |¡ |dk	r,|  |¡ | |jk}|rD| | ¡ |dk	rb|j}| t||ƒ¡ z
| V  W d|dk	r€| |¡ |rŽ| | ¡ X dS )zCContext manager that prepares the whole logging machinery properly.N)	r   Ú	getLoggerÚsetFormatterÚsetLevelZhandlersZ
addHandlerr"   ÚminZremoveHandler)ÚhandlerÚ	formatterr"   Zroot_loggerZadd_new_handlerÚ
orig_levelr   r   r   Úcatching_logs§   s"    





rW   c               @   s(   e Zd ZdZdd„ Zdd„ Zdd„ ZdS )	ÚLogCaptureHandlerz;A logging handler that stores log records and the log text.c             C   s   t j | tj ¡ ¡ g | _dS )zCreates a new log handler.N)r   ÚStreamHandlerr   ÚpyÚioÚTextIOÚrecords)r   r   r   r   r   Æ   s    zLogCaptureHandler.__init__c             C   s   | j  |¡ tj | |¡ dS )z;Keep the log records in a list in addition to the log text.N)r]   Úappendr   rY   Úemit)r   r'   r   r   r   r_   Ë   s    zLogCaptureHandler.emitc             C   s   g | _ tj ¡ | _d S )N)r]   rZ   r[   r\   Ústream)r   r   r   r   ÚresetÐ   s    zLogCaptureHandler.resetN)r(   r)   r*   r+   r   r_   ra   r   r   r   r   rX   Ã   s   rX   c               @   s„   e Zd ZdZdd„ Zdd„ Zedd„ ƒZdd	„ Zed
d„ ƒZ	edd„ ƒZ
edd„ ƒZedd„ ƒZdd„ Zddd„Zeddd„ƒZdS )ÚLogCaptureFixturez-Provides access and control of log capturing.c             C   s   || _ i | _dS )zCreates a new funcarg.N)Ú_itemÚ_initial_log_levels)r   Úitemr   r   r   r   Ø   s    zLogCaptureFixture.__init__c             C   s0   x*| j  ¡ D ]\}}t |¡}| |¡ qW dS )zcFinalizes the fixture.

        This restores the log levels changed by :meth:`set_level`.
        N)rd   r   r   rP   rR   )r   Úlogger_namer"   Úloggerr   r   r   Ú	_finalizeÞ   s    
zLogCaptureFixture._finalizec             C   s   | j jS )z+
        :rtype: LogCaptureHandler
        )rc   Úcatch_log_handler)r   r   r   r   rT   è   s    zLogCaptureFixture.handlerc             C   s    | j j |¡}|r|jS g S dS )a\  
        Get the logging records for one of the possible test phases.

        :param str when:
            Which test phase to obtain the records from. Valid values are: "setup", "call" and "teardown".

        :rtype: List[logging.LogRecord]
        :return: the list of captured records at the given stage

        .. versionadded:: 3.4
        N)rc   Úcatch_log_handlersr$   r]   )r   ÚwhenrT   r   r   r   Úget_recordsï   s    zLogCaptureFixture.get_recordsc             C   s   | j j ¡ S )zReturns the log text.)rT   r`   Úgetvalue)r   r   r   r   Útext  s    zLogCaptureFixture.textc             C   s   | j jS )z Returns the list of log records.)rT   r]   )r   r   r   r   r]     s    zLogCaptureFixture.recordsc             C   s   dd„ | j D ƒS )zÇReturns a list of a stripped down version of log records intended
        for use in assertion comparison.

        The format of the tuple is:

            (logger_name, log_level, message)
        c             S   s   g | ]}|j |j| ¡ f‘qS r   )r   r%   Ú
getMessage)r   Úrr   r   r   ú
<listcomp>  s    z3LogCaptureFixture.record_tuples.<locals>.<listcomp>)r]   )r   r   r   r   Úrecord_tuples  s    	zLogCaptureFixture.record_tuplesc             C   s   dd„ | j D ƒS )a†  Returns a list of format-interpolated log messages.

        Unlike 'records', which contains the format string and parameters for interpolation, log messages in this list
        are all interpolated.
        Unlike 'text', which contains the output from the handler, log messages in this list are unadorned with
        levels, timestamps, etc, making exact comparisons more reliable.

        Note that traceback or stack info (from :func:`logging.exception` or the `exc_info` or `stack_info` arguments
        to the logging functions) is not included, as this is added by the formatter in the handler.

        .. versionadded:: 3.7
        c             S   s   g | ]}|  ¡ ‘qS r   )ro   )r   rp   r   r   r   rq   $  s    z.LogCaptureFixture.messages.<locals>.<listcomp>)r]   )r   r   r   r   Úmessages  s    zLogCaptureFixture.messagesc             C   s   | j  ¡  dS )z8Reset the list of log records and the captured log text.N)rT   ra   )r   r   r   r   Úclear&  s    zLogCaptureFixture.clearNc             C   s,   |}t  |¡}| j ||j¡ | |¡ dS )aÇ  Sets the level for capturing of logs. The level will be restored to its previous value at the end of
        the test.

        :param int level: the logger to level.
        :param str logger: the logger to update the level. If not given, the root logger level is updated.

        .. versionchanged:: 3.4
            The levels of the loggers changed by this function will be restored to their initial values at the
            end of the test.
        N)r   rP   rd   Ú
setdefaultr"   rR   )r   r"   rg   rf   r   r   r   Ú	set_level*  s    
zLogCaptureFixture.set_levelc          	   c   s6   t  |¡}|j}| |¡ z
dV  W d| |¡ X dS )a9  Context manager that sets the level for capturing of logs. After the end of the 'with' statement the
        level is restored to its original value.

        :param int level: the logger to level.
        :param str logger: the logger to update the level. If not given, the root logger level is updated.
        N)r   rP   r"   rR   )r   r"   rg   rV   r   r   r   Úat_level;  s    


zLogCaptureFixture.at_level)N)N)r(   r)   r*   r+   r   rh   ÚpropertyrT   rl   rn   r]   rr   rs   rt   rv   r   rw   r   r   r   r   rb   Õ   s   

rb   c             c   s   t | jƒ}|V  | ¡  dS )a¢  Access and control log capturing.

    Captured logs are available through the following properties/methods::

    * caplog.text            -> string containing formatted log output
    * caplog.records         -> list of logging.LogRecord instances
    * caplog.record_tuples   -> list of (logger_name, level, message) tuples
    * caplog.clear()         -> clear captured records and formatted log output string
    N)rb   Znoderh   )ZrequestÚresultr   r   r   ÚcaplogL  s    
rz   c          	   G   s„   x2|D ]&}|   |¡}|dkr&|  |¡}|rP qW dS t|tjƒrH| ¡ }yttt||ƒƒS  t	k
r~   t
 d ||¡¡‚Y nX dS )z Return the actual logging level.Nzo'{}' is not recognized as a logging level name for '{}'. Please consider passing the logging level num instead.)r2   r3   Ú
isinstancer   Zstring_typesÚupperÚintÚgetattrr   Ú
ValueErrorÚpytestZ
UsageErrorr&   )r4   Zsetting_namesZsetting_namerB   r   r   r   Úget_actual_log_level\  s    


r   T)Ztrylastc             C   s   | j  t| ƒd¡ d S )Nzlogging-plugin)ÚpluginmanagerÚregisterÚLoggingPlugin)r4   r   r   r   Úpytest_configurev  s    r…   c               @   s  e Zd ZdZdd„ Zdd„ Zdd„ Zdd	„ Zej	d
d
ddd„ ƒZ
edd„ ƒZedd„ ƒZej	d
ddd„ ƒZej	d
ddd„ ƒZej	d
ddd„ ƒZej	d
ddd„ ƒZej	d
ddd„ ƒZej	d
ddd„ ƒZej	d
d
ddd „ ƒZej	d
d
dd!d"„ ƒZej	d
dd#d$„ ƒZd%S )&r„   zLAttaches to the logging module and captures log messages for each test.
    c             C   sè   || _ |  ¡ r | d¡s d|j_t|dƒ| _t t|dƒt|dƒ¡| _	t
|dƒ| _t
|dƒ| _t|ddƒ| _t|d	dƒ| _tj| j| jd
| _t|dƒ}|r¾tj|ddd| _| j | j¡ nd| _d| _dd„ | _|  ¡ rä|  ¡  dS )z·Creates a new plugin to capture log messages.

        The formatter can be safely shared across all handlers so
        create a single one for the entire test session here.
        Úverboseé   r?   rC   rD   rB   rJ   rK   rL   )ÚdatefmtrI   ÚwzUTF-8)ÚmodeÚencodingNc               S   s   t ƒ S )N)r   r   r   r   r   Ú<lambda>¦  s    z(LoggingPlugin.__init__.<locals>.<lambda>)Ú_configÚ_log_cli_enabledr2   r<   r†   r6   Ú
print_logsr   Ú	FormatterrU   r   rB   rJ   rK   rL   Úlog_file_formatterÚFileHandlerÚlog_file_handlerrQ   Úlog_cli_handlerÚlive_logs_contextÚ_setup_cli_logging)r   r4   rI   r   r   r   r     s0    

zLoggingPlugin.__init__c                s®   | j }|j d¡}|d krd S |j d¡}t||ƒ‰t|ddƒ}t|ddƒ}|jjdkrxtj 	|¡rxtt
|ƒ||d‰ ntj||d‰ t|d	d
ƒ‰ˆ| _‡ ‡‡fdd„| _d S )NZterminalreporterZcapturemanagerrG   rC   rH   rD   Zno)rˆ   rF   rB   c                  s   t ˆˆ ˆdS )N)rU   r"   )rW   r   )Úlog_cli_formatterr”   rF   r   r   rŒ   Ë  s   z2LoggingPlugin._setup_cli_logging.<locals>.<lambda>)r   r‚   Z
get_pluginÚ_LiveLoggingStreamHandlerr6   r<   Zcolorr	   r   r   r   r   r   r   r”   r•   )r   r4   Úterminal_reporterÚcapture_managerrG   rH   r   )r—   r”   rF   r   r–   ®  s(    



z LoggingPlugin._setup_cli_loggingc             C   s`   t |ƒ}| ¡ st | jj|ƒ}|j ¡ s8|jjddd tjt	|ƒddd| _
| j
 | j¡ dS )zãPublic method, which can set filename parameter for
        Logging.FileHandler(). Also creates parent directory if
        it does not exist.

        .. warning::
            Please considered as an experimental API.
        T)Úexist_okÚparentsr‰   zUTF-8)rŠ   r‹   N)r   Zis_absoluter   ZrootdirÚparentÚexistsÚmkdirr   r’   Ústrr“   rQ   r‘   )r   Úfnamer   r   r   Úset_log_pathÏ  s    
zLoggingPlugin.set_log_pathc             C   s   | j  d¡dk	p| j  d¡S )z‘Return True if log_cli should be considered enabled, either explicitly
        or because --log-cli-level was given in the command-line.
        z--log-cli-levelNrE   )r   r2   r3   )r   r   r   r   rŽ   ä  s    zLoggingPlugin._log_cli_enabledT)ÚhookwrapperZtryfirstc          
   c   s^   |   ¡ L | jr| j d¡ | jd k	rJt| j| jd d V  W d Q R X nd V  W d Q R X d S )NZ
collection)r"   )r•   r”   Úset_whenr“   rW   rJ   )r   r   r   r   Úpytest_collectionì  s    

zLoggingPlugin.pytest_collectionc          
   c   sP   |   ||¡: | jd k	r<t| j| jd d V  W d Q R X nd V  W d Q R X d S )N)r"   )Ú_runtest_for_mainr“   rW   rJ   )r   re   rk   r   r   r   Ú_runtest_forø  s
    
zLoggingPlugin._runtest_forc          	   c   s¨   t tƒ | j| jdŠ}| jr(| j |¡ |dkr:dV  dS t|dƒsJi |_||j|< ||_z
dV  W d|dkrv|`|`X | j	rš|j
 ¡  ¡ }| |d|¡ W dQ R X dS )z6Implements the internals of pytest_runtest_xxx() hook.)rU   r"   Nrj   ÚteardownÚlog)rW   rX   rU   rB   r”   r¤   Úhasattrrj   ri   r   r`   rm   ÚstripZadd_report_section)r   re   rk   Zlog_handlerr©   r   r   r   r¦     s(    


zLoggingPlugin._runtest_for_main)r£   c          	   c   s"   |   |d¡ d V  W d Q R X d S )NZsetup)r§   )r   re   r   r   r   Úpytest_runtest_setup  s    z"LoggingPlugin.pytest_runtest_setupc          	   c   s"   |   |d¡ d V  W d Q R X d S )NZcall)r§   )r   re   r   r   r   Úpytest_runtest_call#  s    z!LoggingPlugin.pytest_runtest_callc          	   c   s"   |   |d¡ d V  W d Q R X d S )Nr¨   )r§   )r   re   r   r   r   Úpytest_runtest_teardown(  s    z%LoggingPlugin.pytest_runtest_teardownc          	   c   s2   | j r| j  ¡  |  d d¡ d V  W d Q R X d S )NÚstart)r”   ra   r§   )r   r   r   r   Úpytest_runtest_logstart-  s    
z%LoggingPlugin.pytest_runtest_logstartc          	   c   s"   |   d d¡ d V  W d Q R X d S )NÚfinish)r§   )r   r   r   r   Úpytest_runtest_logfinish4  s    z&LoggingPlugin.pytest_runtest_logfinishc          	   c   s"   |   d d¡ d V  W d Q R X d S )NZ	logreport)r§   )r   r   r   r   Úpytest_runtest_logreport9  s    z&LoggingPlugin.pytest_runtest_logreportc          
   c   s^   |   ¡ L | jr| j d¡ | jd k	rJt| j| jd d V  W d Q R X nd V  W d Q R X d S )NZsessionfinish)r"   )r•   r”   r¤   r“   rW   rJ   )r   r   r   r   Úpytest_sessionfinish>  s    

z"LoggingPlugin.pytest_sessionfinishc          
   c   s^   |   ¡ L | jr| j d¡ | jd k	rJt| j| jd d V  W d Q R X nd V  W d Q R X d S )NZsessionstart)r"   )r•   r”   r¤   r“   rW   rJ   )r   r   r   r   Úpytest_sessionstartI  s    

z!LoggingPlugin.pytest_sessionstartc          
   c   sL   |   ¡ : | jdk	r8t| j| jd dV  W dQ R X ndV  W dQ R X dS )zRuns all collected test items.N)r"   )r•   r“   rW   rJ   )r   Zsessionr   r   r   Úpytest_runtestloopT  s
    

z LoggingPlugin.pytest_runtestloopN)r(   r)   r*   r+   r   r–   r¢   rŽ   r€   Úhookimplr¥   r   r§   r¦   r¬   r­   r®   r°   r²   r³   r´   rµ   r¶   r   r   r   r   r„   {  s"   /!	r„   c               @   s0   e Zd ZdZdd„ Zdd„ Zdd„ Zdd	„ Zd
S )r˜   a  
    Custom StreamHandler used by the live logging feature: it will write a newline before the first log message
    in each test.

    During live logging we must also explicitly disable stdout/stderr capturing otherwise it will get captured
    and won't appear in the terminal.
    c             C   s2   t jj| |d || _|  ¡  |  d¡ d| _dS )zŒ
        :param _pytest.terminal.TerminalReporter terminal_reporter:
        :param _pytest.capture.CaptureManager capture_manager:
        )r`   NF)r   rY   r   rš   ra   r¤   Ú_test_outcome_written)r   r™   rš   r   r   r   r   h  s
    
z"_LiveLoggingStreamHandler.__init__c             C   s
   d| _ dS )zAReset the handler; should be called before the start of each testFN)Ú_first_record_emitted)r   r   r   r   ra   s  s    z_LiveLoggingStreamHandler.resetc             C   s   || _ d| _|dkrd| _dS )z7Prepares for the given test phase (setup/call/teardown)Fr¯   N)Ú_whenÚ_section_name_shownr¸   )r   rk   r   r   r   r¤   w  s    z"_LiveLoggingStreamHandler.set_whenc          	   C   sž   | j r| j  ¡ ntƒ }|z | js6| j d¡ d| _n"| jdkrX| jsXd| _| j d¡ | js‚| jr‚| jj	d| j ddd d| _t
j | |¡ W d Q R X d S )NÚ
T)r¨   r±   z	live log ú-)Úsepr
   )rš   Zglobal_and_fixture_disabledr   r¹   r`   Úwriterº   r¸   r»   Zsectionr   rY   r_   )r   r'   Zctx_managerr   r   r   r_   ~  s    
z_LiveLoggingStreamHandler.emitN)r(   r)   r*   r+   r   ra   r¤   r_   r   r   r   r   r˜   _  s
   r˜   )NN)$r+   Z
__future__r   r   r   r   r/   Ú
contextlibr   rZ   r   r€   Z_pytest.compatr   Z_pytest.configr   Z_pytest.pathlibr   rM   rN   r   r	   r6   rO   rW   rY   rX   Úobjectrb   Zfixturerz   r   r·   r…   r„   r˜   r   r   r   r   Ú<module>   s6   4	Tw e