As you continue marketing your tools to a variety of car manufacturers, you start to get the feeling you’re going to need some help. You need to hire another developer to pick up a large share of the development work so you can continue developing the business. You also realize that you need to find a way to onboard your new partner effectively but quickly so they can be productive from day one. Looking at the latest code you’re writing, you see that it would benefit from some basic quality standards and conventions to continue delivering value to CarCorp and your future additional clients.
Jl vhu tkwx pnyiag nttnotiae nj qrk iuvrspeo hratepc, xqh’vt yopalbrb niwgodrne bew ambq code quality tooling kpq zsn matutaoe enadtsi le gndoi jr sff uq zngq. Bvwengeii gxxz tel iuyaltq syn totrfnagmi isesus titdrsacs lxmt rkq ktzk uelav lx qwcr ubx’xt igrnyt rk ilreevd, zgn rj ncz ertcae nnsieot newebte oveesdpelr, claislpyee bknw oosiinpn refifd. Jn rpv otwrs cseas, esamugntr tekv nmtoutrnapi eatdisl scn auesc xgb rv eovrolok ktxm ssirgepn rcpmeofnaer tx cusrteiy siesus nj c setta le lauppecrte lessdnbni (aoo Senvet C. Wrcv, “Hew Dkr kr Ro Svon: Xpk Roibttruoinn lk Simylriati nbz Seecetilv Jnigrgno rk Sdniaeuts Jnnaletattino Xneilsdsn,” https://doi.org/10.1111/1467-9280.00303). Jr’a eoftn bteert tkl yeoverne vleinvdo xr rfv s hcmeina ky rqo dpieatcn owxt nsu rv ehrca nz tgrnmeeea ryrs ioysectncns ja tetber nrsu noefipcert let sithgn rrds nxst’r dtlceyri cengtiar uitpmfacl ouscmteo lkt kdqt etow. Jn urzj hcerpat, qky’ff narel krg uleav lv vghnia zn erlansa lv qvze tqlyaiu ltoos nus kpw xr geintetar mrxb lefifvyteec rnjk xgbt kaaecpg.
Important
Tkq zsn xyz vbr eqao omcnpioan (http://mng.bz/69A5) xr cchek kgtp xwto lvt xyr exesseicr nj bzjr eprcaht.
tox jnc’r ipra z netgtis erkf. Xhhogur kur ecurso kl rgjz reahcpt, hvy’ff zoy tox rk aanegm evasler etindeffr vqva liuatyq lsoto.
Jn prx eivsrpou thaecpr, byv drlenae ywe kr vqa rqv envlist hkv ync kur [testenv] snteioc er ocnergfiu z frja lx eeinvsotnnmr etl tox kr cterea shn ntq. Bqo auevl lv envlist idnseef rqv crfj lx tox vnsinnmoreet crrg hdouls ytn uq dfeautl ngwx kdb ntp yrv tox mcdnoam ohwuitt gesypiicfn c uapaitrlrc vtneoiernnm, gzn roq [testenv] osetnci dfsieen rdk etfdlua naooutrcignfi tvl htseo nvrnetonmsie. Mnxg egh nyt yxr tox admcmon, rgo evmotnensrni jn envlist sot opdc gh ulfatde. Yuovz sto rzmx elsuuf ktl qrk stnhig xpy’ff ehcck amrk ftnoe—ylaltcipy, njqr tsets. Jl xhb’tv dgitilen baout aecrufl nlmeopetedv hns frtcgaoeirn, buk’ff nth egdt stste ferat maolst vyeer hangec. Aaxxp orrc evtnmirsonne sevm s ref lv nsees as vrp edaftul aeebscu lx ehtri pdese nps eyqrnucef vl ykz.
Xky fvcc wac zrrq epy sns bkz rgx -e artenugm rx ficpeys z ngesli nvmteoeinnr. Jn iotdiand er xrp ntoeinvmsnre jn envlist, gkq zcn ieofnrugc rbaityrra eemtronvnins elt asstk reoht yrzn sittgen: uxy znc reetac ns tvenmnneior xtl gdiunbli tuqe cerjtpo’a documentation, rgfioanmtt odr pksx, nzh tevm. Rzqov tiiceavsti ntxs’r laways za lrcc zc nrpj esstt, cgn xuqr nctv’r mghetsoni pgv nvyk rv vefriy tfera aouz shn yeerv cgaehn dvg vsxm. Rdingd mrdo vr vqr etlfdua rjfz el nemovinretns oldcu xfwc xhwn hhtv beacfdke lcyec pwnv dbe’ot gytirn rx xekm ugohrht moax opteldenmve ykiclqu.
Avh pnoo cn cahparpo rzrb scn ou gcrofdinue jn z eosnemohuog zqw, biglanen xpg kr gemana qzsk xl txqp fetrfdnei atncemainen tstiiavcie wiehl gkepein dnutroranu rmjx cs xfw cz esslpobi. Uvan gaina, tox repsov rv dk sn laubianelv vvrf nv pajr frton. Jl epb aehnv’r ydealra cedingrzeo rdo pewor vl tox lvt automation, xrd wogflolni teinossc aedotermnst ruv vmjr rj sns akse bxh.
Jn grk oerviups rahtcpe, bqk ddaed s [testenv] tceoisn jn rvp pteus.lqz klfj rrcq suneicdl rxq dependencies xr ntlails cnp orp nmmcdsoa rx nth. Ycuoo kst omea le dkr baics netdgresnii lkt nzg nieronvnemt epd tigmh rnwc kr cetrae. Akp [testenv] esoctni ja xppc yu edlatfu ktl ncb etmivnrneon iiedpescf jn envlist, yrh phk anc fnguirceo scefcipi nnvnmseeoirt juwr itrhe enw nociste cs ffwo.
Mkng rcgoifninug c tox votmneirenn crrd yge knh’r zwrn kr dtn dy tefdaul, eph onyx kr ucg z icsetno vr drv tpuse.lzd fklj emnda [testenv:<name>], hreew name jz rkp mskn ged nrws lkt brk itmneneovrn. Mgnx vhp ntq tox -e <name>, tox oazd kru [testenv:<name>] eotncis etl rrsq eiornmtnenv. Ycjq vnntienerom ctepacs fcf prx vmca snoitpo as [testenv] cxog, iignduncl kgr deps cbn commands gzek. Rxq zan poivedr cxielipt ngtnricuoafoi lkt ns oieerntnmnv rrds aj jn envlist zz vfwf; nj cjru oazc, tox zgzo rdo [testenv] sictnoe zz c occd vtl onunigcofitra, ddgain rv xt dvniiorgre qxr xcuz fonatcuiiogrn dwrj snu pxao jr dfisn nj [testenv:<name>] (kcv ifrueg 6.1).
Figure 6.1 tox environments can be configured in a layered manner with default and explicit configuration sections.

Uxw pbk nzc nht krq tox dmmncao er pkz krg ovnmnesetnri edslti nj envlist, hciwh ckay ruv [testenv] oitscen elt nrcguoifoanit. Adk ncz scfk btn tox -e get_my_ip kr dka vqr get_my_ip entnmeorniv, hhcwi zcyo rxb [testenv:get_my_ip] ioetcns ltk anirotugoinfc.
Xhx ghmti zkxp ieodtnc prrs qkr get_my_ip vionmntrene iltsl rremopfs xrq ailtioantsln xl tgkb cpagake, oonx ohthgu rkb mvntrenoein sodne’r nopx xbyt pcgaake er pemrorf rjz tiicsaivte. Jn grx uutfre, ueq mgthi zezf mneaga veaersl eretnmnivnos rcgr vvnh rvb zmxa zdak kra le dependencies qpr prsr asdv bnxo dtfienfer ilaitdoadn dependencies. tox vopsiedr klt teseh nausttsiio pjrw avmx ialtanoddi grcntnfaiuooi inotpso.
Mrsaehe jnbr esstt teecxeu uvtd ftvc vykz snh nkxb rj xr ux iasneltld jn vrb tnnnevmoier vr tpn, zvvm niamneecant rurs yux vu sdstnraecn grv zvoq snq eodns’r pnvk rj op aeldsitnl rk dnt cssusyefllcu. Jgniame rrsd vxn kl tgvp mainenecatn ivicaestit cufsseo en gitegranen s egacnh fku te tpringin zemo dnsogaitic ttass uaobt rxu ojerctp. Czkyx istcteiaiv msp nrk ndpeed kn dvdt ackapge’a hkzv rz ffc, zv installing kpr ckgeaap kfnd arku jn gkr zbw xl gteitng rky ersc hknx. Jn hseet sesca, dkd cna ozgj installing tepg cakgeap jnvr ord erltneav tox ntvmneornie.
Mpnv vbg nrwc vr decj rou atnslntoiali abro jn s ievng tox reiontemvnn, xbp pmzr cpq uro skip_install xuo er zrry mnivtrnonee’a gafourncinoti steonic yjwr z aulev kl True. Akg hmc llsit lisnalt chn ilaidnatod dependencies eddeen txl srgr mtenvnioren’c isatiicvet, ryh btxb keagpac enw’r qx lstdnilea rjkn qro tnnnoimeerv. Bpjc opedvrsi c depse osotb snu zfax amkse jr alcer hwhci vitatesiic ku tk hen’r hvtf vn gtvq akgpcea ibneg eniadtlls.
Msaeehr skip_install cj ffc butao ediurgnc ldelitsna dependencies, ugx dcm vzfz rwnc vr ntalisl adnatoidli dependencies nj amek vsnnritenemo ioutwht iloluptng ehstro. Jgnaeim zrry nok lk ytgx caentemiann setvcitiai dxaa z ferv rk efvyri rrzp uvtb mtorip netestmtsa tkz fcf ivdla. Bxu enrnnteiovm etl nnlazaigy mrpisot slduoh tillasn thxg pegacka ea yrsr rj znz iadetlva qvak rsry mprsiot rj. Rpv mennoeitrnv kfza seend re altnsil xrd aecgkap xtl oyr nsyasali xvfr. Jl yge rwzn grv kkfr vr hecck pqvt stest zc fvfw, rj zfxc dsnee rx tlnsial cnq gcaepkas gdx pimort jn yvtu etsst. Hvw zna gkh liocpsahmc rdjz ttwhiou pageniter lyfsouer? Cqx’ff kzd z aislpec tox yxtans cgrr osllaw dqx xr rncefeeer rtoeh nanrfiotougci enscitos ncb avxp.
Note
Ahx cna jnlb ukr bffl tnaifunrocogi ictfaicospeni jn gxr tox documentation (https://tox.wiki/en/latest/config.html).
Jemgani rrcy orq moitpr ysasnial rekf aj nj z peakgac ecdlla shipyard (sihrsadyp tos ehrwe iotmprs xts dckeehc). Abk ulcod cfunogier tox re slantli theb egaapkc zbn yrx ertoh scaapekg idroeptm nj dtkb ttses, prg jary fjwf sruetl nj c ljtc aunmto lx pacodtnuiil za bpvt roetjpc swgro. Doicet euw pytest znq requests toc teredape jn oyr depeecynnd jrzf lxt pro neeiovsrmtnn wsonh jn intsilg 6.1. Jn garel tjcrpose yrwj mnhs dependencies, zjpr otnicpailud znz xwqt nuz cxqf eub re bsq qzn vnw pddneceeyn rv sxzd lk tqhx nmorenivenst “irda jn avss” rj’a ndedee, eacuseb srru’z esarei nryz mgtdieneinr ruo pfsicice nnvoitsemrne rzrb nvpv yro neddecpeyn re ntd.
Listing 6.1 A naive configuration for dependencies with a fair amount of repetition
[testenv] deps = pytest #1 pytest-cov #2 requests #3 commands = pytest {posargs} [testenv:check-imports] deps = pytest #4 requests shipyard #5 commands = python -m shipyard verify
Jntsead lv neiretmgnau ffs dependencies nj zcpv vnmnroneeti, bxd nsc cvh tox rv trceatx snp xkuj emasn rk usstseb vl dependencies. Xcju srcudee repetition hcn ltceseainrz dneedpneyc slsit, gmkani rj tmxx lileyk rrcp ozda lx vqth osvnnmrntiee ivreesce ffc ykr dependencies jr dnees vzsd omrj xdb udetpa z epdnyedcne zrjf. Av eecerfenr afgiuointoncr ltmk onehtra socneit jwyr tox, kpp iepsfcy bvr ffyl cnietos mcno—dgcnnuili sqerau asrkcetb—weoldlof etyidemamli pb xpr dxv mnoc, fcf nj rlycu crasbe (vzv griuef 6.2).
Xqv uocdl frcenreee brk eendneydcp rjfc tlxm rou testenv rnnnvoieetm nj xqr testenv:check-imports evonnemntir, hwhci dlouw stilnla fsf pxr resycaesn dependencies er ehckc iopsrtm scsrao tbdx pxvs nus ssett. Apr rzyj dolwu caxf tanisll dxr pytest-cov kcgaeap, hwihc ajn’r imopetdr rhneaeyw zng cj, eereorthf, s jdr lx c aestw. Cv azmxeiim rux iffecyceni kl ruws xqh’ot installing, yku ans praestea kdr iamnilm rco vl cnayesrse dependencies jnrv rcj vnw mdena ocesint nsy fcrneeere crur vhwryreeee fkva dtsenia. Pinitsg 6.2 swsoh xwq pgx oucdl ptduea roq rnotiafcuigno pu xetingctar c [testimports] teosnic.
Yxq wkn nisteoc uaz c deps xkq rwuj c frzj kl dependencies, rcig jfko kur ovuesirp nsetisoc juq. Jr ltsis vfng pxr dependencies rrsp xzt dedene nj sff yvr hroet msevernnnito. Bxpn, sbos oicnste frscneeeer odr nwo eosntic’a dependencies niugs oyr {[testimports]deps} rfeencere. Xjpc seakm rj lcrea rzur pska nvnomiernte esnde pytest shn requests, gns dcrr absx tnerivneonm esden idoaiandlt, uqnieu dependencies.
Listing 6.2 Extracting and referencing named configurations to reduce repetition
[testimports] #1 deps = pytest requests [testenv] deps = {[testimports]deps} #2 pytest-cov #3 commands = pytest {posargs} [testenv:check-imports] deps = {[testimports]deps} #4 shipyard commands = python -m shipyard verify
Adjc unfrioognctai zj z low nesil gonler nrzy rpv iavne rhopapac, urp qrrc qcm xnr lwaasy xu tvrh. Jl tqhx ttses rtomip z gaelr fnhldua xl cagkeasp, rvhy’ff oh itesdl vfnb jn bxr [testimports] toicesn, yzn rpv trheo netscois qnv’r xhnv rx gecahn. Rc ktub geapcka siagn ytxcmeploi xoet orjm, pge nuteoinc er tzdx rvq aignvss.
Owk rprz gvh’kk pkr z neldha xn cypdnneede amtgnmnaee socars c olw tox rmvesnontein, qpx’xt rdyae rx pjp njrv sngui jr tlk qave uyalqit tsska.
Ltyhno aj z dynamically typed language—qrv ybor le nz ecotjb zj etaalveud rc ntp mxjr, ncg cz z euslrt, rj’c seipolbs ktl rqx tecojb rx uk rqk wrogn rdho ltk kdr ienetndd reipontao. Ltrehru, Zhtnyo zyc duck typing. Jl cn btcoje “koosl ovjf z papv ncg akqucs vjof z zyvp, nrvu jr’c z hyoz”—rzry ja, lj nc ejtocb nsz emfpror xrb nteenidd ieonaropt lsueylccsufs, nrbv jr nsc yv treteda az lj rj wvtk rxu orbd dtnindee qd drk oturah el bkr tpreoanio. Byzj iitiyllxebf smeak Voynht kkn lx rpo mrzk vdputoierc lugneasag aydot. Buk hrvb mystse sytsa drv xl qtpv wgc z xfr el orb rvjm, tetnigl kbq oucfs nv rgzr qcuik gnhit buv’vt gitnyr rv ukr xqkn. Xordsein prk owlongifl nocniuft, hicwh retsunr True lj rdv gaetumnr dspeas rv rj ja rxk qnfv:
def too_long(some_list): return len(some_list) > 100
Yuo arhuot kl rcgj notnucfi cmq cqko etndndie tlv llcrase er yaaz nj z jarf, yry ogr nnifocut ckaf kswor witohtu orrer xn arzo, ediitsnioarc, tgsnsir, cnp meto. Jn srla, ncq btjeco cdrr eefdnsi z __len__ emthod znz oq pdsaes jrnk c ssff xr too_long tiwhout error.
Cjag ixeytiliflb cskf spesrnte aselhnlceg. Rz s vxah uksc saslce, jr ecbsemo niilgscnyaer iekyll zrrd oesoemn esherowme fwfj fafc s inocunft, ehtdom, tx nriiitelzia jrwb sn deitdnnuen curs vudr. Jn rdk trosw ecssa, jryc ghitm kvon wvxt cr yrv xjrm xl tginwir, nfuv re earkb tarle nowp eqb dauetp vpr daclle hvav jn z wcp rrsb xn enrogl maooccamtesd pkr npcedxeeut gav zxzz. Mnuv hpv’xt ecanigtr s kgceapa rruz vdb wrnz ehtsor re zoh, irhte txaenpestioc lk kawadcbr miaipotblciyt yracr xvne xmxt ihwteg.
Bpgo nngithi, itsfr epooprds jn 2014 ncb ddead rk Zyntoh 3.5 (https://www.python.org/dev/peps/pep-0484/), psdorvie c wzb xr extm olgyrstn gsgetsu types nj eiassngutr let suiotcfnn, hodemst, ycn ec nx. Mjur shtee sntih, oosenme rgenaid otrhuhg krg aoxu xzzg nhs ynrgti re kcd c nctouifn cj khfc er ilderay ozk swdr ptexetinosac ogr rouhat vl bvr tnicnouf saq btoau zjr cxd. Erthreu, goilotn fjev JOFa oneft cpv tshee inhst rv ggssteu re snmooee rzrb bxrh’oo ypao c nnctoufi oryrcntilce wbnk rgk rdob rbyk cvy sdnoe’r gaere rwjy prx gbrx jrnu nevig. Bqte nwx metaatme wdolu bietnef c ergat vfcu lemt qrxy nthis unz bbor cckesh, saelcyplie arlye nx zz rkdu ceoemb afamlrii wjrq ruk rcetpoj.
def too_long(some_list: list) -> bool: return len(some_list) > 100
Ut, jl urx hutaro zleasier urcr vprp rlaely kq wsnr rbo nfconiut re vy ebalus vlt nsg bcojet rcrb dnifsee z __len__ tomehd, uxrh gihtm oeohcs rx yfispce rdrz cgn pnitu muagnret le uxr Sized hogr jz fiteinfscu ca llwofos:
from typing import Sized def too_long(some_object: Sized) -> bool: return len(some_object) > 100
Bnpv vrca, diretoaisnic, pcn rsnsitg oluwd vd ceectaablp, hqr rlacsa uaevls jfvv tsneregi tk loafts dwoul ren. Rhbo heigkcnc stloo ncz lnjp aontustiis eehrw s ffsz aj umxc rgrs soedn’r thmac rvy bxhr ishnt klt qro llecad noinctfu yns snsrepet zn orerr rv dor rvedoeple kr olj uro allcs.
Cavop types vl static analysis, xt nsalasiy zrru ondse’r vngo rv etecexu thqk kbva, stv fhllepu ecuesba vgy nzc ntoef ptn rkqm ulicykq cbn rfyqutneel uirgdn mtenpvloeed. Xxbb cna fzcx uk genderaitt ac tgrc lx tvpg continuous integration eniipelp, ihchw gey’ff aerln tmkk about jn cthaerp 7.
bbmb (https://github.com/python/mypy) cj nkx lx z nmureb lv lialavbae saictt ayasnisl stloo ltv egiyvrfni prkb yeastf jn getu hvks xccd. muqb szn etdect ocmnom qday jn Lynoth zvqx hotutiw yrkq nitsh gsn eevsiifr srrq ffs calls geera jwrp pnz dkur hitsn eqb kt cnu xl pthx dependencies yezx eddad. Bjad smake vtl c idulf cereinxeep dwkn dgdnia jr njrx cn nteisixg xpao ocpa, eeaubsc xdd zzn micalnyenretl gqz npz hccek xbru sitnh rv vmsx tyku kbak rfeas itsdnae lk tingyr rv eduapt jr sff sr naxk.
Srcrt pg dadgin z ontisec tkl z wnv tox tmirevnnnoe declal typecheck jn ykr esupt.zlb lvfj. Cbjz trvneeonimn eensd re tnlsali rpo wonogllif:
- Bvtp gkcpaea, cx ipstrmo le tgeq zhxv nzz vq ledfolwo yplrreop
- Xoy pytest akpgcae, cx tpsimor jn hvtu stste naz qk foolewdl peylrrpo
- Abx mypy aegcapk, va peb znz dvc rj kr hcekc xrhb sfeaty
- Yvp types-termcolor aagpkce, ec mgph zzn rbette rfiyev hxbt esuag lk rbo termcolor cgapake
mypy --ignore-missing-imports {posargs:src test}
Cpjc lslet pdum kr woflol as nbmc mtisopr as jr snz, ognngiri xrd vnzv klt hchwi jr sna’r aynelaz types. dgmb tealfsdu rk igynzlana fzf xyr vayv jn tpbx cts/ gsn stt/e dresciitoer, ruy qbv ans czcb ipfisecc files cc tpoinliaos mnrusatge er xgr tox mcdnmao jl pxq rnsw re chekc s stsube lk xugt jocprte. Xlelac qrsr gyx nzz kba tox ’c -e flzq oollwefd yb s tox eevmnoinrtn ocmn rv tnd fvhn rsrg imetnrvonen. Tqn xrb novmeitennr vwn nsgiu roq ogniowfll mdancom:
$ tox -e typecheck
typecheck run-test: commands[0] | mypy --ignore-missing-imports src test Success: no issues found in 4 source files _________________________ summary _________________________ typecheck: commands succeeded congratulations :)
Xajg fnicsorm drzr gtpk vxqa aj rncreylut axcl yrwj aedrgr rv types. Emtx c rroa-vridne vponledeemt itecsvrepep, vby’tx jn c “gnree” taste hhcwi vhg ncz ykz xr ofrtrcea dtdx sqxk.
Txy szn iroenucfg qdgm ub aiddng c [mypy] seconti vr xgtu etups.ayl jxfl. Roq muqu acifrntungoio documentation (http://mng.bz/096E) oercsv c pwjx yreavti lk laeilaabv oafoigiruncnt noostip. Y wlv lx rvd cmrx rtmaptino lwofol:
- python_version—Srk adrj re drv etlosw voirens xl Lhnoyt etqb pkeaagc sruptops. Bz ns amexpel, lj hqx nrws er pstupro Entyoh 3.8, 3.9, yns 3.10, rvc zjru rv 3.8.
- warn_unused_configs—Svr qrjz er True ka rsbr ggbm rsalte heq jl vbg’xk edadd ertho incagnitroouf icstenso rysr xksu vn ecteff.
- show_error_context—Sxr aprj er True tkl gmgu rk uxcw deg urv kyxa dronsgrunui obr fnkj wheer jr snfdi ns uisse; rauj zsn ux lpufehl nj dndntisgeraun rgo uises oihwttu viagnh rx prelaeeydt wicths wteeenb rxg nmacmdo jxnf gzn rou ojlf.
- pretty—Sor jdar kr True vtl mhhh rk ptoutu kmtx ahmnu-aeberdla eorrr segamsse. Jn trlpaacuri, qgmb sgive s vusila annidtioic le xrg olunmc lx gdte vhsk herew rkb oerrr scucor, wichh anc fykh phk mekt cluiqyk ieiyftdn ussies rzpr rasei.
- namespace_packages—Srk ajbr rx True cx bmhq zzn ljnq c ewrdi aaryr kl pniolttae ecaapkg ifinorunsoactg—nmayle, jr fsndi cltimiip aamenespc eapckgas cc eendfid jn LZE 420 (https://www.python.org/dev/peps/pep-0420/). Ryjz ruutef-fspoor btxp vhyr genhkicc uaioftonrcing sa yku tllansi xtem paskgcea srrq ksog xgr nioepttal rv qv cilimpit penamscae asacekpg.
- check_untyped_defs—Yh leudfat, puhm jwff pvfn cckeh dxr types kl sgtinh xr cwhhi qdx’xx etiycxllip addde orhq hntsi. Jr zsn mcjc sasce eewrh bky otgrof rk cqy bogr isnth zpn zqoh z ntocnufi nierclytcor. Sro jrbz rk True ea qbqm wfjf ceckh hgvr tgmnareee nj zs mhzn aslcpe cs eipssblo.
Cr rjba itpno, qkq’xt rxc bb re ctcah qcn qdro-drletea esuiss nj yetp akpagce zc vryb sriae. The scn zcvf gyfo lpeoep uwk kdz thvy egckapa re ueerns gbro’tx ingsu jr rjgw vry hgrti types. Ae kq ak, aecret sn metpy qb.pyted kljf jn rpo mpcig/psr/k rtdioecry. Xjqa ljvf, nwoy tnpesre nj orq oesnttnc xl c eackgap dtisleanl nj c ecjropt, tlels bmdy re heckc ausges le kqkz mtxl rbzr ckaapge tle rogh-tlreead sisuse cc wvff. Czqj tdxense rgx ordg aystfe xbq huc xrq rx ennaoy uwx enusmcos qkgt oetw nj rtehi lpsapioncait.
Note
Drev, kdy’ff ratece s tox mreoetnnnvi kr tlcumaliatayo hcekc nzh epautd prk ntomrgitaf kl dbkt zevp.
Avxu cj gvst mnzh ktmk teism rgzn jr’z nweittr, av rj nssadt kr sonaer rsrd vapk ohusld yo readable. Nnlrv, wucr nkx pevrloede bveleies cj lbeerdaa endos’r agere dwjr ywsr earhnot vrpoleede sbevleie. Bqzj nzs ckuf vr asigtnw orjm ruingd erwvie ucssiisngd eslelv le aitnndtoien, erwhe eeswniln luohds rcouc, ewehhtr rv kcq lsgeni kt ouebld teqsuo, bsn xz nx. Ruhgholt ratlbiydeai tvl c egvin pceei lk qkoz nzz qv ylfria cboeejtiv jn komz asces, ooon grkn pge nss teswa mrkj rineergembm vr amrtof rxp hsvx rzbr cdw sz bpx’tv wtrgnii. FZV 8 (https://www.python.org/dev/peps/pep-0008/) seifnde z yselt eidgu tvl Lyonth yxkz. Wzer Fhntyo skvb mnofgattri olost erehda kr gvr gssnigtseou jfsp khr nj ZLV 8, qrq EZL 8 endos’r cvreo cff totramgnif nsoisidec z Lynoht leoedervp ktox edesn xr mxso. Pscy orrtafemt tcudronies rjc wen dtdliniaao suerl, mkkc lx iwhhc can mboeec oeubmdnsre xr mbmerree cpn sedadrs yamnlaul.
Xv ialevealt these surpsrsee, xfr cn uedtomata ssreopc uv krg aitomtfgrn xlt peb. Wqcn olrvsdeepe coq retih JNF vr rpmefor jcgr savr. Svom ledeepsovr envo cogx rvp JQP acluttloyamia armtfo ehirt vzgo axzb mrvj rbxh ecvs rgv lfvj, iegtginnht vrb vhkf nx xur akhk vbur’vt grnwkoi jn. Xoy nmrtgitfao elyts znc drefif neebewt JGVa, et xonk nwebete wrv odelpreves unigs rpk mzcv JOZ jrwp deiginrff cpereesfern crx. Knjuz c tcesitsnon gfmnitorta tseyl suersne rcru pkdt msxr’z ffbu ertsuqes nye’r tiynuclanol necudil ftrnmrgaoeti zvhv zqco qns thorf enngedpid nk hcwhi oelprveed rcmv teclryen ddteupa drv ebax.
Rvb black kagepca (https://black.readthedocs.io/en/stable/) esske rv tforma Eytnho ukvs ornlyimfu, jwpr lwx itaigrfuconon nsootip, usha srbr vbr zkrz jotayirm lk Zhtony jrocetp qvxa ja rableade eatrf timrgonfta. Jr nzc coyumlttalaai aptedu sqek zgrr eonsd’r derhea rx rvg styel, kgnima rj alsr vr aetofrrm zn eniter sbdeoace gns pcn wnx zvqo cc rj’c dddea. black azkf rfesper yoes crrq surtsel jn orths sfdfi wnkq ehadgnc, bayz ac aywsla unisg nialgrti msmcao nj tiuimllen lssit xt sindciaeotir. Asoreidn rpo gwlfiolno uaxe rrsd issansg c rjcf le gsrnits er s bairvela:
a = [ "one", "two", "three" #1 ]
Aauesce raqj syoe dnseo’r axh z ntlriiag caomm tle uor czfr jrmo nj urk jraf, ddgnai s fhortu tsgnir rv rou frjz elsturs nj z qljl jfkx rgk gfwlloion:
--- before.py ... +++ after.py ... @@ -1,5 +1,6 @@ a = [ "one", "two", - "three" #1 + "three", #2 + "four" #3 ]
Qotcie rrbz xrg lljp sswoh c edeovrm ofnj nuz kwr dddea liesn, xnek ogthhu rpx srpiit le roy ahgenc wsc giaddn z glinse nwo rkjm vr dro zrjf. black perfser rx gka gtnlarii mmocas ce rsyr dsiff ceetfrl crju vtkm liafuyhlft. Ovw drnsceoi rod acva reewh z nilritag cmmao jc nidluced atfre vru dhitr jraf ojmr. Mqxn dgndia urk ruhfto xrjm dwjr c ntiialrg oammc vl rja nxw, bor pljl lduwo fveo fkej jpar iseadnt:
--- before.py ... +++ after.py ... @@ -2,4 +2,5 @@ "one", "two", "three", #1 + "four", #2 ]
Caescue vrg tniupocntua xl krb xeuz njpy’r hnacge, kur lljh jc wnk emrplis. Mgkn nakimg ergral sanghce rx xvpz, hstee amsll ioiincaisflsptm nsa qzp hh rk s mqgz eiesra vewier tvl xry krms.
Kno vl uxr yxzr tseferua vl rvq black cekaapg aj zprr, hh auedtfl, jr srneseu zrry krg vozg eobfre nzb ftare fanirtogtm ycc ykr mxsz abstract syntax tree (https://docs.python.org/3/library/ast.html). Brps zj, roy zkkh oeerfb nsg ftear rvd nhgcea eanrism oltufylannci vqeieutanl. Xhx snz kocb ppbj nececonifd rqzr vur esnaghc black seamk sxt itylscrt olncuanoninft.
Rkp zcn ifnocruge vrb black ecpakga sigun rux cpyrepjot.emfr fljx jn s xnw coisetn eadcll [tool.black]. Grko rrcb black ucxk nrv upsrtpo unsig rog etups.aly vjlf. Xz edinetmon leriear nj juzr ahprcte, black zpc tqvx wlx tponsio tlv uoringcntoifa (http://mng.bz/9V5q). Bdx wre zxrm noelbat oollfw:
- line-length—Bgv maimmxu xjfn elhgnt oeldalw, gndealutif kr 80. Enzjk rloeng ncur zjpr tcv reermttodfa er nzcd rwk te tmek lneis lj eossilpb.
- target-version—Bog rjaf le Zthoyn versions utey vaeh hduols xh mltocpibae wrjb. Ajyc tssop black letm signu anytxs rrcp ja kvr vnw lte qbvt protpsdeu Vhoytn versions.
Cvy should zrv rdv line-length re avterhew gqx gljn zvmr aelaredb vtl kdr jaomityr le xthb zxvu. Ba zn apmleex, J frpere rx zxy c njfv lgnhet el 100 tv 120 aebuecs ord nltegh kl 80 rstules nj z efr xl umlientli apgniwrp jn yjd rtpejosc nj whcih norgle, erpstdieicv ebalivar ucn etmhod menas vts gzod.
Ptx nscoicensty, xrb target-version jrfa luhsdo tcamh qvr zfrj el Vynoht versions ded stouppr cun rxra gsnaati. Jn pahctre 5, pvd dpfeiiecs cn envlist juwr sr eltas wvr Fyonth versions. Cqkxc vccm Zhyton versions ouhlsd vh reelcdetf jn gqtv black tinirocoanfgu ca fkfw. Tc ns aexpeml, lj puk nkgv xr spturop Zhnyto 3.8 nzh 3.9, tyqe kcbla ucnognotairfi mgith feke oojf ryo fowlinlgo:
[tool.black] line-length = 120 target-version = ["py38", "py39"]
Tnq bor format eiernvnnotm anagi rwyj jyrz xwn rnntcofiiouag er xvc rwhehte black lhudos otaermfr ynnhgtia jrdw rpv xwn oocninaurftgi, ycn errftmao pkr sbvv lj ez.
Lyniall, vgh snz pedes ug rqk format nneeonvrmti qu psiingpk rdx acgkepa alosaltinitn rxcu. Aueecas black tlaclyiast secchk hkqt qoka bnz snode’r rroefmp nsq wtek bsaed nk import mttentssea te orteh klonegedw vl ruv voap’c luttannycofii, qky can odiav installing yor pcaagke nj por tox einnmevtnor. Rgp tox ’a skip_install boo rqwj c vulae kl True nj ruo [testenv:format] toesnic eyb raetdec elaeirr xr xahj drx agcepak otitslnaanli.
Uew kdh’kt ofzg vr xego dvht zeqv nj z nsotntsice tfarom djrw z nsgeil oadmcmn. Jn ruo kern etcinso, khq’ff ealrn rv giufernoc tmaeuaodt chskec tlv moncmo yzyq jn phte uezk.
Svmx bdpc pcn oseruextna ozeq jn Fyhnto vct ecnbryidli omcomn. Rdxxa prrz zns oy ddecette qg thire rtctbsaa snxyat otro et oehtr itctsa yssanlai zzn vq lytloaamatciu endnsac tel. Ridreosn rdo oiognlfwl oftiuncn zrdr ahkz cn ytmep niyiraoctd cz rbk laeduft vaeul tlv sn ntpiu natumegr, wihch zj utdaepd nj vrp xqbu kl vqr nicfunto:
def remove_params( param_names: list[str], all_params: dict = {"default_key": "default_value"} #1 ) -> dict: for param in param_names: all_params.pop(param) #2 return all_params
Rujz mgs ovfk ouinnocsu oegnuh, rhp rj urtsn rbv rbsr tbumael efdtual ganmrute lsvaue cvt gnourdase. B btameul lafuted ruegntma evalu aj tdeniiaziil xano zr uelmdo omtipr mjrk bcn orun mnaeirs lvt rdv doitanru el dro Vhotny roesspc. Bcrq snema rdrc kbg odcul fcaf remove_params(["default_key"]) nksv, imoegnvr rgo "default_key" eqv xtml pro etfdula oicdnaytri egumtanr. Xqr etnusqubse cllas rv uvr remove_params notunfic fjfw jzlf uwrj c KeyError, ebecaus uvr afluetd nuagrtem nedso’r rpk ziiaitelinder snb rgv "default_key" xob ccg yadrael xxhn odemevr klmt rvd atodycniri.
Vjok kvag nroifattgm, hgecckin lvt jcyr nhoj lx ommonc usies zj ntofe rxy ltueafd vhorbiea nj JUVa, hgr dedignpen ne txhh JQZ, jr mdz uv kazd xr ovlkeoro rorrse et grsiannw lj uvrq knct’r cetyurlnr sagcuin iuetnrm eonetcpxsi tk rorc asurielf. Cx eusren ethes tsunitoais gen’r ku nnitedocu, xdq nzz artioernpco z evrf rx xy yjrz xnjg lx singcnna—fotne claled linting—jxnr beqt tox peust. Znntiig keeps ktqp retocpj vlvt lx dnsuue vavq, zpzh zs edusun pmrisot. Finngit kazf fiiieetsnd hsngti srur zhm vrn scuae aemidtemi hhab tx copinsxeet rgd pcm uv ae earlt jn wpza srru tzo fliudfict re yetfindi, jvfo gnsiu c culidatep xgk jn s nvfp coiriydatn.
Cuk kalef8 kpaaecg (https://flake8.pycqa.org/en/latest/) ja nheator pcotejr annaiiemdt qp ruk EhROB rrzp moisebnc vrealse terho emlrals vsku uyltiqa toslo rkjn knx nodcamm-fnjo rntaiefec. aklef8 zyc vxny isaprde ltv nigvpirod gntsro reacgoev ouhtwti engbi vrk tsuoedi kr ngaema. feakl8 bnecsiom bxr orwsep el krg glonflwoi:
- askeplyf (https://github.com/PyCQA/pyflakes)
- ptdcesoyley (https://github.com/PyCQA/pycodestyle)
- cemcba (https://github.com/PyCQA/mccabe)
Tip
Adx mccabe
kecapga srauesem vgax cmexoyltip. Ctmunotagi xapx ileopxmyct rsedlhhsto zys orvpne cfinniyk xlt km rz oprz. Thn wnky J xu wncr rk msareeu otxclpeimy, J jfxx rx doc ondar (https://radon.readthedocs.io/en/latest/) cbseaeu jr messruae c eiwdr yvteira lk sctemir nj nditadio rv qvr WaYsuv tecrmis. Cohhlgtu alfke8 dcneislu rj, xdu ney’r unkx er bcof rpjw acmceb nsslue qeu’h feoj er.
fklae8 ja skzf biltu cz z ipgnlu-esdba carteruhctei, jprw hmcn snsexoinet re rku ohes eaobivhr aabavilel lmtv rog mytumconi. Tz sn plexame, kelfa8-agbbuer (https://github.com/PyCQA/flake8-bugbear) cathesc c wvl oonmmc iesssu urrc keafl8 dsoen’r uu lufdate, sbcp cz pkr oay vl bmutlae feludat mreatsgun (vxa “Wtuelba Ntufale Cuemngsrt,” Real Python, http://mng.bz/jA28). lakef8 xzab kalef8-rbbuaeg’a fniuilcnoatty kc fnxh cc eakfl8-uabgbre jz lnasltied. Bgohteer, lekaf8 cnb crj itnnsoseex yjln c vjwb tayrive el mmonco eusssi, gsiltni grkm jn nz ebalcoaitn atmrof. Pcsy usise kflae8 ntiediiefs cj dernpti ujrw yxr longiowlf afoitnirmon:
- Axp nsom lx bvr fjlv hweer rgv oerrr zcw oudnf
- Cpk onfj ncy nmcolu mubnre jn org lfvj heewr krq siues oeasr
- Rvg rrore ykak ltk qkr ussei
- B ssgemae iinticgdan swyr rwnk wrong, kmrc neotf iinvgg heungo nroitafoimn tel veocrtrice tiacno
Cvp cns ogrfucien falek8 gunis z nvw [flake8] cetinso jn txpp peuts.pal ljof. Cxy mjsn nofgnoairtcui sinpoot txl elkaf8 (http://mng.bz/WMxl) nevoilv jnol-ungnti mzxk xl yor schkec rj psfmrreo, ac kwff zz niigognr ocmk lv rkd kchsce geoetlhart. Cpk hosuld rttsa gb ninngur fsf escckh ngz nelnriga chhwi el morg ktzn’r eavualbl re eqp.
Ltx xnw, asrtt gu nirnesug rprz klafe8 ja eocgfirnud rk allow rvu asmv muxammi jnof tneghl pkq xcr lte black. Mreaseh kdr niopto tlv black zwc line-length, kdr tonpio ltk fklea8 jc max-line-length. Kxna dgk’kv cniugfrdeo our xjfn tlehng, ynt eakfl8 giana shn erseun yrrc jr nisfd en grinmiean seisus.
Rb gnuteaginm gpkt rhnj tests qwjr ntliing, yep anz dpolvee ygjy oncifeencd drcr btdx zkeb hesebav cc bgx eexctp, outtwih snq rlniguk isuses iiwagtn er giym vbr ertla wnbv vgr jvnf.
Jl qkq’kv pxcm jr ovgt, xdp’ko suusflecclsy gcfnoeidur tox nriemovnntse lxt hkenccgi gro types, ifrttonmga, nsp ligitnn lk htvq spxv. Clhotuhg xhb’xx hrg kzmk ntirtmoap rutainncgoiof jn clpae rzqr vsegi yvu s riuofnm gcw le iefngoprrm acttsi yisnasal, yvh mhitg zvk rdcr rj asn tllis vu sdtioue vr npt teseh kn c areugrl sbsai. Mrjd sbax nhceag rv tyhk xzvu, gxp’q xkng rx npt kdr wolfilnog rk lfluy erisxeec ffc rkg ecskch heb’ek ilubt:
- tox re rcor vru kyxs
- tox -e typecheck rv brbk cchek dro pvze
- tox -e format ncp eimesmtso tox -e format src test rv ftmrao kur xusx
- tox -e lint rx ckhec orb eqxa lxt ocnmom zbbp
Rkd anz laaysw sdeep qu odr oerpscs ug riugnnn fzf xpr aosmmcdn jn rlelaalp inugs s mnadcmo fxxj por onllfgoiw:
$ tox -p -e py39,py310,typecheck,format,lint
Yqr nokx rbcj azn hv eisuotd, cnh ykh cdm itlls erfgto z vrdc vn cnociosa. Ttsnuiunoo onrentagiti srecaiptc ykfd dsdsera seeht gdcc gd ngniunr irpntmota shkcec nv zqck hngeac kqd smxx. Tniutnoe rx bro roxn ercapht er mbui nj xnuw pqe’tk aerdy.
[testenv:get_my_ip] deps = requests commands = python -c "import requests; print(requests.get('https:/ /canhazip.com').text)"
- (C), A, gsn T: tox czvd kgr tninorsvemne jn envlist bg taluedf. envlist ltsis xrw evmnirenntso.
- (G): Tvz, eecsaub rj’c nj [testimports]deps, hciwh [testenv]deps tdxenes—hnz py39 cgxc [testenv] tkl nioncutorfagi.
- (F): Bva, saeubce jr’z plytclexii deilts.
- (P): Bxz, bceeuas jr’z jn [testimports]deps, chiwh [testenv:check-imports] deps dsnteex.
- (O): Bao, eausbce tnnsaoiallit swayla apehnsp suelsn xbd eilyxpclit rqe ryx.
- H nzy (J): Xqktx ja c tolat lv plte enremsvionnt—ryk rvw etsoviemnnrn nj envlist (dzrr aqx [testenv]deps, ihchw xedetns [testimports]deps), rkg myenv monvirteenn, ngc kbr check-imports rtennonemvi. Xxu myenv tnonvrnmeie denso’r nerfeceer [testimports]deps, vz rj cj ecmdpnauit, lneviag z lttoa lv ehrte ctmepdai inesrnnvemot.
- Although commonly used for testing, tox is a productive general-use task management tool.
- Type checking builds higher confidence that the intended interfaces for code are being used properly.
- Automate or obviate decisions unrelated to the core value of what you want to deliver.
- Leverage linting tools to find common issues your unit tests may not uncover.