gCEdZddlmZddlZddlZddlZ ddlmZgdZ ejdZ ejdZejdZej Zd Zd Zej&d d ZdZej,dZej,dZGddeZGddeZddZddZGddZdZddiZe dk(rddlZejByy#e $r ddl mZYwxYw)a lxml-based doctest output comparison. Note: normally, you should just import the `lxml.usedoctest` and `lxml.html.usedoctest` modules from within a doctest, instead of this one:: >>> import lxml.usedoctest # for XML output >>> import lxml.html.usedoctest # for HTML output To use this module directly, you must call ``lxmldoctest.install()``, which will cause doctest to use this in all subsequent calls. This changes the way output is checked and comparisons are made for XML or HTML-like content. XML or HTML content is noticed because the example starts with ``<`` (it's HTML if it starts with ```` or include an ``any`` attribute in the tag. An ``any`` tag matches any tag, while the attribute matches any and all attributes. When a match fails, the reformatted example and gotten text is displayed (indented), and a rough diff-like output is given. Anything marked with ``+`` is in the output but wasn't supposed to be, and similarly ``-`` means its in the example but wasn't in the output. You can disable parsing on one line with ``# doctest:+NOPARSE_MARKUP`` )etreeN)escape) PARSE_HTML PARSE_XMLNOPARSE_MARKUPLXMLOutputCheckerLHTMLOutputCheckerinstall temp_installrrrc(|y|jSN)stripvs D/opt/hc_python/lib64/python3.12/site-packages/lxml/doctestcompare.pyrr8sywwyc.tjd|S)N )_norm_whitespace_resubrs rnorm_whitespacer>s  " "3 **rFT)recoverremove_blank_textc6tj|tSr )r fromstring _html_parserhtmls rhtml_fromstringrCs   D, //rz^<[^>]+ (at|object) z[ \t\n][ \t\n]+c~eZdZdZdZdZdZdZdZdZ dZ d Z dd Z dd Z dd Zd ZdZdZdZdZddZy)r) paramimgareabrbasefontinputbasemetalinkcolc"tjSr )rXMLselfs rget_default_parserz$LXMLOutputChecker.get_default_parserPs yyrcJt|dd}||j}|}ntj}|j |||}|s |||||S ||} ||}|j||S#t j $rYywxYw#t j $rYywxYw)N_temp_override_selfF)getattr_temp_call_super_check_output OutputChecker check_output get_parserrXMLSyntaxError compare_docs) r.wantgot optionflagsalt_self super_methodparserwant_docgot_docs rr5zLXMLOutputChecker.check_outputSs4!6=  ==LD(55LsK8dC. . d|H SkG  733 ##  ##  s$A3B 3B B  B"!B"cd}t|zryt|zrt}|St|zrtj }|S|j jjdr'|j jdrt}|S|j|r!|j|r|j}|S)Nzs rr6zLXMLOutputChecker.get_parserhs K '  #$F  $YYF jjl  "--g6))+((1$F %%d+))#.,,.F rct|j}|jdxrtj| S)N<)rrC_repr_research)r.ss rrDz$LXMLOutputChecker._looks_like_markupxs2 GGI S!+ ** ,rc |j|j|jsy|j|j|jdsy|j|j|jdsyd|j vrt |j j}t |j j}||k7ry|D]1}|j|j ||j |dr1y|jdk7s t|rmt|}t|}|s|rS|r|sy|jd}|jd} |j|| sy|s|jdk(r y|rP|rSy)NFTanyz...r) tag_comparetag text_comparetexttailattribsortedkeyslenlistpopr8) r.r9r: want_keysgot_keyskey want_children got_children want_first got_firsts rr8zLXMLOutputChecker.compare_docs}sP#''2  CHHd;  CHHd;  #t{{//12Icjjoo/0HH$ ((S)93::c?ER ! 99 T JM9L<$L *..q1 (,,Q/ ((Y? # 5(@ <rc|xsd}|xsd}|r2t|j}t|j}dtj|z}|j dd}tj ||ryy)Nz^%s$z\.\.\.z.*TF)rrrerreplacerH)r.r9r:rs rrNzLXMLOutputChecker.text_comparesszriR "4(..0D!#&,,.C $'||It, 99T3 rc|dk(ryt|ttfrt|ttfs||k(S|xsd}|xsd}|jdr)|j dd|j ddk(S||k(S)NrKTr_z{...}}) isinstancestrbytesrCsplit)r.r9r:s rrLzLXMLOutputChecker.tag_compares 5=4#u.!#U|43; zriR ??7 #::c?2&#))C.*<< <3; rc |j}|j|||}g}| ||} ||} ||r>tj||||} |r"|j | dj|S| S|tu} d|j| dd|j | dd|j|| | dg} dj| S#tj$r.t j d}|j d|zYwxYw#tj$r/t j d}|j d|zYwxYw) NzIn example: %szIn actual output: %s z Expected:zGot:zDiff:) r9r6rr7sysexc_infoappendr4output_differencejoinr format_doc collect_diff) r.exampler:r;r9r>errorsr?er@valuer diff_partss rrpz#LXMLOutputChecker.output_differencesZ||sK8   4!$< : + >V!33gsK1E e$yy(( (!ooha8oogtQ7'''4C E yy$$/'' 4LLN1% .23 4 '' :LLN1% 4q89 :s"C D >D D>EEcl|sy|j|jvry|js t|ryy)NFT)rM empty_tagsrOrT)r.elrs rhtml_empty_tagz LXMLOutputChecker.html_empty_tags. 66 ( 77c"grc g}t|s|jd|z|j||j|j||j||s_t |j r*|j|j |j |j|j|t |jr*|j|j |j|jddj|S|jd|z|j||j|j||j||s|jdt |j rO|jd|z|j|j |j |jd|D]'}|j|j|||dz)|jd|z|j|j||jdt |jrO|jd|z|j|j |j|jddj|S)Nrrkr_rl) rTro format_tagr|rrO format_textformat_end_tagrPrqrr)r.docrindentprefixpartsr{s rrrzLXMLOutputChecker.format_docs3x LLV $ LL LL- .&&sD1?LL!1!1#((!;< T0056SXX T--chh78 LL 775> ! SZ  V T__S)*""3- LL SXX SZ( T--chh78 T" T__Rvax@A LLV $ LL,,S1 2 LL  ? LLV $ LL))#((3 4 LL wwu~rcD|y|r|j}t|dS)Nr_rj)r html_escape)r.rOrs rrzLXMLOutputChecker.format_texts% < ::rFr>) rer CommentBaserRrQitemsrorrMrq)r.r{attrsnamerws rr~zLXMLOutputChecker.format_tag s b%++ ,!"))//"34KD% LLdD,<,)rerrrM)r.r{s rrz LXMLOutputChecker.format_end_tags$ b%++ ,rc  g}t|st|s|jd|z|j|j|||j||sV|j|j |j |j |j|j |||j|j |j|j|jddj|S|jd|z|j|j|||jdt|j st|j rZ|jd|z|j|j |j |j |jdt|}t|}|s|r|s6|j|j|jd||dzd<|s6|j|j|jd||dzdt|j|j|jd|jd||dz|r|r|jd|z|j|j |||jdt|jst|jrZ|jd|z|j|j |j|j|jddj|S)Nrrkr_rrl+-)rTrocollect_diff_tagr|collect_diff_textrOcollect_diff_end_tagrPrqrrUrrrVrs)r.r9r:rrrrZr[s rrszLXMLOutputChecker.collect_diffs4yS LLV $ LL..tS9 :&&sD1 T33DIIsxxHI T66tSAB LL// 388D E LL 775> ! SZ  T**456 T  uSXX LLV $ LL// 388D E LL T Cy |  T__\-=-=a-@$qRUVW T__]->->q-A4PQSVWX LL**!!!$l&6&6q&94K L|  SZ  T..tS9: T  uSXX LLV $ LL// 388D E LL wwu~rc h|j|j|js|jd|jd}n |j}g}|jdk(xsd|jv}t|jj D]\}}||jvr+|s)|j d|d|j |dd?||jvr!|j|j||d}n|j |d}|j |d|d|sbt|jj D]<\}}||jvr|j d|d|j |dd>|rd |d d j|d }|Sd |z}|S) N (got: )rKrrFrrrFrrr) rLrMrQrRrrorrrq) r.r9r:rMrrKrrwrOs rrz"LXMLOutputChecker.collect_diff_tag@sn#''2$(HHcgg6C''Chh%75DKK#7!#**"2"2"45KD%4;;&s 41A1A%1OPQ4;;&11$++d2CUERD++E59D $566%dkk&7&7&9: e3::% 41A1A%1OPQ ; "CHHUO4C 3,C rc|j|jk7r!|jd|jd}d|zS|j}d|zS)Nrrr)rM)r.r9r:rMs rrz&LXMLOutputChecker.collect_diff_end_tag[sE 88sww $(HHcgg6C}''C}rc|j|||r|sy|j||S|d|d}|j||S)Nr_rr)rNr)r.r9r:rrOs rrz#LXMLOutputChecker.collect_diff_textbsJ   T3 .##C/ /!%s+e,,rN)T)r_)__name__ __module__ __qualname__rzr/r5r6rDr8rNrLrpr|rrrr~rrsrrrrrrrJsa'J4* , :  %@!F$ 5 $L6-rrceZdZdZy)r ctSr )rr-s rr/z%LHTMLOutputChecker.get_default_parserksrN)rrrr/rrrr r jsrr cF|rtt_ytt_y)z Install doctestcompare for all future doctests. If html is true, then by default the HTML parser will be used; otherwise the XML parser is used. N)r doctestr4rrs rr r ns 2 1rc$|rt}nt}t}|jd}|}|j}||_|jdj }|j j }tt_t||||||y)z Use this *inside* a doctest to enable this checker for this doctest only. If html is true, then by default the HTML parser will be used; otherwise the XML parser is used. r.checkN) r r_find_doctest_framef_locals_checker__func__r5rr_RestoreChecker) r del_moduleCheckerframedt_selfchecker old_checker check_funcchecker_check_funcs rr r zs $#  !EnnV$GiG""KG(11J --66GMG[' 2 rc<eZdZdZdZdZdZdZdZdZ dZ y ) rc||_||_|j|j_||j_||_||_||_|j|jyr ) rr call_superr3r1r clone_funcr install_cloneinstall_dt_self)r.rr new_checkerrrrs r__init__z_RestoreChecker.__init__sY " 59__ 2+6 ($$$  rc|jj|_|jj|_|j j|j_yr )r__code__ func_code __globals__ func_globalsrr-s rrz_RestoreChecker.install_clones;11 OO77#'??#;#; rc:|j|j_yr )rrrr-s runinstall_clonez_RestoreChecker.uninstall_clones#'>> rc\|jj|_||j_yr )r_DocTestRunner__record_outcome prev_funcr-s rrz_RestoreChecker.install_dt_selfsDD6: 3rc:|j|j_yr )rrrr-s runinstall_dt_selfz!_RestoreChecker.uninstall_dt_selfs6:nn 3rc|jreddl}|j|j=d|jvr;|jjdd\}}|j|}t ||yyy)Nr.rj)rrmmodulesrsplitdelattr)r.rmpackagemodule package_mods runinstall_modulez _RestoreChecker.uninstall_modulesd ??  DOO,doo%"&//"8"8a"@!kk'2  V,& rc|j|j|j`|j`|j |i|}|j |Sr )rrrr1r3rr)r.argskwresults r__call__z_RestoreChecker.__call__sT   LL , LL 6,,  rc|j |j|i||jS#|jwxYwr )rrr)r.rrs rrz_RestoreChecker.call_supers?  !"4??D/B/    D   s 4AN) rrrrrrrrrrrrrrrrs+ <2;E-!rrcddl}|jd}|r!|j}d|vr|S|j}|r!t d)NrrjBOOMzBCould not find doctest (only use this function *inside* a doctest))rm _getframerf_back LookupError)rmrls rrrsO CMM! E  NN Q;L   L NNrbasicai >>> temp_install() >>> print """stuff""" ... >>> print """""" >>> print """blahblahblah""" # doctest: +NOPARSE_MARKUP, +ELLIPSIS ...foo /> __main__)F)FN)"__doc__lxmlrrmr`rrrr ImportErrorcgi__all__register_optionflagrrrr4rr HTMLParserrrcompilerGrrr r r rr__test__rtestmodrrrrs2#J ** <)W ( ( 6 'G ' ' 4 ,,,-=>%%  + uF 0 2::- . bjj!34^- ^-@ * 2! F,!,!\ N   zGOOq *)*sC.. C<;C<