Put do provjere tipa 4 miliona linija Python koda. Dio 3

Predstavljamo Vašoj pažnji treći dio prijevoda materijala o putu kojim je Dropbox išao prilikom implementacije sistema za provjeru tipa za Python kod.

Put do provjere tipa 4 miliona linija Python koda. Dio 3

→ Prethodni dijelovi: prvo и drugi

Dostizanje 4 miliona linija ukucanog koda

Još jedan veliki izazov (i drugi najčešći problem među interno ispitanim) bio je povećanje količine koda pokrivenog provjerom tipa u Dropboxu. Isprobali smo nekoliko pristupa da riješimo ovaj problem, od prirodnog povećanja veličine ukucane kodne baze do fokusiranja napora mypy tima na statičko i dinamičko automatsko zaključivanje tipova. Na kraju se činilo da ne postoji jednostavna pobjednička strategija, ali smo uspjeli postići brzi rast obima označenog koda kombinacijom mnogih pristupa.

Kao rezultat toga, naše najveće Python spremište (sa pozadinskim kodom) ima skoro 4 miliona linija označenog koda. Rad na statičkom kucanju koda završen je za otprilike tri godine. Mypy sada podržava različite vrste izvještaja o pokrivenosti koda koji olakšavaju praćenje napretka kucanja. Konkretno, možemo generirati izvještaje o kodu sa nejasnoćama u tipovima, kao što je, na primjer, eksplicitna upotreba tipa Any u napomenama koje se ne mogu provjeriti ili sa stvarima kao što je uvoz biblioteka trećih strana koje nemaju bilješke tipa. Kao dio projekta za poboljšanje tačnosti provjere tipa u Dropboxu, doprinijeli smo poboljšanju definicija tipova (tzv. stub fajlova) za neke popularne biblioteke otvorenog koda u centraliziranom Python spremištu otkucano.

Implementirali smo (i standardizirali u narednim PEP-ovima) nove karakteristike sistema tipova koje omogućavaju preciznije tipove za neke specifične Python obrasce. Značajan primjer za to je TypeDict, koji obezbeđuje tipove za rečnike slične JSON-u koji imaju fiksni skup string ključeva, svaki sa vrednošću sopstvenog tipa. Nastavićemo da širimo sistem tipova. Naš sljedeći korak će vjerovatno biti poboljšanje podrške za Python-ove numeričke mogućnosti.

Put do provjere tipa 4 miliona linija Python koda. Dio 3
Broj redova označenog koda: server

Put do provjere tipa 4 miliona linija Python koda. Dio 3
Broj redova označenog koda: klijent

Put do provjere tipa 4 miliona linija Python koda. Dio 3
Ukupan broj redova označenog koda

Evo pregleda glavnih karakteristika stvari koje smo uradili da povećamo količinu koda sa komentarima u Dropboxu:

Rigornost napomene. Postepeno smo povećavali zahtjeve za rigoroznost označavanja novog koda. Počeli smo sa savjetima za linter koji su predložili dodavanje napomena datotekama koje već imaju neke bilješke. Sada su nam potrebne oznake tipa u novim Python datotekama i u većini postojećih datoteka.

Tipkanje izvještaja. Timovima šaljemo sedmične izvještaje o nivou kucanja njihovog koda i dajemo savjete o tome šta prvo treba označiti.

Popularizacija mypy-ja. Razgovaramo o mypy-ju na događajima i razgovaramo s timovima kako bismo im pomogli da počnu s napomenama tipa.

Ankete. Vršimo periodične ankete korisnika kako bismo identificirali glavne probleme. Spremni smo ići prilično daleko u rješavanju ovih problema (čak i kreirati novi jezik da bismo ubrzali mypy!).

Performanse. Uvelike smo poboljšali performanse mypyja korištenjem demona i mypyc. Ovo je urađeno kako bi se izgladile neprijatnosti koje nastaju tokom procesa anotiranja i kako bi se mogao raditi sa velikim količinama koda.

Integracija sa urednicima. Napravili smo alate za podršku pokretanju mypy-ja u uređivačima koji su popularni na Dropboxu. Ovo uključuje PyCharm, Vim i VS Code. Ovo je uvelike pojednostavilo proces označavanja koda i provjere njegove funkcionalnosti. Ove vrste radnji su uobičajene prilikom označavanja postojećeg koda.

Statička analiza. Napravili smo alat za zaključivanje potpisa funkcija pomoću alata za statičku analizu. Ovaj alat može raditi samo u relativno jednostavnim situacijama, ali nam je pomogao da povećamo pokrivenost tipa koda bez mnogo napora.

Podrška za biblioteke trećih strana. Mnogi od naših projekata koriste alate SQLAlchemy. Koristi prednosti dinamičkih mogućnosti Pythona koje tipovi PEP 484 nisu u mogućnosti direktno modelirati. Mi smo, u skladu sa PEP 561, kreirali odgovarajući stub fajl i napisali dodatak za mypy (open source), što poboljšava podršku za SQLAlchemy.

Poteškoće na koje smo naišli

Put do 4 miliona linija ukucanog koda nije nam uvijek bio lak. Na ovoj stazi naišli smo na mnoge udarne rupe i napravili nekoliko grešaka. Ovo su neki od problema na koje smo naišli. Nadamo se da će pričanje o njima pomoći drugima da izbjegnu slične probleme.

Fajlovi koji nedostaju. Naš rad smo započeli provjeravanjem samo male količine datoteka. Sve što nije uključeno u ove datoteke nije provjereno. Datoteke su dodane na listu za skeniranje kada su se u njima pojavile prve napomene. Ako je nešto uvezeno iz modula koji se nalazi izvan opsega verifikacije, onda smo govorili o radu sa vrijednostima kao što su Any, koji uopšte nisu testirani. To je dovelo do značajnog gubitka tačnosti kucanja, posebno u ranim fazama migracije. Ovaj pristup je do sada funkcionisao iznenađujuće dobro, iako je tipična situacija da dodavanje datoteka u opseg pregleda otkriva probleme u drugim delovima kodne baze. U najgorem slučaju, kada su spojene dvije izolirane oblasti koda, u kojima su, nezavisno jedna od druge, tipovi već bili provjereni, pokazalo se da su tipovi ovih područja međusobno nekompatibilni. To je dovelo do potrebe za unošenjem mnogih izmjena u napomene. Gledajući sada unazad, shvaćamo da smo trebali ranije dodati module osnovne biblioteke u mypy-jevo područje za provjeru tipa. To bi naš rad učinilo mnogo predvidljivijim.

Anotiranje starog koda. Kada smo počeli, imali smo oko 4 miliona linija postojećeg Python koda. Bilo je jasno da označavanje cijelog ovog koda nije bio lak zadatak. Napravili smo alat pod nazivom PyAnnotate koji može prikupljati informacije o tipu tokom izvođenja testova i može dodati bilješke tipa vašem kodu na osnovu prikupljenih informacija. Međutim, nismo primijetili posebno rašireno usvajanje ovog alata. Prikupljanje informacija o tipu bilo je sporo, a automatski generirane napomene često su zahtijevale mnogo ručnih izmjena. Razmišljali smo o automatskom pokretanju ovog alata svaki put kada pregledamo kod, ili o prikupljanju informacija o tipu na osnovu analize malog broja stvarnih mrežnih zahtjeva, ali smo odlučili da to ne učinimo jer je oba pristupa bila previše rizična.

Kao rezultat toga, može se primijetiti da je većinu koda vlasnici ručno označili. Kako bismo ovaj proces vodili u pravom smjeru, pripremamo izvještaje o posebno važnim modulima i funkcijama koje je potrebno označiti. Na primjer, važno je osigurati oznake tipa za modul biblioteke koji se koristi na stotinama mjesta. Ali stari servis koji se zamjenjuje novom više nije toliko važan za označavanje. Također eksperimentiramo s korištenjem statičke analize za generiranje napomena tipa za naslijeđeni kod.

Ciklični uvoz. Gore sam govorio o cikličkom uvozu („zamršenosti zavisnosti“), čije postojanje je otežavalo ubrzavanje mypy-ja. Također smo morali naporno raditi kako bi mypy podržavao sve vrste idioma koji su uzrokovani ovim cikličnim uvozom. Nedavno smo završili veliki projekat redizajna sistema koji je popravio većinu mypy-ovih problema u vezi sa cirkularnim uvozom. Ovi problemi su zapravo proizašli iz ranih dana projekta, još iz Alorea, obrazovnog jezika na koji je mypy projekat prvobitno bio fokusiran. Alore sintaksa olakšava rješavanje problema s cikličnim uvoznim komandama. Savremeni mypy je naslijedio neka ograničenja od svoje ranije, jednostavne implementacije (koja je bila odlična za Alore). Python otežava rad sa kružnim uvozom, uglavnom zato što su izrazi dvosmisleni. Na primjer, operacija dodjele može zapravo definirati pseudonim tipa. Mypy nije uvijek u mogućnosti da otkrije ovakve stvari dok se većina uvozne petlje ne obradi. U Aloreu nije bilo takvih nejasnoća. Loše odluke donete u ranim fazama razvoja sistema mogu predstavljati neprijatno iznenađenje za programera mnogo godina kasnije.

Rezultati: put do 5 miliona linija koda i novi horizonti

Mypy projekat je prešao dug put - od ranih prototipova do sistema koji kontroliše 4 miliona linija tipova proizvodnog koda. Kako je mypy evoluirao, Pythonovi tipovi nagoveštaja su standardizovani. Ovih dana, moćan ekosistem se razvio oko kucanja Python koda. Ima mjesta za bibliotečku podršku, sadrži pomoćne alate za IDE i editore, ima nekoliko sistema kontrole tipova, od kojih svaki ima svoje prednosti i nedostatke.

Iako je provjera tipa već data u Dropboxu, vjerujem da smo još uvijek u ranim danima kucanja Python koda. Mislim da će tehnologije za provjeru tipa nastaviti da se razvijaju i poboljšavaju.

Ako već niste koristili provjeru tipa u svom velikom Python projektu, znajte da je sada vrlo dobar trenutak da počnete preći na statičko kucanje. Razgovarao sam sa onima koji su napravili sličnu tranziciju. Niko od njih nije požalio. Provjera tipa čini Python jezikom koji je mnogo pogodniji za razvoj velikih projekata od „običnog Pythona“.

Dragi čitaoci! Koristite li provjeru tipa u svojim Python projektima?

Put do provjere tipa 4 miliona linija Python koda. Dio 3
Put do provjere tipa 4 miliona linija Python koda. Dio 3

izvor: www.habr.com

Dodajte komentar