PNG  IHDRX cHRMz&u0`:pQ<bKGD pHYsodtIME MeqIDATxw]Wug^Qd˶ 6`!N:!@xI~)%7%@Bh&`lnjVF29gΨ4E$|>cɚ{gk= %,a KX%,a KX%,a KX%,a KX%,a KX%,a KX%, b` ǟzeאfp]<!SJmɤY޲ڿ,%c ~ع9VH.!Ͳz&QynֺTkRR.BLHi٪:l;@(!MԴ=žI,:o&N'Kù\vRmJ雵֫AWic H@" !: Cé||]k-Ha oݜ:y F())u]aG7*JV@J415p=sZH!=!DRʯvɱh~V\}v/GKY$n]"X"}t@ xS76^[bw4dsce)2dU0 CkMa-U5tvLƀ~mlMwfGE/-]7XAƟ`׮g ewxwC4\[~7@O-Q( a*XGƒ{ ՟}$_y3tĐƤatgvێi|K=uVyrŲlLӪuܿzwk$m87k( `múcE)"@rK( z4$D; 2kW=Xb$V[Ru819קR~qloѱDyįݎ*mxw]y5e4K@ЃI0A D@"BDk_)N\8͜9dz"fK0zɿvM /.:2O{ Nb=M=7>??Zuo32 DLD@D| &+֎C #B8ַ`bOb $D#ͮҪtx]%`ES`Ru[=¾!@Od37LJ0!OIR4m]GZRJu$‡c=%~s@6SKy?CeIh:[vR@Lh | (BhAMy=݃  G"'wzn޺~8ԽSh ~T*A:xR[ܹ?X[uKL_=fDȊ؂p0}7=D$Ekq!/t.*2ʼnDbŞ}DijYaȲ(""6HA;:LzxQ‘(SQQ}*PL*fc\s `/d'QXW, e`#kPGZuŞuO{{wm[&NBTiiI0bukcA9<4@SӊH*؎4U/'2U5.(9JuDfrޱtycU%j(:RUbArLֺN)udA':uGQN"-"Is.*+k@ `Ojs@yU/ H:l;@yyTn}_yw!VkRJ4P)~y#)r,D =ě"Q]ci'%HI4ZL0"MJy 8A{ aN<8D"1#IJi >XjX֔#@>-{vN!8tRݻ^)N_╗FJEk]CT՟ YP:_|H1@ CBk]yKYp|og?*dGvzنzӴzjֺNkC~AbZƷ`.H)=!QͷVTT(| u78y֮}|[8-Vjp%2JPk[}ԉaH8Wpqhwr:vWª<}l77_~{s۴V+RCģ%WRZ\AqHifɤL36: #F:p]Bq/z{0CU6ݳEv_^k7'>sq*+kH%a`0ԣisqにtү04gVgW΂iJiS'3w.w}l6MC2uԯ|>JF5`fV5m`Y**Db1FKNttu]4ccsQNnex/87+}xaUW9y>ͯ骵G{䩓Գ3+vU}~jJ.NFRD7<aJDB1#ҳgSb,+CS?/ VG J?|?,2#M9}B)MiE+G`-wo߫V`fio(}S^4e~V4bHOYb"b#E)dda:'?}׮4繏`{7Z"uny-?ǹ;0MKx{:_pÚmFמ:F " .LFQLG)Q8qN q¯¯3wOvxDb\. BKD9_NN &L:4D{mm o^tֽ:q!ƥ}K+<"m78N< ywsard5+вz~mnG)=}lYݧNj'QJS{S :UYS-952?&O-:W}(!6Mk4+>A>j+i|<<|;ر^߉=HE|V#F)Emm#}/"y GII웻Jі94+v뾧xu~5C95~ūH>c@덉pʃ1/4-A2G%7>m;–Y,cyyaln" ?ƻ!ʪ<{~h~i y.zZB̃/,雋SiC/JFMmBH&&FAbϓO^tubbb_hZ{_QZ-sύodFgO(6]TJA˯#`۶ɟ( %$&+V'~hiYy>922 Wp74Zkq+Ovn錄c>8~GqܲcWꂎz@"1A.}T)uiW4="jJ2W7mU/N0gcqܗOO}?9/wìXžΏ0 >֩(V^Rh32!Hj5`;O28؇2#ݕf3 ?sJd8NJ@7O0 b־?lldщ̡&|9C.8RTWwxWy46ah嘦mh٤&l zCy!PY?: CJyв]dm4ǜҐR޻RլhX{FƯanшQI@x' ao(kUUuxW_Ñ줮[w8 FRJ(8˼)_mQ _!RJhm=!cVmm ?sFOnll6Qk}alY}; "baӌ~M0w,Ggw2W:G/k2%R,_=u`WU R.9T"v,<\Ik޽/2110Ӿxc0gyC&Ny޽JҢrV6N ``یeA16"J³+Rj*;BϜkZPJaÍ<Jyw:NP8/D$ 011z֊Ⱳ3ι֘k1V_"h!JPIΣ'ɜ* aEAd:ݺ>y<}Lp&PlRfTb1]o .2EW\ͮ]38؋rTJsǏP@芎sF\> P^+dYJLbJ C-xϐn> ι$nj,;Ǖa FU *择|h ~izť3ᤓ`K'-f tL7JK+vf2)V'-sFuB4i+m+@My=O҈0"|Yxoj,3]:cо3 $#uŘ%Y"y죯LebqtҢVzq¼X)~>4L׶m~[1_k?kxֺQ`\ |ٛY4Ѯr!)N9{56(iNq}O()Em]=F&u?$HypWUeB\k]JɩSع9 Zqg4ZĊo oMcjZBU]B\TUd34ݝ~:7ڶSUsB0Z3srx 7`:5xcx !qZA!;%͚7&P H<WL!džOb5kF)xor^aujƍ7 Ǡ8/p^(L>ὴ-B,{ۇWzֺ^k]3\EE@7>lYBȝR.oHnXO/}sB|.i@ɥDB4tcm,@ӣgdtJ!lH$_vN166L__'Z)y&kH;:,Y7=J 9cG) V\hjiE;gya~%ks_nC~Er er)muuMg2;֫R)Md) ,¶ 2-wr#F7<-BBn~_(o=KO㭇[Xv eN_SMgSҐ BS헃D%g_N:/pe -wkG*9yYSZS.9cREL !k}<4_Xs#FmҶ:7R$i,fi!~' # !6/S6y@kZkZcX)%5V4P]VGYq%H1!;e1MV<!ϐHO021Dp= HMs~~a)ަu7G^];git!Frl]H/L$=AeUvZE4P\.,xi {-~p?2b#amXAHq)MWǾI_r`S Hz&|{ +ʖ_= (YS(_g0a03M`I&'9vl?MM+m~}*xT۲(fY*V4x@29s{DaY"toGNTO+xCAO~4Ϳ;p`Ѫ:>Ҵ7K 3}+0 387x\)a"/E>qpWB=1 ¨"MP(\xp߫́A3+J] n[ʼnӼaTbZUWb={~2ooKױӰp(CS\S筐R*JغV&&"FA}J>G֐p1ٸbk7 ŘH$JoN <8s^yk_[;gy-;߉DV{c B yce% aJhDȶ 2IdйIB/^n0tNtџdcKj4϶v~- CBcgqx9= PJ) dMsjpYB] GD4RDWX +h{y`,3ꊕ$`zj*N^TP4L:Iz9~6s) Ga:?y*J~?OrMwP\](21sZUD ?ܟQ5Q%ggW6QdO+\@ ̪X'GxN @'4=ˋ+*VwN ne_|(/BDfj5(Dq<*tNt1х!MV.C0 32b#?n0pzj#!38}޴o1KovCJ`8ŗ_"]] rDUy޲@ Ȗ-;xџ'^Y`zEd?0„ DAL18IS]VGq\4o !swV7ˣι%4FѮ~}6)OgS[~Q vcYbL!wG3 7띸*E Pql8=jT\꘿I(z<[6OrR8ºC~ډ]=rNl[g|v TMTղb-o}OrP^Q]<98S¤!k)G(Vkwyqyr޽Nv`N/e p/~NAOk \I:G6]4+K;j$R:Mi #*[AȚT,ʰ,;N{HZTGMoּy) ]%dHء9Պ䠬|<45,\=[bƟ8QXeB3- &dҩ^{>/86bXmZ]]yޚN[(WAHL$YAgDKp=5GHjU&99v簪C0vygln*P)9^͞}lMuiH!̍#DoRBn9l@ xA/_v=ȺT{7Yt2N"4!YN`ae >Q<XMydEB`VU}u]嫇.%e^ánE87Mu\t`cP=AD/G)sI"@MP;)]%fH9'FNsj1pVhY&9=0pfuJ&gޤx+k:!r˭wkl03׼Ku C &ѓYt{.O.zҏ z}/tf_wEp2gvX)GN#I ݭ߽v/ .& и(ZF{e"=V!{zW`, ]+LGz"(UJp|j( #V4, 8B 0 9OkRrlɱl94)'VH9=9W|>PS['G(*I1==C<5"Pg+x'K5EMd؞Af8lG ?D FtoB[je?{k3zQ vZ;%Ɠ,]E>KZ+T/ EJxOZ1i #T<@ I}q9/t'zi(EMqw`mYkU6;[t4DPeckeM;H}_g pMww}k6#H㶏+b8雡Sxp)&C $@'b,fPߑt$RbJ'vznuS ~8='72_`{q纶|Q)Xk}cPz9p7O:'|G~8wx(a 0QCko|0ASD>Ip=4Q, d|F8RcU"/KM opKle M3#i0c%<7׿p&pZq[TR"BpqauIp$ 8~Ĩ!8Սx\ւdT>>Z40ks7 z2IQ}ItԀ<-%S⍤};zIb$I 5K}Q͙D8UguWE$Jh )cu4N tZl+[]M4k8֦Zeq֮M7uIqG 1==tLtR,ƜSrHYt&QP윯Lg' I,3@P'}'R˪e/%-Auv·ñ\> vDJzlӾNv5:|K/Jb6KI9)Zh*ZAi`?S {aiVDԲuy5W7pWeQJk֤#5&V<̺@/GH?^τZL|IJNvI:'P=Ϛt"¨=cud S Q.Ki0 !cJy;LJR;G{BJy޺[^8fK6)=yʊ+(k|&xQ2`L?Ȓ2@Mf 0C`6-%pKpm')c$׻K5[J*U[/#hH!6acB JA _|uMvDyk y)6OPYjœ50VT K}cǻP[ $:]4MEA.y)|B)cf-A?(e|lɉ#P9V)[9t.EiQPDѠ3ϴ;E:+Օ t ȥ~|_N2,ZJLt4! %ա]u {+=p.GhNcŞQI?Nd'yeh n7zi1DB)1S | S#ًZs2|Ɛy$F SxeX{7Vl.Src3E℃Q>b6G ўYCmtկ~=K0f(=LrAS GN'ɹ9<\!a`)֕y[uՍ[09` 9 +57ts6}b4{oqd+J5fa/,97J#6yν99mRWxJyѡyu_TJc`~W>l^q#Ts#2"nD1%fS)FU w{ܯ R{ ˎ󅃏џDsZSQS;LV;7 Od1&1n$ N /.q3~eNɪ]E#oM~}v֯FڦwyZ=<<>Xo稯lfMFV6p02|*=tV!c~]fa5Y^Q_WN|Vs 0ҘދU97OI'N2'8N֭fgg-}V%y]U4 峧p*91#9U kCac_AFңĪy뚇Y_AiuYyTTYЗ-(!JFLt›17uTozc. S;7A&&<ԋ5y;Ro+:' *eYJkWR[@F %SHWP 72k4 qLd'J "zB6{AC0ƁA6U.'F3:Ȅ(9ΜL;D]m8ڥ9}dU "v!;*13Rg^fJyShyy5auA?ɩGHRjo^]׽S)Fm\toy 4WQS@mE#%5ʈfFYDX ~D5Ϡ9tE9So_aU4?Ѽm%&c{n>.KW1Tlb}:j uGi(JgcYj0qn+>) %\!4{LaJso d||u//P_y7iRJ߬nHOy) l+@$($VFIQ9%EeKʈU. ia&FY̒mZ=)+qqoQn >L!qCiDB;Y<%} OgBxB!ØuG)WG9y(Ą{_yesuZmZZey'Wg#C~1Cev@0D $a@˲(.._GimA:uyw֬%;@!JkQVM_Ow:P.s\)ot- ˹"`B,e CRtaEUP<0'}r3[>?G8xU~Nqu;Wm8\RIkբ^5@k+5(By'L&'gBJ3ݶ!/㮻w҅ yqPWUg<e"Qy*167΃sJ\oz]T*UQ<\FԎ`HaNmڜ6DysCask8wP8y9``GJ9lF\G g's Nn͵MLN֪u$| /|7=]O)6s !ĴAKh]q_ap $HH'\1jB^s\|- W1:=6lJBqjY^LsPk""`]w)󭃈,(HC ?䔨Y$Sʣ{4Z+0NvQkhol6C.婧/u]FwiVjZka&%6\F*Ny#8O,22+|Db~d ~Çwc N:FuuCe&oZ(l;@ee-+Wn`44AMK➝2BRՈt7g*1gph9N) *"TF*R(#'88pm=}X]u[i7bEc|\~EMn}P瘊J)K.0i1M6=7'_\kaZ(Th{K*GJyytw"IO-PWJk)..axӝ47"89Cc7ĐBiZx 7m!fy|ϿF9CbȩV 9V-՛^pV̌ɄS#Bv4-@]Vxt-Z, &ֺ*diؠ2^VXbs֔Ìl.jQ]Y[47gj=幽ex)A0ip׳ W2[ᎇhuE^~q흙L} #-b۸oFJ_QP3r6jr+"nfzRJTUqoaۍ /$d8Mx'ݓ= OՃ| )$2mcM*cЙj}f };n YG w0Ia!1Q.oYfr]DyISaP}"dIӗթO67jqR ҊƐƈaɤGG|h;t]䗖oSv|iZqX)oalv;۩meEJ\!8=$4QU4Xo&VEĊ YS^E#d,yX_> ۘ-e\ "Wa6uLĜZi`aD9.% w~mB(02G[6y.773a7 /=o7D)$Z 66 $bY^\CuP. (x'"J60׿Y:Oi;F{w佩b+\Yi`TDWa~|VH)8q/=9!g߆2Y)?ND)%?Ǐ`k/sn:;O299yB=a[Ng 3˲N}vLNy;*?x?~L&=xyӴ~}q{qE*IQ^^ͧvü{Huu=R|>JyUlZV, B~/YF!Y\u_ݼF{_C)LD]m {H 0ihhadd nUkf3oٺCvE\)QJi+֥@tDJkB$1!Đr0XQ|q?d2) Ӣ_}qv-< FŊ߫%roppVBwü~JidY4:}L6M7f٬F "?71<2#?Jyy4뷢<_a7_=Q E=S1И/9{+93֮E{ǂw{))?maÆm(uLE#lïZ  ~d];+]h j?!|$F}*"4(v'8s<ŏUkm7^7no1w2ؗ}TrͿEk>p'8OB7d7R(A 9.*Mi^ͳ; eeUwS+C)uO@ =Sy]` }l8^ZzRXj[^iUɺ$tj))<sbDJfg=Pk_{xaKo1:-uyG0M ԃ\0Lvuy'ȱc2Ji AdyVgVh!{]/&}}ċJ#%d !+87<;qN޼Nفl|1N:8ya  8}k¾+-$4FiZYÔXk*I&'@iI99)HSh4+2G:tGhS^繿 Kتm0 вDk}֚+QT4;sC}rՅE,8CX-e~>G&'9xpW,%Fh,Ry56Y–hW-(v_,? ; qrBk4-V7HQ;ˇ^Gv1JVV%,ik;D_W!))+BoS4QsTM;gt+ndS-~:11Sgv!0qRVh!"Ȋ(̦Yl.]PQWgٳE'`%W1{ndΗBk|Ž7ʒR~,lnoa&:ü$ 3<a[CBݮwt"o\ePJ=Hz"_c^Z.#ˆ*x z̝grY]tdkP*:97YľXyBkD4N.C_[;F9`8& !AMO c `@BA& Ost\-\NX+Xp < !bj3C&QL+*&kAQ=04}cC!9~820G'PC9xa!w&bo_1 Sw"ܱ V )Yl3+ס2KoXOx]"`^WOy :3GO0g;%Yv㐫(R/r (s } u B &FeYZh0y> =2<Ϟc/ -u= c&׭,.0"g"7 6T!vl#sc>{u/Oh Bᾈ)۴74]x7 gMӒ"d]U)}" v4co[ ɡs 5Gg=XR14?5A}D "b{0$L .\4y{_fe:kVS\\O]c^W52LSBDM! C3Dhr̦RtArx4&agaN3Cf<Ԉp4~ B'"1@.b_/xQ} _߃҉/gٓ2Qkqp0շpZ2fԫYz< 4L.Cyυι1t@鎫Fe sYfsF}^ V}N<_`p)alٶ "(XEAVZ<)2},:Ir*#m_YӼ R%a||EƼIJ,,+f"96r/}0jE/)s)cjW#w'Sʯ5<66lj$a~3Kʛy 2:cZ:Yh))+a߭K::N,Q F'qB]={.]h85C9cr=}*rk?vwV렵ٸW Rs%}rNAkDv|uFLBkWY YkX מ|)1!$#3%y?pF<@<Rr0}: }\J [5FRxY<9"SQdE(Q*Qʻ)q1E0B_O24[U'],lOb ]~WjHޏTQ5Syu wq)xnw8~)c 쫬gٲߠ H% k5dƝk> kEj,0% b"vi2Wس_CuK)K{n|>t{P1򨾜j>'kEkƗBg*H%'_aY6Bn!TL&ɌOb{c`'d^{t\i^[uɐ[}q0lM˕G:‚4kb祔c^:?bpg… +37stH:0}en6x˟%/<]BL&* 5&fK9Mq)/iyqtA%kUe[ڛKN]Ě^,"`/ s[EQQm?|XJ߅92m]G.E΃ח U*Cn.j_)Tѧj̿30ڇ!A0=͜ar I3$C^-9#|pk!)?7.x9 @OO;WƝZBFU keZ75F6Tc6"ZȚs2y/1 ʵ:u4xa`C>6Rb/Yм)^=+~uRd`/|_8xbB0?Ft||Z\##|K 0>>zxv8۴吅q 8ĥ)"6>~\8:qM}#͚'ĉ#p\׶ l#bA?)|g g9|8jP(cr,BwV (WliVxxᡁ@0Okn;ɥh$_ckCgriv}>=wGzβ KkBɛ[˪ !J)h&k2%07δt}!d<9;I&0wV/ v 0<H}L&8ob%Hi|޶o&h1L|u֦y~󛱢8fٲUsւ)0oiFx2}X[zVYr_;N(w]_4B@OanC?gĦx>мgx>ΛToZoOMp>40>V Oy V9iq!4 LN,ˢu{jsz]|"R޻&'ƚ{53ўFu(<٪9:΋]B;)B>1::8;~)Yt|0(pw2N%&X,URBK)3\zz&}ax4;ǟ(tLNg{N|Ǽ\G#C9g$^\}p?556]/RP.90 k,U8/u776s ʪ_01چ|\N 0VV*3H鴃J7iI!wG_^ypl}r*jɤSR 5QN@ iZ#1ٰy;_\3\BQQ x:WJv츟ٯ$"@6 S#qe딇(/P( Dy~TOϻ<4:-+F`0||;Xl-"uw$Цi󼕝mKʩorz"mϺ$F:~E'ҐvD\y?Rr8_He@ e~O,T.(ފR*cY^m|cVR[8 JҡSm!ΆԨb)RHG{?MpqrmN>߶Y)\p,d#xۆWY*,l6]v0h15M˙MS8+EdI='LBJIH7_9{Caз*Lq,dt >+~ّeʏ?xԕ4bBAŚjﵫ!'\Ը$WNvKO}ӽmSşذqsOy?\[,d@'73'j%kOe`1.g2"e =YIzS2|zŐƄa\U,dP;jhhhaxǶ?КZ՚.q SE+XrbOu%\GتX(H,N^~]JyEZQKceTQ]VGYqnah;y$cQahT&QPZ*iZ8UQQM.qo/T\7X"u?Mttl2Xq(IoW{R^ ux*SYJ! 4S.Jy~ BROS[V|žKNɛP(L6V^|cR7i7nZW1Fd@ Ara{詑|(T*dN]Ko?s=@ |_EvF]׍kR)eBJc" MUUbY6`~V޴dJKß&~'d3i WWWWWW
Current Directory: /opt/imunify360/venv/lib/python3.11/site-packages/lxml
Viewing File: /opt/imunify360/venv/lib/python3.11/site-packages/lxml/classlookup.pxi
# Configurable Element class lookup ################################################################################ # Custom Element classes cdef public class ElementBase(_Element) [ type LxmlElementBaseType, object LxmlElementBase ]: u"""ElementBase(*children, attrib=None, nsmap=None, **_extra) The public Element class. All custom Element classes must inherit from this one. To create an Element, use the `Element()` factory. BIG FAT WARNING: Subclasses *must not* override __init__ or __new__ as it is absolutely undefined when these objects will be created or destroyed. All persistent state of Elements must be stored in the underlying XML. If you really need to initialize the object after creation, you can implement an ``_init(self)`` method that will be called directly after object creation. Subclasses of this class can be instantiated to create a new Element. By default, the tag name will be the class name and the namespace will be empty. You can modify this with the following class attributes: * TAG - the tag name, possibly containing a namespace in Clark notation * NAMESPACE - the default namespace URI, unless provided as part of the TAG attribute. * HTML - flag if the class is an HTML tag, as opposed to an XML tag. This only applies to un-namespaced tags and defaults to false (i.e. XML). * PARSER - the parser that provides the configuration for the newly created document. Providing an HTML parser here will default to creating an HTML element. In user code, the latter three are commonly inherited in class hierarchies that implement a common namespace. """ def __init__(self, *children, attrib=None, nsmap=None, **_extra): u"""ElementBase(*children, attrib=None, nsmap=None, **_extra) """ cdef bint is_html = 0 cdef _BaseParser parser cdef _Element last_child # don't use normal attribute access as it might be overridden _getattr = object.__getattribute__ try: namespace = _utf8(_getattr(self, 'NAMESPACE')) except AttributeError: namespace = None try: ns, tag = _getNsTag(_getattr(self, 'TAG')) if ns is not None: namespace = ns except AttributeError: tag = _utf8(_getattr(_getattr(self, '__class__'), '__name__')) if b'.' in tag: tag = tag.split(b'.')[-1] try: parser = _getattr(self, 'PARSER') except AttributeError: parser = None for child in children: if isinstance(child, _Element): parser = (<_Element>child)._doc._parser break if isinstance(parser, HTMLParser): is_html = 1 if namespace is None: try: is_html = _getattr(self, 'HTML') except AttributeError: pass _initNewElement(self, is_html, tag, namespace, parser, attrib, nsmap, _extra) last_child = None for child in children: if _isString(child): if last_child is None: _setNodeText(self._c_node, (_collectText(self._c_node.children) or '') + child) else: _setTailText(last_child._c_node, (_collectText(last_child._c_node.next) or '') + child) elif isinstance(child, _Element): last_child = child _appendChild(self, last_child) elif isinstance(child, type) and issubclass(child, ElementBase): last_child = child() _appendChild(self, last_child) else: raise TypeError, f"Invalid child type: {type(child)!r}" cdef class CommentBase(_Comment): u"""All custom Comment classes must inherit from this one. To create an XML Comment instance, use the ``Comment()`` factory. Subclasses *must not* override __init__ or __new__ as it is absolutely undefined when these objects will be created or destroyed. All persistent state of Comments must be stored in the underlying XML. If you really need to initialize the object after creation, you can implement an ``_init(self)`` method that will be called after object creation. """ def __init__(self, text): # copied from Comment() factory cdef _Document doc cdef xmlDoc* c_doc if text is None: text = b'' else: text = _utf8(text) c_doc = _newXMLDoc() doc = _documentFactory(c_doc, None) self._c_node = _createComment(c_doc, _xcstr(text)) if self._c_node is NULL: raise MemoryError() tree.xmlAddChild(<xmlNode*>c_doc, self._c_node) _registerProxy(self, doc, self._c_node) self._init() cdef class PIBase(_ProcessingInstruction): u"""All custom Processing Instruction classes must inherit from this one. To create an XML ProcessingInstruction instance, use the ``PI()`` factory. Subclasses *must not* override __init__ or __new__ as it is absolutely undefined when these objects will be created or destroyed. All persistent state of PIs must be stored in the underlying XML. If you really need to initialize the object after creation, you can implement an ``_init(self)`` method that will be called after object creation. """ def __init__(self, target, text=None): # copied from PI() factory cdef _Document doc cdef xmlDoc* c_doc target = _utf8(target) if text is None: text = b'' else: text = _utf8(text) c_doc = _newXMLDoc() doc = _documentFactory(c_doc, None) self._c_node = _createPI(c_doc, _xcstr(target), _xcstr(text)) if self._c_node is NULL: raise MemoryError() tree.xmlAddChild(<xmlNode*>c_doc, self._c_node) _registerProxy(self, doc, self._c_node) self._init() cdef class EntityBase(_Entity): u"""All custom Entity classes must inherit from this one. To create an XML Entity instance, use the ``Entity()`` factory. Subclasses *must not* override __init__ or __new__ as it is absolutely undefined when these objects will be created or destroyed. All persistent state of Entities must be stored in the underlying XML. If you really need to initialize the object after creation, you can implement an ``_init(self)`` method that will be called after object creation. """ def __init__(self, name): cdef _Document doc cdef xmlDoc* c_doc name_utf = _utf8(name) c_name = _xcstr(name_utf) if c_name[0] == c'#': if not _characterReferenceIsValid(c_name + 1): raise ValueError, f"Invalid character reference: '{name}'" elif not _xmlNameIsValid(c_name): raise ValueError, f"Invalid entity reference: '{name}'" c_doc = _newXMLDoc() doc = _documentFactory(c_doc, None) self._c_node = _createEntity(c_doc, c_name) if self._c_node is NULL: raise MemoryError() tree.xmlAddChild(<xmlNode*>c_doc, self._c_node) _registerProxy(self, doc, self._c_node) self._init() cdef int _validateNodeClass(xmlNode* c_node, cls) except -1: if c_node.type == tree.XML_ELEMENT_NODE: expected = ElementBase elif c_node.type == tree.XML_COMMENT_NODE: expected = CommentBase elif c_node.type == tree.XML_ENTITY_REF_NODE: expected = EntityBase elif c_node.type == tree.XML_PI_NODE: expected = PIBase else: assert False, f"Unknown node type: {c_node.type}" if not (isinstance(cls, type) and issubclass(cls, expected)): raise TypeError( f"result of class lookup must be subclass of {type(expected)}, got {type(cls)}") return 0 ################################################################################ # Element class lookup ctypedef public object (*_element_class_lookup_function)(object, _Document, xmlNode*) # class to store element class lookup functions cdef public class ElementClassLookup [ type LxmlElementClassLookupType, object LxmlElementClassLookup ]: u"""ElementClassLookup(self) Superclass of Element class lookups. """ cdef _element_class_lookup_function _lookup_function cdef public class FallbackElementClassLookup(ElementClassLookup) \ [ type LxmlFallbackElementClassLookupType, object LxmlFallbackElementClassLookup ]: u"""FallbackElementClassLookup(self, fallback=None) Superclass of Element class lookups with additional fallback. """ cdef readonly ElementClassLookup fallback cdef _element_class_lookup_function _fallback_function def __cinit__(self): # fall back to default lookup self._fallback_function = _lookupDefaultElementClass def __init__(self, ElementClassLookup fallback=None): if fallback is not None: self._setFallback(fallback) else: self._fallback_function = _lookupDefaultElementClass cdef void _setFallback(self, ElementClassLookup lookup): u"""Sets the fallback scheme for this lookup method. """ self.fallback = lookup self._fallback_function = lookup._lookup_function if self._fallback_function is NULL: self._fallback_function = _lookupDefaultElementClass def set_fallback(self, ElementClassLookup lookup not None): u"""set_fallback(self, lookup) Sets the fallback scheme for this lookup method. """ self._setFallback(lookup) cdef inline object _callLookupFallback(FallbackElementClassLookup lookup, _Document doc, xmlNode* c_node): return lookup._fallback_function(lookup.fallback, doc, c_node) ################################################################################ # default lookup scheme cdef class ElementDefaultClassLookup(ElementClassLookup): u"""ElementDefaultClassLookup(self, element=None, comment=None, pi=None, entity=None) Element class lookup scheme that always returns the default Element class. The keyword arguments ``element``, ``comment``, ``pi`` and ``entity`` accept the respective Element classes. """ cdef readonly object element_class cdef readonly object comment_class cdef readonly object pi_class cdef readonly object entity_class def __cinit__(self): self._lookup_function = _lookupDefaultElementClass def __init__(self, element=None, comment=None, pi=None, entity=None): if element is None: self.element_class = _Element elif issubclass(element, ElementBase): self.element_class = element else: raise TypeError, u"element class must be subclass of ElementBase" if comment is None: self.comment_class = _Comment elif issubclass(comment, CommentBase): self.comment_class = comment else: raise TypeError, u"comment class must be subclass of CommentBase" if entity is None: self.entity_class = _Entity elif issubclass(entity, EntityBase): self.entity_class = entity else: raise TypeError, u"Entity class must be subclass of EntityBase" if pi is None: self.pi_class = None # special case, see below elif issubclass(pi, PIBase): self.pi_class = pi else: raise TypeError, u"PI class must be subclass of PIBase" cdef object _lookupDefaultElementClass(state, _Document _doc, xmlNode* c_node): u"Trivial class lookup function that always returns the default class." if c_node.type == tree.XML_ELEMENT_NODE: if state is not None: return (<ElementDefaultClassLookup>state).element_class else: return _Element elif c_node.type == tree.XML_COMMENT_NODE: if state is not None: return (<ElementDefaultClassLookup>state).comment_class else: return _Comment elif c_node.type == tree.XML_ENTITY_REF_NODE: if state is not None: return (<ElementDefaultClassLookup>state).entity_class else: return _Entity elif c_node.type == tree.XML_PI_NODE: if state is None or (<ElementDefaultClassLookup>state).pi_class is None: # special case XSLT-PI if c_node.name is not NULL and c_node.content is not NULL: if tree.xmlStrcmp(c_node.name, <unsigned char*>"xml-stylesheet") == 0: if tree.xmlStrstr(c_node.content, <unsigned char*>"text/xsl") is not NULL or \ tree.xmlStrstr(c_node.content, <unsigned char*>"text/xml") is not NULL: return _XSLTProcessingInstruction return _ProcessingInstruction else: return (<ElementDefaultClassLookup>state).pi_class else: assert False, f"Unknown node type: {c_node.type}" ################################################################################ # attribute based lookup scheme cdef class AttributeBasedElementClassLookup(FallbackElementClassLookup): u"""AttributeBasedElementClassLookup(self, attribute_name, class_mapping, fallback=None) Checks an attribute of an Element and looks up the value in a class dictionary. Arguments: - attribute name - '{ns}name' style string - class mapping - Python dict mapping attribute values to Element classes - fallback - optional fallback lookup mechanism A None key in the class mapping will be checked if the attribute is missing. """ cdef object _class_mapping cdef tuple _pytag cdef const_xmlChar* _c_ns cdef const_xmlChar* _c_name def __cinit__(self): self._lookup_function = _attribute_class_lookup def __init__(self, attribute_name, class_mapping, ElementClassLookup fallback=None): self._pytag = _getNsTag(attribute_name) ns, name = self._pytag if ns is None: self._c_ns = NULL else: self._c_ns = _xcstr(ns) self._c_name = _xcstr(name) self._class_mapping = dict(class_mapping) FallbackElementClassLookup.__init__(self, fallback) cdef object _attribute_class_lookup(state, _Document doc, xmlNode* c_node): cdef AttributeBasedElementClassLookup lookup cdef python.PyObject* dict_result lookup = <AttributeBasedElementClassLookup>state if c_node.type == tree.XML_ELEMENT_NODE: value = _attributeValueFromNsName( c_node, lookup._c_ns, lookup._c_name) dict_result = python.PyDict_GetItem(lookup._class_mapping, value) if dict_result is not NULL: cls = <object>dict_result _validateNodeClass(c_node, cls) return cls return _callLookupFallback(lookup, doc, c_node) ################################################################################ # per-parser lookup scheme cdef class ParserBasedElementClassLookup(FallbackElementClassLookup): u"""ParserBasedElementClassLookup(self, fallback=None) Element class lookup based on the XML parser. """ def __cinit__(self): self._lookup_function = _parser_class_lookup cdef object _parser_class_lookup(state, _Document doc, xmlNode* c_node): if doc._parser._class_lookup is not None: return doc._parser._class_lookup._lookup_function( doc._parser._class_lookup, doc, c_node) return _callLookupFallback(<FallbackElementClassLookup>state, doc, c_node) ################################################################################ # custom class lookup based on node type, namespace, name cdef class CustomElementClassLookup(FallbackElementClassLookup): u"""CustomElementClassLookup(self, fallback=None) Element class lookup based on a subclass method. You can inherit from this class and override the method:: lookup(self, type, doc, namespace, name) to lookup the element class for a node. Arguments of the method: * type: one of 'element', 'comment', 'PI', 'entity' * doc: document that the node is in * namespace: namespace URI of the node (or None for comments/PIs/entities) * name: name of the element/entity, None for comments, target for PIs If you return None from this method, the fallback will be called. """ def __cinit__(self): self._lookup_function = _custom_class_lookup def lookup(self, type, doc, namespace, name): u"lookup(self, type, doc, namespace, name)" return None cdef object _custom_class_lookup(state, _Document doc, xmlNode* c_node): cdef CustomElementClassLookup lookup lookup = <CustomElementClassLookup>state if c_node.type == tree.XML_ELEMENT_NODE: element_type = u"element" elif c_node.type == tree.XML_COMMENT_NODE: element_type = u"comment" elif c_node.type == tree.XML_PI_NODE: element_type = u"PI" elif c_node.type == tree.XML_ENTITY_REF_NODE: element_type = u"entity" else: element_type = u"element" if c_node.name is NULL: name = None else: name = funicode(c_node.name) c_str = tree._getNs(c_node) ns = funicode(c_str) if c_str is not NULL else None cls = lookup.lookup(element_type, doc, ns, name) if cls is not None: _validateNodeClass(c_node, cls) return cls return _callLookupFallback(lookup, doc, c_node) ################################################################################ # read-only tree based class lookup cdef class PythonElementClassLookup(FallbackElementClassLookup): u"""PythonElementClassLookup(self, fallback=None) Element class lookup based on a subclass method. This class lookup scheme allows access to the entire XML tree in read-only mode. To use it, re-implement the ``lookup(self, doc, root)`` method in a subclass:: from lxml import etree, pyclasslookup class MyElementClass(etree.ElementBase): honkey = True class MyLookup(pyclasslookup.PythonElementClassLookup): def lookup(self, doc, root): if root.tag == "sometag": return MyElementClass else: for child in root: if child.tag == "someothertag": return MyElementClass # delegate to default return None If you return None from this method, the fallback will be called. The first argument is the opaque document instance that contains the Element. The second argument is a lightweight Element proxy implementation that is only valid during the lookup. Do not try to keep a reference to it. Once the lookup is done, the proxy will be invalid. Also, you cannot wrap such a read-only Element in an ElementTree, and you must take care not to keep a reference to them outside of the `lookup()` method. Note that the API of the Element objects is not complete. It is purely read-only and does not support all features of the normal `lxml.etree` API (such as XPath, extended slicing or some iteration methods). See https://lxml.de/element_classes.html """ def __cinit__(self): self._lookup_function = _python_class_lookup def lookup(self, doc, element): u"""lookup(self, doc, element) Override this method to implement your own lookup scheme. """ return None cdef object _python_class_lookup(state, _Document doc, tree.xmlNode* c_node): cdef PythonElementClassLookup lookup cdef _ReadOnlyProxy proxy lookup = <PythonElementClassLookup>state proxy = _newReadOnlyProxy(None, c_node) cls = lookup.lookup(doc, proxy) _freeReadOnlyProxies(proxy) if cls is not None: _validateNodeClass(c_node, cls) return cls return _callLookupFallback(lookup, doc, c_node) ################################################################################ # Global setup cdef _element_class_lookup_function LOOKUP_ELEMENT_CLASS cdef object ELEMENT_CLASS_LOOKUP_STATE cdef void _setElementClassLookupFunction( _element_class_lookup_function function, object state): global LOOKUP_ELEMENT_CLASS, ELEMENT_CLASS_LOOKUP_STATE if function is NULL: state = DEFAULT_ELEMENT_CLASS_LOOKUP function = DEFAULT_ELEMENT_CLASS_LOOKUP._lookup_function ELEMENT_CLASS_LOOKUP_STATE = state LOOKUP_ELEMENT_CLASS = function def set_element_class_lookup(ElementClassLookup lookup = None): u"""set_element_class_lookup(lookup = None) Set the global element class lookup method. This defines the main entry point for looking up element implementations. The standard implementation uses the :class:`ParserBasedElementClassLookup` to delegate to different lookup schemes for each parser. .. warning:: This should only be changed by applications, not by library packages. In most cases, parser specific lookups should be preferred, which can be configured via :meth:`~lxml.etree.XMLParser.set_element_class_lookup` (and the same for HTML parsers). Globally replacing the element class lookup by something other than a :class:`ParserBasedElementClassLookup` will prevent parser specific lookup schemes from working. Several tools rely on parser specific lookups, including :mod:`lxml.html` and :mod:`lxml.objectify`. """ if lookup is None or lookup._lookup_function is NULL: _setElementClassLookupFunction(NULL, None) else: _setElementClassLookupFunction(lookup._lookup_function, lookup) # default setup: parser delegation cdef ParserBasedElementClassLookup DEFAULT_ELEMENT_CLASS_LOOKUP DEFAULT_ELEMENT_CLASS_LOOKUP = ParserBasedElementClassLookup() set_element_class_lookup(DEFAULT_ELEMENT_CLASS_LOOKUP)