o 3aL!@svdZddlmZddlmZedZddZGdddZGd d d eZGd d d e Z Gd ddeZ ddZ dS)zCompare two HTML documents.) HTMLParser)_lazy_re_compilez [\t\n\f\r ]+cCs td|S)N )ASCII_WHITESPACEsub)stringr2/usr/lib/python3/dist-packages/django/test/html.pynormalize_whitespace s r c@sfeZdZddZddZddZddZd d Zdd d ZddZ ddZ ddZ ddZ ddZ dS)ElementcCs||_t||_g|_dSN)namesorted attributeschildren)selfr rrrr __init__s  zElement.__init__cCst|tr*t|}|jr)t|jdtr)|jd|7<t|jd|jd<dSn|jrAt|jdtrA|jdrA|j|rK|j|dSdSN) isinstancestrr risspacepopappendrelementrrr rs  zElement.appendcsZfdd|jt|jD]\}}t|tr!||j|<qt|dr*|qdS)Ncs>|rt|dtr|d|d<|ds||}|Sr)rrrstriprrrstrip_last_elementrr r(s z-Element.finalize..rstrip_last_elementfinalize)r enumeraterrstriphasattrr )richildrrr r 's    zElement.finalizecCst|dr |j|jkr dSt|jt|jkrdS|j|jkrNtt|jD]'}|j|\}}|j|\}}|dur<|}|durB|}||ksJ||krMdSq&|j|jkS)Nr F)r#r lenrranger)rrr$attrvalue other_attr other_valuerrr __eq__7s   zElement.__eq__cCst|jg|jRSr )hashr rrrrr __hash__KszElement.__hash__TcCst|ts ||kr dSt|tr|j|jkrdSd}d}|jD]T}t|tr=t|tr<|r5|||7}q||vr<dSq||j||d7}|sN|rN|St|trs|jrs|j|}||krq|d7}|t|jkrp|d7}d}qd}q|S)Nrcount)rr RootElementrr2_countr&)rrr2r$elem_child_idxr% elem_childrrr r4Ns8    zElement._countcCs|j|dddkS)NFr1rr4rrrr __contains__uzElement.__contains__cCs|j|ddS)NTr1r7rrrr r2xz Element.countcCs |j|Sr r)rkeyrrr __getitem__{s zElement.__getitem__cCsd|j}|jD]\}}|r|d||f7}q|d|7}q|jr;|d7}|ddd|jD7}|d|j7}|S|d 7}|S) Nz<%sz %s="%s"z %sz> cs|]}t|VqdSr r.0crrr z"Element.__str__..z >)r rrjoin)routputr;r)rrr __str__~s zElement.__str__cCst|Sr r?r.rrr __repr__szElement.__repr__N)T)__name__ __module__ __qualname__rrr r,r/r4r8r2r<rHrIrrrr r s ' r cs$eZdZfddZddZZS)r3cstdddS)Nr)superrr. __class__rr rr9zRootElement.__init__cCsddd|jDS)Nr=csr>r r?r@rrr rCrDz&RootElement.__str__..)rFrr.rrr rHszRootElement.__str__)rJrKrLrrH __classcell__rrrNr r3s r3c@s eZdZdS)HTMLParseErrorN)rJrKrLrrrr rQsrQcsbeZdZhdZfddZddZdddZed d Zd d Z d dZ ddZ ddZ Z S)Parser>brhrcolimgwbrareabaselinkmetaembedframeinputparamtracksourcespacercs"tt|_g|_i|_dSr )rMrr3root open_tagselement_positionsr.rNrr rs  zParser.__init__cCst||r )rQgetpos)rmsgrrr errorr:z Parser.errorNcCs@|s |r |j|}|dur|}t|dr|j|jf}d|S)NlinenozLine %d, Column %d)rerfr#rioffset)rpositionrrrr format_positions   zParser.format_positioncCs|jr|jdS|jSr)rdrcr.rrr currents zParser.currentcCs(|||||jvr||dSdSr )handle_starttagSELF_CLOSING_TAGS handle_endtag)rtagattrsrrr handle_startendtags  zParser.handle_startendtagcCsLdd|D}t||}|j|||jvr|j|||j|<dS)Nc SsBg|]\}}|dkr|dtddt|Dfn||fqS)classrcss|]}|r|VqdSr r)rAr)rrr rCrDz4Parser.handle_starttag...)rFrrsplit)rAr r)rrr s "z*Parser.handle_starttag..)r rmrrordrfre)rrqrrrrrr rns    zParser.handle_starttagcCsh|js|d||f|j}|j|kr2|js&|d||f|j}|j|ksdSdS)NzUnexpected end tag `%s` (%s))rdrhrlrr )rrqrrrr rps   zParser.handle_endtagcCs|j|dSr )rmr)rdatarrr handle_dataszParser.handle_data)NN)rJrKrLrorrhrlpropertyrmrsrnrprxrPrrrNr rRs    rRcCsRt}||||j}|t|jdkr't|jdts'|jd}|S)z Take a string that contains HTML and turn it into a Python object structure that can be easily compared against other HTML on semantic equivalence. Syntactical differences like which quotation is used on arguments will be ignored. r0r) rRfeedclosercr r&rrr)htmlparserdocumentrrr parse_htmls  rN) __doc__ html.parserrdjango.utils.regex_helperrrr r r3 ExceptionrQrRrrrrr s   E