
    Bhac                    Z   d 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
c 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!d*dZ"d+dZ#dddgidg didZ$e$d   jK                         e$d<    e#e$d   e$d          e$d   e$d<    G d d      Z&	 	 	 	 	 	 d,dZ'e jP                  d-d       Z)e jP                  d-d        Z*d.d!Z+ e jP                  d"#      d-d$       Z,d/d%Z-d0d&Z.d0d'Z/d1d(Z0 G d) d      Z1y)2a  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)CallableN)nodes)timing)ExceptionRepr)ReprFileLocation)Config)filename_arg)Parser)FixtureRequest)
TestReport)StashKey)TerminalReporterLogXMLc                N    dd}d}t        j                  ||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.
    c                V    t        | j                               }|dk  rd|dS d|dS )N   z#x02X04X)ordgroup)matchobjis     [/var/www/html/Telegram-Engagement-Pod-/env/lib/python3.12/site-packages/_pytest/junitxml.pyreplzbin_xml_escape.<locals>.repl0   s6     !9#w<#w<    u    [^	
 -~-퟿-�က0-ჿff])r   zre.Match[str]returnstr)resubr   )argr   illegal_xml_res      r   bin_xml_escaper#   %   s+      	W  66.$C11r   c                    i }| j                         D ]I  \  }}|j                         D ]1  \  }}t        |t              st        t	        |            ||z   ||<   3 K | j                  |       y N)items
isinstancelist	TypeErrortypeupdate)leftrightresultklvlkrvrs          r   merge_familyr3   @   sc    F**,BkkmFBb$'R))bF2J $ 
 	KKr   testcase	classnamename)filelineurl)_base_base_legacyr:   xunit1r;   xunit2c                      e 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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dZddZy) _NodeReporterc                    || _         || _        | j                  j                  | _        | j                  j                  | _        d| _        g | _        g | _        i | _        y )N        )idxml	add_statsfamilyduration
propertiesr   attrs)selfnodeidrC   s      r   __init__z_NodeReporter.__init__W   sL    ++hhoo13')
%'
r   c                    | j                   j                  |j                         | j                  j	                  |       y r%   )rC   rD   tagr   append)rI   nodes     r   rN   z_NodeReporter.appenda   s*    488$

$r   c                b    | j                   j                  t        |      t        |      f       y r%   )rG   rN   r   r#   rI   r6   values      r   add_propertyz_NodeReporter.add_propertye   s"    D	>%+@ABr   c                F    t        |      | j                  t        |      <   y r%   )r#   rH   r   rQ   s      r   add_attributez_NodeReporter.add_attributeh   s     .u 5

3t9r   c                    | j                   rRt        j                  d      }| j                   D ],  \  }}|j                  t        j                  d||             . |S yz9Return a Junit node containing custom properties, if any.rG   propertyr6   rR   N)rG   ETElementrN   rI   rG   r6   rR   s       r   make_properties_nodez"_NodeReporter.make_properties_nodek   sM    ??L1J#e!!"**Zd%"PQ  /r   c                   t        |j                        }| j                  }|d d }| j                  j                  r&|j                  d| j                  j                         dj                  |      t        |d         |j                  d   d}|j                  d   t        |j                  d         |d<   t        |d      r|j                  |d<   || _        | j                  j                  |       | j                  dk(  ry i }| j                  D ]-  }|t        | j                     d	   v s| j                  |   ||<   / || _        y )
Nr   .)r5   r6   r7      r8   r9   r<   r4   )mangle_test_addressrJ   rH   rC   prefixinsertjoinr#   locationr   hasattrr9   r+   rE   families)rI   
testreportnamesexisting_attrs
classnamesrH   
temp_attrskeys           r   record_testreportz_NodeReporter.record_testreportt   s(   #J$5$563BZ
88??a1*-"59-''*!

 q!-
 3 3A 67E&M:u%%>>E%L


.) ;;(" 
::Cht{{+J77"&**S/
3   
r   c                    t        j                  d| j                  | j                  d      }| j	                         }||j                  |       |j                  | j                         |S )Nr4   .3f)time)rZ   r[   rH   rF   r]   rN   extendr   )rI   r4   rG   s      r   to_xmlz_NodeReporter.to_xml   sV    ::j$**dmmC=PR..0
!OOJ'

#r   Nc                t    t        j                  ||      }t        |      |_        | j	                  |       y )N)messagerZ   r[   r#   textrN   )rI   rM   rv   datarO   s        r   _add_simplez_NodeReporter._add_simple   s*    zz#w/"4(	Dr   c                R   | j                   j                  s|j                  ry |j                  }|j                  }|j
                  }| j                   j                  dk(  ry d}| j                   j                  dv r| j                  |d      }| j                   j                  dv r*|| j                  |d      z  }| j                  ||d       d}| j                   j                  dv r*|| j                  |d	      z  }| j                  ||d
       d}|r| j                  ||d       y y )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)rI   reportcontent_outcontent_logcontent_errcontent_alls         r   write_captured_outputz#_NodeReporter.write_captured_output   s   xx))fmm&&mm&&88t#88~-//=MNK88??400>NOOK\BK88??400>NOOK\BK\B r   c                J    dj                  |j                  dd      |dg      S )N
P   -r}   )re   center)rI   contentheaders      r   r   z_NodeReporter._prepare_content   s#    yy&--C0'2>??r   c                p    t        j                  |      }t        |      |_        | j	                  |       y r%   rw   )rI   r   r   jheaderrM   s        r   r   z_NodeReporter._write_content   s(    jj!!'*Cr   c                &    | j                  d       y )Nr   )rD   rI   r   s     r   append_passz_NodeReporter.append_pass   s    x r   c                6   t        |d      r| j                  dd       y |j                  J t        |j                  dd       }||j                  }nt        |j                        }t        |      }| j                  d|t        |j                               y )Nwasxfailskippedz%xfail-marked test passes unexpectedly	reprcrashfailure)rg   rz   longreprgetattrrv   r   r#   )rI   r   r   rv   s       r   append_failurez_NodeReporter.append_failure   s    6:&Y(OP??...18d2I $#++foo.$W-GYV__1EFr   c                l    |j                   J | j                  ddt        |j                                y )Nerrorzcollection failure)r   rz   r   r   s     r   append_collect_errorz"_NodeReporter.append_collect_error   s.    ***"6FOO8LMr   c                P    | j                  ddt        |j                               y )Nr   zcollection skipped)rz   r   r   r   s     r   append_collect_skippedz$_NodeReporter.append_collect_skipped   s    $8#foo:NOr   c                ,   |j                   J t        |j                   dd       }||j                  }nt        |j                         }|j                  dk(  rd| d}nd| d}| j                  dt        |      t        |j                                y )Nr   teardownzfailed on teardown with ""zfailed on setup with "r   )r   r   rv   r   whenrz   r#   )rI   r   r   reasonmsgs        r   append_errorz_NodeReporter.append_error   s    ***-4V__kSW-X	 &&F)F;;*$-fXQ7C*6(!4C."5s6??7KLr   c                   t        |d      rW|j                  }|j                  d      r|dd  }t        |      }t	        j
                  dd|      }| j                  |       y t        |j                  t              sJ |j                  \  }}}|j                  d      r|dd  }| d	| d
| }t	        j
                  ddt        |            }t        |      |_
        | j                  |       | j                  |       y )Nr   zreason:    r   zpytest.xfail)r*   rv   z	Skipped: 	   :z: zpytest.skip)rg   r   
startswithr#   rZ   r[   rN   r'   r   tuplerx   r   )rI   r   xfailreasonr   filenamelineno
skipreasondetailss           r   append_skippedz_NodeReporter.append_skipped   s    6:& //K%%j1)!"o(5KjjUGKK foou555+1??(Hfj$$[1'^
!
!F82j\:Gjj~j7QG *'2GLKK &&v.r   c                n    | j                         | j                  j                          fd| _         y )Nc                      S r%    )ry   s   r   <lambda>z(_NodeReporter.finalize.<locals>.<lambda>  s    dr   )rt   __dict__clear)rI   ry   s    @r   finalizez_NodeReporter.finalize   s'    {{} #r   )rJ   zstr | TestReportrC   r   r   None)rO   
ET.Elementr   r   r6   r   rR   objectr   r   r   zET.Element | None)ri   r   r   r   )r   r   r%   )rM   r   rv   r   ry   
str | Noner   r   r   r   r   r   )r   r   r   r   r   r   )r   r   r   r   r   r   r   r   r   r   )__name__
__module____qualname__rK   rN   rS   rU   r]   ro   rt   rz   r   r   r   r   r   r   r   r   r   r   r   r   r   r?   r?   V   sc    ( C6 <
C.@
!G N
PM/,#r   r?   c                    ddl m} | j                  j                  j	                  t
        d      }|A|j                  dvr2| j                  j                   || d|j                   d             yyy)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_keyrE   rO   warn)requestfixture_namer   rC   s       r   !_warn_incompatibility_with_xunit2r     sl     4
..


"
"7D
1C
3::-AA. DSZZLPlm	
 Br   c                ,     t         d       d f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_propertyc                T    j                   j                  j                  | |f       y r%   )rO   user_propertiesrN   )r6   rR   r   s     r   append_propertyz(record_property.<locals>.append_property%  s    $$++T5M:r   r   )r   )r   r   s   ` r   r   r     s     &g/@A; r   c                2   ddl m} | j                  j                   |d             t	        | d       dd}|}| j
                  j                  j                  t        d      }|1|j                  | 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_attributec                     y r%   r   rY   s     r   add_attr_noopz+record_xml_attribute.<locals>.add_attr_noop;  s    r   Nr   )r   r   rO   r   r   r   r   r   r   node_reporterrJ   rU   )r   r   r   	attr_funcrC   r   s         r   r   r   +  s     CLL$%VW &g/EF I
..


"
"7D
1C
))',,*=*=>!//	r   c                    d}t        |t              s1d}t        |j                  | t	        |      j
                              y)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)paramgN)r'   r   r)   formatr*   r   )r   v__tracebackhide__r   s       r   _check_record_param_typer   H  s@     aE

$q'2B2B
CDD r   session)scopec                    d}dd}| j                   j                  j                  t        d      }||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.
    Tc                     d}t        d|        y)zFNo-op function in case --junit-xml was not passed in the command-line.Tr6   N)r   )r6   rR   r   s      r   record_funcz.record_testsuite_property.<locals>.record_funcm  s      .r   Nr   )r   r   r   r   add_global_property)r   r   r   rC   s       r   record_testsuite_propertyr   Q  sC    4 /
 ..


"
"7D
1C
--r   c                   | j                  d      }|j                  dddddt        j                  t        d      d d	       |j                  d
dddd d       | j                  ddd       | j                  ddd       | j                  dddd       | j                  ddd       | j                  ddd        y )!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)parserr   s     r   pytest_addoptionr  x  s    OO01E	OO|\B?  	 
OO?   MM>   MM	:	   MM!E	   MM4  
 MM:  r   c                   | j                   j                  }|rt        | d      s| j                  d      }t	        || j                   j
                  | j                  d      | j                  d      | j                  d      || j                  d            | j                  t        <   | j                  j                  | j                  t                  y y y )Nworkerinputr  r   r  r  r  )
optionr   rg   getinir   junitprefixr   r   pluginmanagerregister)r   r   r  s      r   pytest_configurer    s    mm##Gwv}5}}^4 &MM%%MM,-MM/*MM12MM34!
W 	%%fll7&;< 6wr   c                    | j                   j                  t        d       }|r-| j                   t        = | j                  j	                  |       y y r%   )r   r   r   r  
unregister)r   rC   s     r   pytest_unconfigurer    s@    
,,

7D
)C
LL!'', r   c                    | j                  d      \  }}}|j                  d      }|d   j                  t        j                  d      |d<   t        j                  dd|d         |d<   |dxx   ||z   z  cc<   |S )N[z::r   r`   z\.py$r}   r_   )	partitionsplitreplacer   SEPr   r    )addressr   possible_open_bracketparamsrj   s        r   rb   rb     sy    *1*;*;C*@'D
JJtEQx		3/E!HvvhE!H-E!H	"I&//ILr   c                      e Zd Z	 	 	 	 	 d	 	 	 	 	 	 	 	 	 	 	 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d	Zdd
ZddZddZddZddZy)r   c                    t         j                  j                  t         j                  j                  |            }t         j                  j	                  t         j                  j                  |            | _        || _        || _        || _	        || _
        || _        || _        t        j                  g dd      | _        i | _        g | _        g | _        g | _        d| _        | j                  dk(  rd| _        y y )N)r   r   r   r   r   r   r<   )osr   
expanduser
expandvarsnormpathabspathlogfilerc   
suite_namer   r   report_durationrE   dictfromkeysstatsnode_reportersnode_reporters_orderedglobal_propertiesopen_reportscnt_double_fail_tests)rI   r)  rc   r*  r   r+  rE   r   s           r   rK   zLogXML.__init__  s     ''$$RWW%7%7%@Aww''(@A$!2.%)]]5q&

 UW;=#8: /1%&" ;;(""DK #r   c                    t        |d|      }t        |dd       }| j                  j                  ||f      }|j                  D ]   \  }}|j	                  |t        |             " ||j                          y y NrJ   rO   )r   r/  popr   rS   r   r   )rI   r   rJ   
workernodereporterpropname	propvalues          r   r   zLogXML.finalize  s{    62VVT2
&&**FJ+?@#)#9#9Hi!!(C	N; $:   r   c                    t        |d|      }t        |dd       }||f}|| j                  v r| j                  |   S t        ||       }|| j                  |<   | j                  j	                  |       |S r5  )r   r/  r?   r0  rN   )rI   r   rJ   r7  rn   r8  s         r   r   zLogXML.node_reporter  s|    #*68V#DVVT2
j $%%%&&s++ .#+C ##**84r   c                P    || j                   v r| j                   |xx   dz  cc<   y y )Nra   )r.  )rI   rn   s     r   rD   zLogXML.add_stats
  s%    $**JJsOq O r   c                J    | j                  |      }|j                  |       |S r%   )r   ro   rI   r   r8  s      r   _opentestcasezLogXML._opentestcase  s%    %%f-""6*r   c                8   d}j                   r4j                  dk(  rL| j                        }|j                         n(j                  rj                  dk(  rct        dd      t        dd      t        fd| j                  D        d      }|r&| j                  |       | xj                  dz  c_	        | j                        }j                  dk(  rJ|j                         | j                  j                         | j                  sR|j                         n@|j                         n.j                  r"| j                        }|j!                         | j#                         j                  dk(  r| j                        }|j                         | j                         t        dd      t        dd      t        fd| j                  D        d      }|r| j                  j%                  |       yyy)	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     K   | ]?  }|j                   j                   k(  r$t        |d d      k(  rt        |dd      k(  r| A ywrC  NrB  rJ   r   .0repr   	report_ii
report_wids     r   	<genexpr>z2LogXML.pytest_runtest_logreport.<locals>.<genexpr>5  sK      #4CJJ&--7 '\4 @I M '[$ ?: M #4   AAra   c              3     K   | ]?  }|j                   j                   k(  r$t        |d d      k(  rt        |dd      k(  r| A ywrE  rF  rG  s     r   rL  z2LogXML.pytest_runtest_logreport.<locals>.<genexpr>Z  sK      0

fmm3#Ct<	I#Cd;zI 0rM  )r   r   r?  r   failedr   nextr2  r   r3  r   rN   r   r   r   r   r   update_testcase_durationremove)rI   r   close_reportr8  rJ  rK  s    `  @@r   pytest_runtest_logreportzLogXML.pytest_runtest_logreport  s   . =={{f$--f5$$V,]]{{j($V[$?
#FL$?	##'#4#4     MM,/..!3.))&1H{{f$''/!!((0--226:%%f-^^))&1H##F+%%f-;;*$))&1H**62MM&! d;Jd;I#00 L !!((6 ' %r   c                    | j                   d|j                  hv r2| j                  |      }|xj                  t	        |dd      z  c_        yy)zAccumulate total duration for nodeid from given report and update
        the Junit.testcase with the new total if already created.r  rF   rA   N)r+  r   r   rF   r   r>  s      r   rQ  zLogXML.update_testcase_durationh  sJ     GV[[#99))&1HS!AA :r   c                    |j                   sA| j                  |      }|j                  r|j                  |       y |j	                  |       y y r%   )r   r?  rO  r   r   r>  s      r   pytest_collectreportzLogXML.pytest_collectreporto  sA    }}))&1H}}--f5//7 r   c                    | j                  d      }|j                  j                  dd       |j                  ddt	        |             y )Ninternalr   )r5   r6   r   zinternal error)r   rH   r+   rz   r   )rI   excreprr8  s      r   pytest_internalerrorzLogXML.pytest_internalerrorw  s@    %%j1zBW&6GEr   c                6    t        j                         | _        y r%   )r   Instantsuite_start)rI   s    r   pytest_sessionstartzLogXML.pytest_sessionstart|  s    !>>+r   c                   t         j                  j                  t         j                  j                  | j                              }t        j
                  |d       t        | j                  dd      5 }| j                  j                         }| j                  d   | j                  d   z   | j                  d   z   | j                  d	   z   | j                  z
  }|j                  d
       t        j                  d| j                  t        | j                  d	         t        | j                  d         t        | j                  d         t        |      |j                   d| j                  j#                         j%                         j'                         t)        j*                         	      }| j-                         }||j/                  |       | j0                  D ]!  }|j/                  |j3                                # t        j                  d      }|j5                  dd       |j/                  |       |j                  t        j6                  |d             d d d        y # 1 sw Y   y xY w)NT)exist_okwzutf-8)encodingr   r   r   r   z&<?xml version="1.0" encoding="utf-8"?>	testsuiterq   )r6   errorsfailuresr   testsrr   	timestamphostname
testsuitesr6   zpytest testsunicode)r$  r   dirnamer(  r)  makedirsopenr^  elapsedr.  r3  writerZ   r[   r*  r   secondsas_utc
astimezone	isoformatplatformrO   _get_global_properties_noderN   r0  rt   settostring)	rI   rl  r)  rF   numtests
suite_noder1  r   rj  s	            r   pytest_sessionfinishzLogXML.pytest_sessionfinish  s   ''//"''//$,,"?@
Gd+$,,g6'''//1H 

8$**Y'(**Y'( **W%& ,,	-  MMBC__4::g./TZZ	23DJJy12(m ((-**113>>@JJL!
J !% @ @ B ,!!"34!%!<!<!!-"6"6"89 "=L1JNN6>2j)MM"++j9EF? 766s   6G.I--I6c                B    |j                  dd| j                          y )Nr   zgenerated xml file: )	write_sepr)  )rI   terminalreporters     r   pytest_terminal_summaryzLogXML.pytest_terminal_summary  s    ""3*>t||n(MNr   c                l    d}t        d|       | j                  j                  |t        |      f       y )NTr6   )r   r1  rN   r#   )rI   r6   rR   r   s       r   r   zLogXML.add_global_property  s0      .%%t^E-B&CDr   c                    | j                   rRt        j                  d      }| j                   D ],  \  }}|j                  t        j                  d||             . |S yrW   )r1  rZ   r[   rN   r\   s       r   rv  z"LogXML._get_global_properties_node  sQ    !!L1J#55e!!"**Zd%"PQ  6r   N)r   r|   r  r<   T)rc   r   r*  r   r   r   r+  r   r   r  r   r   r   )r   zTestReport | strr   r?   )rn   r   r   r   )r   r   r   r?   )rZ  r   r   r   r   )r~  r   r   r   r   r   )r   r   r   rK   r   r   rD   r?  rT  rQ  rW  r[  r_  r{  r  r   rv  r   r   r   r   r     s    
 #&"&# # 	#
 # #  # 
#B
 $!
S7jB8F
,$GLOE
r   )r!   r   r   r   r   )r   r   r   r   r   r   )r   r   r   zCallable[[str, object], None])r   r   r   r   r   r   )r  r   r   r   )r   r	   r   r   )r  r   r   z	list[str])2__doc__
__future__r   collections.abcr   r	  r$  ru  r   xml.etree.ElementTreeetreeElementTreerZ   _pytestr   r   _pytest._code.coder   r   _pytest.configr	   r
   _pytest.config.argparsingr   _pytest.fixturesr   _pytest.reportsr   _pytest.stashr   _pytest.terminalr   r   r   r#   r3   rh   copyr?   r   fixturer   r   r   r   r  r  r  rb   r   r   r   r   <module>r     sb   # $  	  	 " "   , / ! ' , + & " -  (8

26 ;/0!89
 g&++-  Xh.!9 : g& l# l#^

+.
	
  ,  8E i # !#L,^="-j jr   