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/cloudlinux/venv/lib/python3.11/site-packages
Viewing File: /opt/cloudlinux/venv/lib/python3.11/site-packages/pep8ext_naming.py
# -*- coding: utf-8 -*- """Checker of PEP-8 Naming Conventions.""" import sys from collections import deque from fnmatch import fnmatch from functools import partial from itertools import chain from flake8_polyfill import options try: import ast from ast import iter_child_nodes except ImportError: from flake8.util import ast, iter_child_nodes __version__ = '0.10.0' PYTHON_VERSION = sys.version_info[:3] PY2 = PYTHON_VERSION[0] == 2 METACLASS_BASES = frozenset(('type', 'ABCMeta')) # Node types which may contain class methods METHOD_CONTAINER_NODES = {ast.If, ast.While, ast.For, ast.With} FUNC_NODES = (ast.FunctionDef,) if PY2: METHOD_CONTAINER_NODES |= {ast.TryExcept, ast.TryFinally} else: METHOD_CONTAINER_NODES |= {ast.Try} if PYTHON_VERSION > (3, 5): FUNC_NODES += (ast.AsyncFunctionDef,) METHOD_CONTAINER_NODES |= {ast.AsyncWith, ast.AsyncFor} if PY2: def _unpack_args(args): ret = [] for arg in args: if isinstance(arg, ast.Tuple): ret.extend(_unpack_args(arg.elts)) else: ret.append((arg, arg.id)) return ret def get_arg_name_tuples(node): return _unpack_args(node.args.args) elif PYTHON_VERSION < (3, 8): def get_arg_name_tuples(node): groups = (node.args.args, node.args.kwonlyargs) return [(arg, arg.arg) for args in groups for arg in args] else: def get_arg_name_tuples(node): groups = (node.args.posonlyargs, node.args.args, node.args.kwonlyargs) return [(arg, arg.arg) for args in groups for arg in args] class _ASTCheckMeta(type): def __init__(cls, class_name, bases, namespace): try: cls._checks.append(cls()) except AttributeError: cls._checks = [] def _err(self, node, code, **kwargs): lineno, col_offset = node.lineno, node.col_offset if isinstance(node, ast.ClassDef): if PYTHON_VERSION < (3, 8): lineno += len(node.decorator_list) col_offset += 6 elif isinstance(node, FUNC_NODES): if PYTHON_VERSION < (3, 8): lineno += len(node.decorator_list) col_offset += 4 code_str = getattr(self, code) if kwargs: code_str = code_str.format(**kwargs) return lineno, col_offset + 1, '%s %s' % (code, code_str), self def _ignored(name, ignore): return any(fnmatch(name, i) for i in ignore) BaseASTCheck = _ASTCheckMeta('BaseASTCheck', (object,), {'__doc__': "Base for AST Checks.", 'err': _err}) class _FunctionType(object): CLASSMETHOD = 'classmethod' STATICMETHOD = 'staticmethod' FUNCTION = 'function' METHOD = 'method' _default_ignore_names = [ 'setUp', 'tearDown', 'setUpClass', 'tearDownClass', 'setUpTestData', 'failureException', 'longMessage', 'maxDiff'] _default_classmethod_decorators = ['classmethod'] _default_staticmethod_decorators = ['staticmethod'] def _build_decorator_to_type(classmethod_decorators, staticmethod_decorators): decorator_to_type = {} for decorator in classmethod_decorators: decorator_to_type[decorator] = _FunctionType.CLASSMETHOD for decorator in staticmethod_decorators: decorator_to_type[decorator] = _FunctionType.STATICMETHOD return decorator_to_type class NamingChecker(object): """Checker of PEP-8 Naming Conventions.""" name = 'naming' version = __version__ decorator_to_type = _build_decorator_to_type( _default_classmethod_decorators, _default_staticmethod_decorators) ignore_names = frozenset(_default_ignore_names) def __init__(self, tree, filename): self.visitors = BaseASTCheck._checks self.parents = deque() self._node = tree @classmethod def add_options(cls, parser): options.register(parser, '--ignore-names', default=_default_ignore_names, action='store', type='string', parse_from_config=True, comma_separated_list=True, help='List of names or glob patterns the pep8-naming ' 'plugin should ignore. (Defaults to %default)') options.register(parser, '--classmethod-decorators', default=_default_classmethod_decorators, action='store', type='string', parse_from_config=True, comma_separated_list=True, help='List of method decorators pep8-naming plugin ' 'should consider classmethods (Defaults to ' '%default)') options.register(parser, '--staticmethod-decorators', default=_default_staticmethod_decorators, action='store', type='string', parse_from_config=True, comma_separated_list=True, help='List of method decorators pep8-naming plugin ' 'should consider staticmethods (Defaults to ' '%default)') @classmethod def parse_options(cls, options): cls.ignore_names = frozenset(options.ignore_names) cls.decorator_to_type = _build_decorator_to_type( options.classmethod_decorators, options.staticmethod_decorators) def run(self): return self.visit_tree(self._node) if self._node else () def visit_tree(self, node): for error in self.visit_node(node): yield error self.parents.append(node) for child in iter_child_nodes(node): for error in self.visit_tree(child): yield error self.parents.pop() def visit_node(self, node): if isinstance(node, ast.ClassDef): self.tag_class_functions(node) elif isinstance(node, FUNC_NODES): self.find_global_defs(node) method = 'visit_' + node.__class__.__name__.lower() parents = self.parents ignore_names = self.ignore_names for visitor in self.visitors: visitor_method = getattr(visitor, method, None) if visitor_method is None: continue for error in visitor_method(node, parents, ignore_names): yield error def tag_class_functions(self, cls_node): """Tag functions if they are methods, classmethods, staticmethods""" # tries to find all 'old style decorators' like # m = staticmethod(m) late_decoration = {} for node in iter_child_nodes(cls_node): if not (isinstance(node, ast.Assign) and isinstance(node.value, ast.Call) and isinstance(node.value.func, ast.Name)): continue func_name = node.value.func.id if func_name not in self.decorator_to_type: continue meth = (len(node.value.args) == 1 and node.value.args[0]) if isinstance(meth, ast.Name): late_decoration[meth.id] = self.decorator_to_type[func_name] # If this class inherits from a known metaclass base class, it is # itself a metaclass, and we'll consider all of it's methods to be # classmethods. bases = chain( (b.id for b in cls_node.bases if isinstance(b, ast.Name)), (b.attr for b in cls_node.bases if isinstance(b, ast.Attribute)), ) ismetaclass = any(name for name in bases if name in METACLASS_BASES) self.set_function_nodes_types( iter_child_nodes(cls_node), ismetaclass, late_decoration) def set_function_nodes_types(self, nodes, ismetaclass, late_decoration): # iterate over all functions and tag them for node in nodes: if type(node) in METHOD_CONTAINER_NODES: self.set_function_nodes_types( iter_child_nodes(node), ismetaclass, late_decoration) if not isinstance(node, FUNC_NODES): continue node.function_type = _FunctionType.METHOD if node.name in ('__new__', '__init_subclass__') or ismetaclass: node.function_type = _FunctionType.CLASSMETHOD if node.name in late_decoration: node.function_type = late_decoration[node.name] elif node.decorator_list: names = [self.decorator_to_type[d.id] for d in node.decorator_list if isinstance(d, ast.Name) and d.id in self.decorator_to_type] if names: node.function_type = names[0] @staticmethod def find_global_defs(func_def_node): global_names = set() nodes_to_check = deque(iter_child_nodes(func_def_node)) while nodes_to_check: node = nodes_to_check.pop() if isinstance(node, ast.Global): global_names.update(node.names) if not isinstance(node, (ast.ClassDef,) + FUNC_NODES): nodes_to_check.extend(iter_child_nodes(node)) func_def_node.global_names = global_names class ClassNameCheck(BaseASTCheck): """ Almost without exception, class names use the CapWords convention. Classes for internal use have a leading underscore in addition. """ N801 = "class name '{name}' should use CapWords convention" def visit_classdef(self, node, parents, ignore=None): name = node.name if _ignored(name, ignore): return name = name.strip('_') if not name[:1].isupper() or '_' in name: yield self.err(node, 'N801', name=name) class FunctionNameCheck(BaseASTCheck): """ Function names should be lowercase, with words separated by underscores as necessary to improve readability. Functions *not* being methods '__' in front and back are not allowed. mixedCase is allowed only in contexts where that's already the prevailing style (e.g. threading.py), to retain backwards compatibility. """ N802 = "function name '{name}' should be lowercase" N807 = "function name '{name}' should not start and end with '__'" def visit_functiondef(self, node, parents, ignore=None): function_type = getattr(node, 'function_type', _FunctionType.FUNCTION) name = node.name if _ignored(name, ignore): return if name in ('__dir__', '__getattr__'): return if name.lower() != name: yield self.err(node, 'N802', name=name) if (function_type == _FunctionType.FUNCTION and name[:2] == '__' and name[-2:] == '__'): yield self.err(node, 'N807', name=name) visit_asyncfunctiondef = visit_functiondef class FunctionArgNamesCheck(BaseASTCheck): """ The argument names of a function should be lowercase, with words separated by underscores. A classmethod should have 'cls' as first argument. A method should have 'self' as first argument. """ N803 = "argument name '{name}' should be lowercase" N804 = "first argument of a classmethod should be named 'cls'" N805 = "first argument of a method should be named 'self'" def visit_functiondef(self, node, parents, ignore=None): def arg_name(arg): try: return arg, arg.arg except AttributeError: # PY2 return node, arg for arg, name in arg_name(node.args.vararg), arg_name(node.args.kwarg): if name is None or _ignored(name, ignore): continue if name.lower() != name: yield self.err(arg, 'N803', name=name) return arg_name_tuples = get_arg_name_tuples(node) if not arg_name_tuples: return arg0, name0 = arg_name_tuples[0] function_type = getattr(node, 'function_type', _FunctionType.FUNCTION) if function_type == _FunctionType.METHOD: if name0 != 'self' and not _ignored(name0, ignore): yield self.err(arg0, 'N805') elif function_type == _FunctionType.CLASSMETHOD: if name0 != 'cls' and not _ignored(name0, ignore): yield self.err(arg0, 'N804') for arg, name in arg_name_tuples: if name.lower() != name and not _ignored(name, ignore): yield self.err(arg, 'N803', name=name) return visit_asyncfunctiondef = visit_functiondef class ImportAsCheck(BaseASTCheck): """ Don't change the naming convention via an import """ N811 = "constant '{name}' imported as non constant '{asname}'" N812 = "lowercase '{name}' imported as non lowercase '{asname}'" N813 = "camelcase '{name}' imported as lowercase '{asname}'" N814 = "camelcase '{name}' imported as constant '{asname}'" N817 = "camelcase '{name}' imported as acronym '{asname}'" def visit_importfrom(self, node, parents, ignore=None): for name in node.names: asname = name.asname if not asname: continue original_name = name.name err_kwargs = {'name': original_name, 'asname': asname} if original_name.isupper(): if not asname.isupper(): yield self.err(node, 'N811', **err_kwargs) elif original_name.islower(): if asname.lower() != asname: yield self.err(node, 'N812', **err_kwargs) elif asname.islower(): yield self.err(node, 'N813', **err_kwargs) elif asname.isupper(): if ''.join(filter(str.isupper, original_name)) == asname: yield self.err(node, 'N817', **err_kwargs) else: yield self.err(node, 'N814', **err_kwargs) visit_import = visit_importfrom class VariablesCheck(BaseASTCheck): """ Class attributes and local variables in functions should be lowercase """ N806 = "variable '{name}' in function should be lowercase" N815 = "variable '{name}' in class scope should not be mixedCase" N816 = "variable '{name}' in global scope should not be mixedCase" def _find_errors(self, assignment_target, parents, ignore): for parent_func in reversed(parents): if isinstance(parent_func, ast.ClassDef): checker = self.class_variable_check break if isinstance(parent_func, FUNC_NODES): checker = partial(self.function_variable_check, parent_func) break else: checker = self.global_variable_check for name in _extract_names(assignment_target): if _ignored(name, ignore): continue error_code = checker(name) if error_code: yield self.err(assignment_target, error_code, name=name) @staticmethod def is_namedtupe(node_value): if isinstance(node_value, ast.Call): if isinstance(node_value.func, ast.Attribute): if node_value.func.attr == 'namedtuple': return True elif isinstance(node_value.func, ast.Name): if node_value.func.id == 'namedtuple': return True return False def visit_assign(self, node, parents, ignore=None): if self.is_namedtupe(node.value): return for target in node.targets: for error in self._find_errors(target, parents, ignore): yield error def visit_namedexpr(self, node, parents, ignore): if self.is_namedtupe(node.value): return for error in self._find_errors(node.target, parents, ignore): yield error visit_annassign = visit_namedexpr def visit_with(self, node, parents, ignore): if PY2: for error in self._find_errors( node.optional_vars, parents, ignore): yield error return for item in node.items: for error in self._find_errors( item.optional_vars, parents, ignore): yield error visit_asyncwith = visit_with def visit_for(self, node, parents, ignore): for error in self._find_errors(node.target, parents, ignore): yield error visit_asyncfor = visit_for def visit_excepthandler(self, node, parents, ignore): if node.name: for error in self._find_errors(node, parents, ignore): yield error def visit_generatorexp(self, node, parents, ignore): for gen in node.generators: for error in self._find_errors(gen.target, parents, ignore): yield error visit_listcomp = visit_dictcomp = visit_setcomp = visit_generatorexp @staticmethod def global_variable_check(name): if is_mixed_case(name): return 'N816' @staticmethod def class_variable_check(name): if is_mixed_case(name): return 'N815' @staticmethod def function_variable_check(func, var_name): if var_name in func.global_names: return None if var_name.lower() == var_name: return None return 'N806' def _extract_names(assignment_target): """Yield assignment_target ids.""" target_type = type(assignment_target) if target_type is ast.Name: yield assignment_target.id elif target_type in (ast.Tuple, ast.List): for element in assignment_target.elts: element_type = type(element) if element_type is ast.Name: yield element.id elif element_type in (ast.Tuple, ast.List): for n in _extract_names(element): yield n elif not PY2 and element_type is ast.Starred: # PEP 3132 for n in _extract_names(element.value): yield n elif target_type is ast.ExceptHandler: if PY2: # Python 2 supports unpacking tuple exception values. if isinstance(assignment_target.name, ast.Tuple): for name in assignment_target.name.elts: yield name.id elif isinstance(assignment_target.name, ast.Attribute): # Python 2 also supports assigning an exception to an attribute # eg. except Exception as obj.attr yield assignment_target.name.attr else: yield assignment_target.name.id else: yield assignment_target.name def is_mixed_case(name): return name.lower() != name and name.lstrip('_')[:1].islower()