o
    rhc                     @  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	m
Z
 ddl	mZ ddlm  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 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" ddl#Z#e d  Z$dHddZ%dIddZ&i Z'dddgie'd < dg d!ie'd"< e'd  ( e'd#< e&e'd# e'd"  e'd  e'd$< G d%d& d&Z)dJd*d+Z*e#j+dKd-d.Z,e#j+dKd/d0Z-dLd3d4Z.e#j+d5d6dKd7d8Z/dMd;d<Z0dNd?d@Z1dNdAdBZ2dOdEdFZ3G dGd dZ4dS )Pa  Report test results in JUnit-XML format, for use with Jenkins and build
integration servers.

Based on initial code from Ross Lawley.

Output conforms to
https://github.com/jenkinsci/xunit-plugin/blob/master/src/main/resources/org/jenkinsci/plugins/xunit/types/model/xsd/junit-10.xsd
    )annotations)datetime)timezoneN)Callable)Match)nodes)timing)ExceptionRepr)ReprFileLocation)Config)filename_arg)Parser)FixtureRequest)
TestReport)StashKey)TerminalReporterLogXMLargobjectreturnstrc                 C  s    d	dd}d}t ||t| S )
a!  Visually escape invalid XML characters.

    For example, transforms
        'hello\aworld\b'
    into
        'hello#x07world#x08'
    Note that the #xABs are *not* XML escapes - missing the ampersand &#xAB.
    The idea is to escape visually for the user rather than for XML itself.
    matchobj
Match[str]r   r   c                 S  s,   t |  }|dkrd|dS d|dS )N   z#x02X04X)ordgroup)r   i r   N/var/www/html/alpaca_bot/venv/lib/python3.10/site-packages/_pytest/junitxml.pyrepl3   s   zbin_xml_escape.<locals>.replu    [^	
 -~-퟿-�က0-ჿff]N)r   r   r   r   )resubr   )r   r!   illegal_xml_rer   r   r    bin_xml_escape(   s   
r%   Nonec                 C  sX   i }|   D ]\}}|  D ]\}}t|tstt||| ||< qq| | d S N)items
isinstancelist	TypeErrortypeupdate)leftrightresultklvlkrvrr   r   r    merge_familyC   s   
r5   testcase	classnamename_base)filelineurl_base_legacyxunit1xunit2c                   @  s   e Zd Zd=ddZd>ddZd?ddZd?ddZd@ddZdAddZdBddZ	dCdDd#d$Z
dEd&d'ZdFd*d+ZdGd-d.ZdEd/d0ZdEd1d2ZdEd3d4ZdEd5d6ZdEd7d8ZdEd9d:ZdHd;d<ZdS )I_NodeReporternodeidstr | TestReportxmlr   r   r&   c                 C  s<   || _ || _| jj| _| jj| _d| _g | _g | _i | _d S )N        )idrC   	add_statsfamilyduration
propertiesr   attrs)selfrA   rC   r   r   r    __init__Z   s   


z_NodeReporter.__init__node
ET.Elementc                 C  s   | j |j | j| d S r'   )rC   rF   tagr   append)rK   rM   r   r   r    rP   d   s   z_NodeReporter.appendr8   r   valuer   c                 C  s   | j t|t|f d S r'   )rI   rP   r   r%   rK   r8   rQ   r   r   r    add_propertyh   s   z_NodeReporter.add_propertyc                 C  s   t || jt|< d S r'   )r%   rJ   r   rR   r   r   r    add_attributek      z_NodeReporter.add_attributeET.Element | Nonec                 C  >   | j rtd}| j D ]\}}|tjd||d q|S dS z9Return a Junit node containing custom properties, if any.rI   propertyr8   rQ   N)rI   ETElementrP   rK   rI   r8   rQ   r   r   r    make_properties_noden      
z"_NodeReporter.make_properties_node
testreportr   c                 C  s   t |j}| j}|d d }| jjr|d| jj d|t|d |jd d}|jd d ur:t	|jd |d< t
|drD|j|d< || _| j| | jdkrTd S i }| jD ]}|t| j d	 v rk| j| ||< qY|| _d S )
Nr   .)r7   r8   r:      r;   r<   r>   r6   )mangle_test_addressrA   rJ   rC   prefixinsertjoinr%   locationr   hasattrr<   r-   rG   families)rK   r`   namesexisting_attrs
classnamesrJ   
temp_attrskeyr   r   r    record_testreportw   s.   






z_NodeReporter.record_testreportc                 C  sB   t jd| j| jdd}|  }|d ur|| || j |S )Nr6   .3f)time)r[   r\   rJ   rH   r^   rP   extendr   )rK   r6   rI   r   r   r    to_xml   s   
z_NodeReporter.to_xmlNrO   messagedata
str | Nonec                 C  s&   t j||d}t||_| | d S )N)ru   r[   r\   r%   textrP   )rK   rO   ru   rv   rM   r   r   r    _add_simple   s   
z_NodeReporter._add_simplereportc                 C  s   | j js	|jr	d S |j}|j}|j}| j jdkrd S d}| j jdv r(| |d}| j jdv r?|| |d7 }| ||d d}| j jdv rV|| |d	7 }| ||d
 d}|ra| ||d d S d S )Nno )logallz Captured Log )
system-outout-errr   z Captured Out r   )
system-errr   r   z Captured Err r   )	rC   log_passing_testspassed	capstdoutcaplog	capstderrlogging_prepare_content_write_content)rK   r{   content_outcontent_logcontent_errcontent_allr   r   r    write_captured_output   s*   z#_NodeReporter.write_captured_outputcontentheaderc                 C  s   d |dd|dgS )N
P   -r}   )rg   center)rK   r   r   r   r   r    r         z_NodeReporter._prepare_contentjheaderc                 C  s"   t |}t||_| | d S r'   rx   )rK   r{   r   r   rO   r   r   r    r      s   

z_NodeReporter._write_contentc                 C  s   |  d d S )Nr   )rF   rK   r{   r   r   r    append_pass      z_NodeReporter.append_passc                 C  sp   t |dr| dd d S |jd usJ t|jdd }|d ur#|j}nt|j}t|}| d|t|j d S )Nwasxfailskippedz%xfail-marked test passes unexpectedly	reprcrashfailure)ri   rz   longreprgetattrru   r   r%   )rK   r{   r   ru   r   r   r    append_failure   s   

z_NodeReporter.append_failurec                 C  s&   |j d usJ | ddt|j  d S )Nerrorzcollection failure)r   rz   r   r   r   r   r    append_collect_error   s   z"_NodeReporter.append_collect_errorc                 C  s   |  ddt|j d S )Nr   zcollection skipped)rz   r   r   r   r   r   r    append_collect_skipped   r   z$_NodeReporter.append_collect_skippedc                 C  sv   |j d usJ t|j dd }|d ur|j}nt|j }|jdkr'd| d}nd| d}| dt|t|j  d S )Nr   teardownzfailed on teardown with ""zfailed on setup with "r   )r   r   ru   r   whenrz   r%   )rK   r{   r   reasonmsgr   r   r    append_error   s   

z_NodeReporter.append_errorc                 C  s   t |dr&|j}|dr|dd  }t|}tjdd|d}| | d S t|jt	s.J |j\}}}|dr?|dd  }| d	| d
| }tjddt|d}t||_
| | | | d S )Nr   zreason:    r   zpytest.xfail)r,   ru   z	Skipped: 	   :z: zpytest.skip)ri   r   
startswithr%   r[   r\   rP   r)   r   tuplery   r   )rK   r{   xfailreasonr   filenamelineno
skipreasondetailsr   r   r    append_skipped   s$   





z_NodeReporter.append_skippedc                   s$   |    | j   fdd| _ d S )Nc                     s    S r'   r   r   rv   r   r    <lambda>  s    z(_NodeReporter.finalize.<locals>.<lambda>)rt   __dict__clearrK   r   r   r    finalize   s   
z_NodeReporter.finalize)rA   rB   rC   r   r   r&   )rM   rN   r   r&   r8   r   rQ   r   r   r&   r   rV   )r`   r   r   r&   )r   rN   r'   )rO   r   ru   r   rv   rw   r   r&   r{   r   r   r&   )r   r   r   r   r   r   )r{   r   r   r   r   r   r   r&   r   r&   )__name__
__module____qualname__rL   rP   rS   rT   r^   rp   rt   rz   r   r   r   r   r   r   r   r   r   r   r   r   r   r    r@   Y   s&    






	









r@   requestr   fixture_namec                 C  sX   ddl m} | jjtd}|dur(|jdvr*| j|| d|j d dS dS dS )z[Emit a PytestWarning about the given fixture being incompatible with newer xunit revisions.r   )PytestWarningN)r>   legacyz$ is incompatible with junit_family 'z' (use 'legacy' or 'xunit1'))	_pytest.warning_typesr   configstashgetxml_keyrG   rM   warn)r   r   r   rC   r   r   r    !_warn_incompatibility_with_xunit2  s   r   Callable[[str, object], None]c                   s   t  d d fdd	}|S )an  Add extra properties to the calling test.

    User properties become part of the test report and are available to the
    configured reporters, like JUnit XML.

    The fixture is callable with ``name, value``. The value is automatically
    XML-encoded.

    Example::

        def test_function(record_property):
            record_property("example_key", 1)
    record_propertyr8   r   rQ   r   r   r&   c                   s    j j| |f d S r'   )rM   user_propertiesrP   rZ   r   r   r    append_property(  rU   z(record_property.<locals>.append_propertyNr   )r   )r   r   r   r   r    r     s   
r   c                 C  sd   ddl m} | j|d t| d ddd}|}| jjtd}|dur0|	| jj
}|j}|S )zAdd extra xml attributes to the tag for the calling test.

    The fixture is callable with ``name, value``. The value is
    automatically XML-encoded.
    r   )PytestExperimentalApiWarningz/record_xml_attribute is an experimental featurerecord_xml_attributer8   r   rQ   r   r   r&   c                 S  s   d S r'   r   rZ   r   r   r    add_attr_noop>  s   z+record_xml_attribute.<locals>.add_attr_noopNr   )r   r   rM   r   r   r   r   r   r   node_reporterrA   rT   )r   r   r   	attr_funcrC   r   r   r   r    r   .  s   

r   paramvc                 C  s.   d}t |tsd}t|j| t|jddS )zcUsed by record_testsuite_property to check that the given parameter name is of the proper
    type.Tz5{param} parameter needs to be a string, but {g} given)r   gN)r)   r   r+   formatr,   r   )r   r   __tracebackhide__r   r   r   r    _check_record_param_typeK  s
   
r   session)scopec                 C  s0   d}ddd	}| j jtd
}|d
ur|j}|S )a+  Record a new ``<property>`` tag as child of the root ``<testsuite>``.

    This is suitable to writing global information regarding the entire test
    suite, and is compatible with ``xunit2`` JUnit family.

    This is a ``session``-scoped fixture which is called with ``(name, value)``. Example:

    .. code-block:: python

        def test_foo(record_testsuite_property):
            record_testsuite_property("ARCH", "PPC")
            record_testsuite_property("STORAGE_TYPE", "CEPH")

    :param name:
        The property name.
    :param value:
        The property value. Will be converted to a string.

    .. warning::

        Currently this fixture **does not work** with the
        `pytest-xdist <https://github.com/pytest-dev/pytest-xdist>`__ plugin. See
        :issue:`7767` for details.
    Tr8   r   rQ   r   r   r&   c                 S  s   d}t d|  dS )zFNo-op function in case --junit-xml was not passed in the command-line.Tr8   N)r   )r8   rQ   r   r   r   r    record_funcp  s   z.record_testsuite_property.<locals>.record_funcNr   )r   r   r   r   add_global_property)r   r   r   rC   r   r   r    record_testsuite_propertyT  s   
r   parserr   c              
   C  s   |  d}|jdddddtjtddd dd	 |jd
dddd dd | jdddd | jdddd | jddddd | jdddd | jddd d d S )!Nzterminal reportingz
--junitxmlz--junit-xmlstorexmlpathpath)optnamez0Create junit-xml style report file at given path)actiondestmetavarr,   defaulthelpz--junitprefixz--junit-prefixr   z0Prepend prefix to classnames in junit-xml output)r   r   r   r   junit_suite_namez Test suite name for JUnit reportpytest)r   junit_loggingz\Write captured log messages to JUnit report: one of no|log|system-out|system-err|out-err|allr|   junit_log_passing_testsz;Capture log information for passing tests to JUnit report: boolT)r,   r   junit_duration_reportz*Duration time to report: one of total|calltotaljunit_familyz0Emit XML for schema: one of legacy|xunit1|xunit2r?   )getgroup	addoption	functoolspartialr   addini)r   r   r   r   r    pytest_addoption{  sV   


r   r   r   c              
   C  st   | j j}|r6t| ds8| d}t|| j j| d| d| d|| d| jt< | j	| jt  d S d S d S )Nworkerinputr   r   r   r   r   )
optionr   ri   getinir   junitprefixr   r   pluginmanagerregister)r   r   r   r   r   r    pytest_configure  s   

	r  c                 C  s.   | j td }|r| j t= | j| d S d S r'   )r   r   r   r   
unregister)r   rC   r   r   r    pytest_unconfigure  s
   r  address	list[str]c                 C  s^   |  d\}}}|d}|d tjd|d< tdd|d |d< |d  || 7  < |S )N[z::r   rb   z\.py$r}   ra   )	partitionsplitreplacer   SEPr"   r#   )r  r   possible_open_bracketparamsrk   r   r   r    rd     s   
rd   c                   @  s   e Zd Z					d:d;ddZd<ddZd=ddZd>ddZd?ddZd<dd Zd<d!d"Z	d<d#d$Z
d@d'd(ZdAd)d*ZdAd+d,ZdBd/d0ZdCd4d5ZdDd7d8Zd9S )Er   r   r|   r   r>   Tre   rw   
suite_namer   r   report_durationr   r   r   r&   c                 C  s   t jt j|}t jt j|| _|| _|| _|| _	|| _
|| _|| _tg dd| _i | _g | _g | _g | _d| _| jdkrId| _d S d S )N)r   r   r   r   r   r   r>   )osr   
expanduser
expandvarsnormpathabspathlogfilere   r  r   r   r  rG   dictfromkeysstatsnode_reportersnode_reporters_orderedglobal_propertiesopen_reportscnt_double_fail_tests)rK   r  re   r  r   r  rG   r   r   r   r    rL     s&   


zLogXML.__init__r{   r   c                 C  s`   t |d|}t |dd }| j||f}|jD ]\}}||t| q|d ur.|  d S d S NrA   rM   )r   r  popr   rS   r   r   )rK   r{   rA   
workernodereporterpropname	propvaluer   r   r    r     s   zLogXML.finalizeTestReport | strr@   c                 C  sX   t |d|}t |dd }||f}|| jv r| j| S t|| }|| j|< | j| |S r  )r   r  r@   r  rP   )rK   r{   rA   r  ro   r   r   r   r    r     s   



zLogXML.node_reporterro   c                 C  s$   || j v r| j |  d7  < d S d S )Nrc   )r  )rK   ro   r   r   r    rF     s   
zLogXML.add_statsc                 C  s   |  |}|| |S r'   )r   rp   rK   r{   r   r   r   r    _opentestcase  s   

zLogXML._opentestcasec                   sr  d} j r jdkr|  }|  nb jrj jdkrFt ddt ddt fdd| jD d}|rF| | |  j	d7  _	|  } jdkrd|
  | j  | jsc|  n|  n jrw|  }|  |    jdkr|  }|  |   t ddt ddt fd	d| jD d}|r| j| dS dS dS )
a  Handle a setup/call/teardown report, generating the appropriate
        XML tags as necessary.

        Note: due to plugins like xdist, this hook may be called in interlaced
        order with reports from other nodes. For example:

        Usual call order:
            -> setup node1
            -> call node1
            -> teardown node1
            -> setup node2
            -> call node2
            -> teardown node2

        Possible call order in xdist:
            -> setup node1
            -> call node1
            -> setup node2
            -> call node2
            -> teardown node2
            -> teardown node1
        Ncallr   	worker_id
item_indexc                 3  @    | ]}|j  j krt|d dkrt|ddkr|V  qdS r(  Nr'  rA   r   .0repr{   	report_ii
report_widr   r    	<genexpr>8      z2LogXML.pytest_runtest_logreport.<locals>.<genexpr>rc   c                 3  r)  r*  r+  r,  r/  r   r    r2  ]  r3  )r   r   r%  r   failedr   nextr  r   r  r   rP   r   r   r   r   r   update_testcase_durationremove)rK   r{   close_reportr   r   r/  r    pytest_runtest_logreport  s^   



	











	zLogXML.pytest_runtest_logreportc                 C  s8   | j d|jhv r| |}| jt|dd7  _dS dS )zAccumulate total duration for nodeid from given report and update
        the Junit.testcase with the new total if already created.r   rH   rD   N)r  r   r   rH   r   r$  r   r   r    r6  k  s   
zLogXML.update_testcase_durationc                 C  s6   |j s| |}|jr|| d S || d S d S r'   )r   r%  r4  r   r   r$  r   r   r    pytest_collectreportr  s   
zLogXML.pytest_collectreportexcreprr	   c                 C  s0   |  d}|jjddd |ddt| d S )Ninternalr   )r7   r8   r   zinternal error)r   rJ   r-   rz   r   )rK   r;  r   r   r   r    pytest_internalerrorz  s   
zLogXML.pytest_internalerrorc                 C  s   t  | _d S r'   )r   rr   suite_start_timer   r   r   r    pytest_sessionstart  r   zLogXML.pytest_sessionstartc           
      C  s\  t jt j| j}t j|dd t| jddd}t }|| j	 }| j
d | j
d  | j
d  | j
d	  | j }|d
 tjd| jt| j
d	 t| j
d t| j
d t||dt| j	tj  t d	}|  }|d ur{|| | jD ]	}||  q~td}	|	| |tj|	dd W d    d S 1 sw   Y  d S )NT)exist_okwzutf-8)encodingr   r   r   r   z&<?xml version="1.0" encoding="utf-8"?>	testsuiterq   )r8   errorsfailuresr   testsrr   	timestamphostname
testsuitesunicode)r  r   dirnamer  r  makedirsopenr   rr   r>  r  r  writer[   r\   r  r   r   fromtimestampr   utc
astimezone	isoformatplatformrM   _get_global_properties_noderP   r  rt   tostring)
rK   rK  r  suite_stop_timesuite_time_deltanumtests
suite_noder  r   rI  r   r   r    pytest_sessionfinish  sL   





"zLogXML.pytest_sessionfinishterminalreporterr   c                 C  s   | dd| j  d S )Nr   zgenerated xml file: )	write_sepr  )rK   r[  r   r   r    pytest_terminal_summary  r   zLogXML.pytest_terminal_summaryr8   rQ   r   c                 C  s&   d}t d| | j|t|f d S )NTr8   )r   r  rP   r%   )rK   r8   rQ   r   r   r   r    r     s   
zLogXML.add_global_propertyrV   c                 C  rW   rX   )r  r[   r\   rP   r]   r   r   r    rT    r_   z"LogXML._get_global_properties_nodeN)r   r|   r   r>   T)re   rw   r  r   r   r   r  r   r   r   r   r&   r   )r{   r#  r   r@   )ro   r   r   r&   )r{   r   r   r@   )r;  r	   r   r&   r   )r[  r   r   r&   r   r   )r   r   r   rL   r   r   rF   r%  r9  r6  r:  r=  r?  rZ  r]  r   rT  r   r   r   r    r     s(    
!




U




(
)r   r   r   r   r   )r   r   r   r   r   r&   )r   r   r   r   )r   r   r   r   r   r&   )r   r   r   r&   )r   r   r   r&   )r  r   r   r  )5__doc__
__future__r   r   r   r   r  rS  r"   typingr   r   xml.etree.ElementTreeetreeElementTreer[   _pytestr   r   _pytest._code.coder	   r
   _pytest.configr   r   _pytest.config.argparsingr   _pytest.fixturesr   _pytest.reportsr   _pytest.stashr   _pytest.terminalr   r   r   r%   r5   rj   copyr@   r   fixturer   r   r   r   r   r  r  rd   r   r   r   r   r    <module>   s^   	



 
0

	
&
/

