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: /usr/lib/imh-dnskeyapi/venv/lib/python3.13/site-packages/itsdangerous
Viewing File: /usr/lib/imh-dnskeyapi/venv/lib/python3.13/site-packages/itsdangerous/serializer.py
from __future__ import annotations import collections.abc as cabc import json import typing as t from .encoding import want_bytes from .exc import BadPayload from .exc import BadSignature from .signer import _make_keys_list from .signer import Signer if t.TYPE_CHECKING: import typing_extensions as te # This should be either be str or bytes. To avoid having to specify the # bound type, it falls back to a union if structural matching fails. _TSerialized = te.TypeVar( "_TSerialized", bound=t.Union[str, bytes], default=t.Union[str, bytes] ) else: # Still available at runtime on Python < 3.13, but without the default. _TSerialized = t.TypeVar("_TSerialized", bound=t.Union[str, bytes]) class _PDataSerializer(t.Protocol[_TSerialized]): def loads(self, payload: _TSerialized, /) -> t.Any: ... # A signature with additional arguments is not handled correctly by type # checkers right now, so an overload is used below for serializers that # don't match this strict protocol. def dumps(self, obj: t.Any, /) -> _TSerialized: ... # Use TypeIs once it's available in typing_extensions or 3.13. def is_text_serializer( serializer: _PDataSerializer[t.Any], ) -> te.TypeGuard[_PDataSerializer[str]]: """Checks whether a serializer generates text or binary.""" return isinstance(serializer.dumps({}), str) class Serializer(t.Generic[_TSerialized]): """A serializer wraps a :class:`~itsdangerous.signer.Signer` to enable serializing and securely signing data other than bytes. It can unsign to verify that the data hasn't been changed. The serializer provides :meth:`dumps` and :meth:`loads`, similar to :mod:`json`, and by default uses :mod:`json` internally to serialize the data to bytes. The secret key should be a random string of ``bytes`` and should not be saved to code or version control. Different salts should be used to distinguish signing in different contexts. See :doc:`/concepts` for information about the security of the secret key and salt. :param secret_key: The secret key to sign and verify with. Can be a list of keys, oldest to newest, to support key rotation. :param salt: Extra key to combine with ``secret_key`` to distinguish signatures in different contexts. :param serializer: An object that provides ``dumps`` and ``loads`` methods for serializing data to a string. Defaults to :attr:`default_serializer`, which defaults to :mod:`json`. :param serializer_kwargs: Keyword arguments to pass when calling ``serializer.dumps``. :param signer: A ``Signer`` class to instantiate when signing data. Defaults to :attr:`default_signer`, which defaults to :class:`~itsdangerous.signer.Signer`. :param signer_kwargs: Keyword arguments to pass when instantiating the ``Signer`` class. :param fallback_signers: List of signer parameters to try when unsigning with the default signer fails. Each item can be a dict of ``signer_kwargs``, a ``Signer`` class, or a tuple of ``(signer, signer_kwargs)``. Defaults to :attr:`default_fallback_signers`. .. versionchanged:: 2.0 Added support for key rotation by passing a list to ``secret_key``. .. versionchanged:: 2.0 Removed the default SHA-512 fallback signer from ``default_fallback_signers``. .. versionchanged:: 1.1 Added support for ``fallback_signers`` and configured a default SHA-512 fallback. This fallback is for users who used the yanked 1.0.0 release which defaulted to SHA-512. .. versionchanged:: 0.14 The ``signer`` and ``signer_kwargs`` parameters were added to the constructor. """ #: The default serialization module to use to serialize data to a #: string internally. The default is :mod:`json`, but can be changed #: to any object that provides ``dumps`` and ``loads`` methods. default_serializer: _PDataSerializer[t.Any] = json #: The default ``Signer`` class to instantiate when signing data. #: The default is :class:`itsdangerous.signer.Signer`. default_signer: type[Signer] = Signer #: The default fallback signers to try when unsigning fails. default_fallback_signers: list[ dict[str, t.Any] | tuple[type[Signer], dict[str, t.Any]] | type[Signer] ] = [] # Serializer[str] if no data serializer is provided, or if it returns str. @t.overload def __init__( self: Serializer[str], secret_key: str | bytes | cabc.Iterable[str] | cabc.Iterable[bytes], salt: str | bytes | None = b"itsdangerous", serializer: None | _PDataSerializer[str] = None, serializer_kwargs: dict[str, t.Any] | None = None, signer: type[Signer] | None = None, signer_kwargs: dict[str, t.Any] | None = None, fallback_signers: list[ dict[str, t.Any] | tuple[type[Signer], dict[str, t.Any]] | type[Signer] ] | None = None, ): ... # Serializer[bytes] with a bytes data serializer positional argument. @t.overload def __init__( self: Serializer[bytes], secret_key: str | bytes | cabc.Iterable[str] | cabc.Iterable[bytes], salt: str | bytes | None, serializer: _PDataSerializer[bytes], serializer_kwargs: dict[str, t.Any] | None = None, signer: type[Signer] | None = None, signer_kwargs: dict[str, t.Any] | None = None, fallback_signers: list[ dict[str, t.Any] | tuple[type[Signer], dict[str, t.Any]] | type[Signer] ] | None = None, ): ... # Serializer[bytes] with a bytes data serializer keyword argument. @t.overload def __init__( self: Serializer[bytes], secret_key: str | bytes | cabc.Iterable[str] | cabc.Iterable[bytes], salt: str | bytes | None = b"itsdangerous", *, serializer: _PDataSerializer[bytes], serializer_kwargs: dict[str, t.Any] | None = None, signer: type[Signer] | None = None, signer_kwargs: dict[str, t.Any] | None = None, fallback_signers: list[ dict[str, t.Any] | tuple[type[Signer], dict[str, t.Any]] | type[Signer] ] | None = None, ): ... # Fall back with a positional argument. If the strict signature of # _PDataSerializer doesn't match, fall back to a union, requiring the user # to specify the type. @t.overload def __init__( self, secret_key: str | bytes | cabc.Iterable[str] | cabc.Iterable[bytes], salt: str | bytes | None, serializer: t.Any, serializer_kwargs: dict[str, t.Any] | None = None, signer: type[Signer] | None = None, signer_kwargs: dict[str, t.Any] | None = None, fallback_signers: list[ dict[str, t.Any] | tuple[type[Signer], dict[str, t.Any]] | type[Signer] ] | None = None, ): ... # Fall back with a keyword argument. @t.overload def __init__( self, secret_key: str | bytes | cabc.Iterable[str] | cabc.Iterable[bytes], salt: str | bytes | None = b"itsdangerous", *, serializer: t.Any, serializer_kwargs: dict[str, t.Any] | None = None, signer: type[Signer] | None = None, signer_kwargs: dict[str, t.Any] | None = None, fallback_signers: list[ dict[str, t.Any] | tuple[type[Signer], dict[str, t.Any]] | type[Signer] ] | None = None, ): ... def __init__( self, secret_key: str | bytes | cabc.Iterable[str] | cabc.Iterable[bytes], salt: str | bytes | None = b"itsdangerous", serializer: t.Any | None = None, serializer_kwargs: dict[str, t.Any] | None = None, signer: type[Signer] | None = None, signer_kwargs: dict[str, t.Any] | None = None, fallback_signers: list[ dict[str, t.Any] | tuple[type[Signer], dict[str, t.Any]] | type[Signer] ] | None = None, ): #: The list of secret keys to try for verifying signatures, from #: oldest to newest. The newest (last) key is used for signing. #: #: This allows a key rotation system to keep a list of allowed #: keys and remove expired ones. self.secret_keys: list[bytes] = _make_keys_list(secret_key) if salt is not None: salt = want_bytes(salt) # if salt is None then the signer's default is used self.salt = salt if serializer is None: serializer = self.default_serializer self.serializer: _PDataSerializer[_TSerialized] = serializer self.is_text_serializer: bool = is_text_serializer(serializer) if signer is None: signer = self.default_signer self.signer: type[Signer] = signer self.signer_kwargs: dict[str, t.Any] = signer_kwargs or {} if fallback_signers is None: fallback_signers = list(self.default_fallback_signers) self.fallback_signers: list[ dict[str, t.Any] | tuple[type[Signer], dict[str, t.Any]] | type[Signer] ] = fallback_signers self.serializer_kwargs: dict[str, t.Any] = serializer_kwargs or {} @property def secret_key(self) -> bytes: """The newest (last) entry in the :attr:`secret_keys` list. This is for compatibility from before key rotation support was added. """ return self.secret_keys[-1] def load_payload( self, payload: bytes, serializer: _PDataSerializer[t.Any] | None = None ) -> t.Any: """Loads the encoded object. This function raises :class:`.BadPayload` if the payload is not valid. The ``serializer`` parameter can be used to override the serializer stored on the class. The encoded ``payload`` should always be bytes. """ if serializer is None: use_serializer = self.serializer is_text = self.is_text_serializer else: use_serializer = serializer is_text = is_text_serializer(serializer) try: if is_text: return use_serializer.loads(payload.decode("utf-8")) # type: ignore[arg-type] return use_serializer.loads(payload) # type: ignore[arg-type] except Exception as e: raise BadPayload( "Could not load the payload because an exception" " occurred on unserializing the data.", original_error=e, ) from e def dump_payload(self, obj: t.Any) -> bytes: """Dumps the encoded object. The return value is always bytes. If the internal serializer returns text, the value will be encoded as UTF-8. """ return want_bytes(self.serializer.dumps(obj, **self.serializer_kwargs)) def make_signer(self, salt: str | bytes | None = None) -> Signer: """Creates a new instance of the signer to be used. The default implementation uses the :class:`.Signer` base class. """ if salt is None: salt = self.salt return self.signer(self.secret_keys, salt=salt, **self.signer_kwargs) def iter_unsigners(self, salt: str | bytes | None = None) -> cabc.Iterator[Signer]: """Iterates over all signers to be tried for unsigning. Starts with the configured signer, then constructs each signer specified in ``fallback_signers``. """ if salt is None: salt = self.salt yield self.make_signer(salt) for fallback in self.fallback_signers: if isinstance(fallback, dict): kwargs = fallback fallback = self.signer elif isinstance(fallback, tuple): fallback, kwargs = fallback else: kwargs = self.signer_kwargs for secret_key in self.secret_keys: yield fallback(secret_key, salt=salt, **kwargs) def dumps(self, obj: t.Any, salt: str | bytes | None = None) -> _TSerialized: """Returns a signed string serialized with the internal serializer. The return value can be either a byte or unicode string depending on the format of the internal serializer. """ payload = want_bytes(self.dump_payload(obj)) rv = self.make_signer(salt).sign(payload) if self.is_text_serializer: return rv.decode("utf-8") # type: ignore[return-value] return rv # type: ignore[return-value] def dump(self, obj: t.Any, f: t.IO[t.Any], salt: str | bytes | None = None) -> None: """Like :meth:`dumps` but dumps into a file. The file handle has to be compatible with what the internal serializer expects. """ f.write(self.dumps(obj, salt)) def loads( self, s: str | bytes, salt: str | bytes | None = None, **kwargs: t.Any ) -> t.Any: """Reverse of :meth:`dumps`. Raises :exc:`.BadSignature` if the signature validation fails. """ s = want_bytes(s) last_exception = None for signer in self.iter_unsigners(salt): try: return self.load_payload(signer.unsign(s)) except BadSignature as err: last_exception = err raise t.cast(BadSignature, last_exception) def load(self, f: t.IO[t.Any], salt: str | bytes | None = None) -> t.Any: """Like :meth:`loads` but loads from a file.""" return self.loads(f.read(), salt) def loads_unsafe( self, s: str | bytes, salt: str | bytes | None = None ) -> tuple[bool, t.Any]: """Like :meth:`loads` but without verifying the signature. This is potentially very dangerous to use depending on how your serializer works. The return value is ``(signature_valid, payload)`` instead of just the payload. The first item will be a boolean that indicates if the signature is valid. This function never fails. Use it for debugging only and if you know that your serializer module is not exploitable (for example, do not use it with a pickle serializer). .. versionadded:: 0.15 """ return self._loads_unsafe_impl(s, salt) def _loads_unsafe_impl( self, s: str | bytes, salt: str | bytes | None, load_kwargs: dict[str, t.Any] | None = None, load_payload_kwargs: dict[str, t.Any] | None = None, ) -> tuple[bool, t.Any]: """Low level helper function to implement :meth:`loads_unsafe` in serializer subclasses. """ if load_kwargs is None: load_kwargs = {} try: return True, self.loads(s, salt=salt, **load_kwargs) except BadSignature as e: if e.payload is None: return False, None if load_payload_kwargs is None: load_payload_kwargs = {} try: return ( False, self.load_payload(e.payload, **load_payload_kwargs), ) except BadPayload: return False, None def load_unsafe( self, f: t.IO[t.Any], salt: str | bytes | None = None ) -> tuple[bool, t.Any]: """Like :meth:`loads_unsafe` but loads from a file. .. versionadded:: 0.15 """ return self.loads_unsafe(f.read(), salt=salt)