{"id":38649,"date":"2019-10-31T22:25:04","date_gmt":"2019-10-31T19:25:04","guid":{"rendered":"https:\/\/prohoster.info\/blog\/put-k-proverke-tipov-4-millionov-strok-python-koda-chast-3\/"},"modified":"2019-10-31T22:25:04","modified_gmt":"2019-10-31T19:25:04","slug":"put-k-proverke-tipov-4-millionov-strok-python-koda-chast-3","status":"publish","type":"post","link":"https:\/\/prohoster.info\/hr\/blog\/administrirovanie\/put-k-proverke-tipov-4-millionov-strok-python-koda-chast-3","title":{"rendered":"Put do provjere tipova 4 milijuna redaka Python koda. Dio 3","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>Predstavljamo vam tre\u0107i dio prijevoda materijala o putu koji je kompanija Dropbox pro\u0161la prilikom implementacije sustava provjere tipova Python koda.<\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/ruvds\/blog\/468237\/\"><img decoding=\"async\" alt=\"Put do provjere tipova 4 milijuna redaka Python koda. Dio 3\" src=\"\/wp-content\/uploads\/2019\/10\/757669265e870de604388c66adef814d.png\" style=\"display:block;margin: 0 auto;\" \/><\/a><\/noindex><\/p>\n<p>\u2192 Prethodni dijelovi: <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/ruvds\/blog\/468233\/\">prva<\/a><\/noindex> i <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/ruvds\/blog\/468235\/\">dva<\/a><\/noindex><br \/>\n<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h2>Postizanje 4 milijuna redaka tipiziranog koda<\/h2>\n<p>\nJo\u0161 jedan va\u017ean zadatak (to je bio drugi najpopularniji problem koji je brinuo one koji su sudjelovali u internim anketama) bio je pove\u0107anje obima koda u Dropboxu koji je pokriven provjerama tipova. Isprobali smo nekoliko pristupa za rje\u0161avanje ovog zadatka \u2014 od prirodnog rasta obima tipizirane kod baze do fokusiranja napora \u010dlanova tima mypy na stati\u010dkom i dinami\u010dkom automatiziranom izvo\u0111enju tipova. Na kraju se \u010dinilo da nema jednostavne pobjedni\u010dke strategije, ali smo uspjeli posti\u0107i brzi rast obima annotiranog koda kombiniraju\u0107i vi\u0161e pristupa.<\/p>\n<p>Kao rezultat, u na\u0161em najve\u0107em Python repozitoriju (s backend kodom) broj redaka annotiranog koda dosegao je gotovo 4 milijuna. Rad na stati\u010dkoj tipizaciji koda trajao je otprilike tri godine. Mypy sada podr\u017eava razli\u010dite vrste izvje\u0161taja o pokrivenosti koda tipovima, koji olak\u0161avaju pra\u0107enje napretka tipizacije. Konkretno, mo\u017eemo generirati izvje\u0161taje o kodu s neodre\u0111enostima u tipovima, poput onih kod eksplicitne upotrebe tipa <code>Any<\/code> u anotacijama, koje nije mogu\u0107e provjeriti, ili s onima kao \u0161to su uvozi vanjskih biblioteka za koje nema anotacija tipova. Kao dio projekta za pobolj\u0161anje to\u010dnosti provjere tipova u Dropboxu, doprinosili smo pobolj\u0161anju definicija tipova (takozvanih stub datoteka) za neke popularne open-source biblioteke u centraliziranom Python repozitoriju <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/python\/typeshed\">typeshed<\/a><\/noindex>.<\/p>\n<p>Implementirali smo (i standardizirali u sljede\u0107im PEP-ovima) nove mogu\u0107nosti sustava tipova, koje omogu\u0107uju kori\u0161tenje preciznijih tipova za neke specifi\u010dne Python uzorke. Znatni primjer toga je <code>TypeDict<\/code>, koji pru\u017ea tipove za JSON-sli\u010dne rje\u010dnike s fiksnim skupom string klju\u010deva, pri \u010demu svaki od njih ima vrijednost vlastitog tipa. Nastavit \u0107emo \u0161iriti sustav tipova. Vjerojatno \u0107e na\u0161 sljede\u0107i korak biti pobolj\u0161anje podr\u0161ke za mogu\u0107nosti Pythona u radu s brojevima.<\/p>\n<p><img decoding=\"async\" alt=\"Put do provjere tipova 4 milijuna redaka Python koda. Dio 3\" src=\"\/wp-content\/uploads\/2019\/10\/297b9e823141d6cb0d2f19f9a78a1153.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Broj redaka annotiranog koda: server<\/i><\/p>\n<p><img decoding=\"async\" alt=\"Put do provjere tipova 4 milijuna redaka Python koda. Dio 3\" src=\"\/wp-content\/uploads\/2019\/10\/c183a9227e51d847bfdb2b8f6153684f.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Broj redaka anotiranog koda: klijent<\/i><\/p>\n<p><img decoding=\"async\" alt=\"Put do provjere tipova 4 milijuna redaka Python koda. Dio 3\" src=\"\/wp-content\/uploads\/2019\/10\/0a8b936fa454a34c09a9c6a2694485c9.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Ukupan broj redaka anotiranog koda<\/i><\/p>\n<p>Evo pregleda glavnih zna\u010dajki mjera koje smo poduzeli za pove\u0107anje volumena anotiranog koda u Dropboxu:<\/p>\n<p>Strogost anotacije. Postupno smo pove\u0107avali zahtjeve za strogost anotacije novog koda. Po\u010deli smo s preporukama linters-a koje su sugerirale dodavanje anotacija u datoteke koje ve\u0107 imaju neke anotacije. Sada zahtijevamo prisutnost anotacija tipova u novim Python datotekama i u ve\u0107ini postoje\u0107ih datoteka.<\/p>\n<p>Izvje\u0161taji o tipizaciji. Svakodnevno \u0161aljemo timovima izvje\u0161taje o razini tipizacije njihovog koda i pru\u017eamo savjete o tome \u0161to bi trebalo anotirati kao prvo.<\/p>\n<p>Popularizacija mypy. O mypy pri\u010damo na raznim doga\u0111anjima i komuniciramo s timovima, poma\u017eu\u0107i im da po\u010dnu koristiti anotacije tipova.<\/p>\n<p>Ankete. Povremeno provodimo ankete me\u0111u korisnicima kako bismo utvrdili glavne probleme. Spremni smo i\u0107i dovoljno daleko kako bismo rije\u0161ili te probleme (\u010dak i do stvaranja novog jezika radi ubrzanja mypy!).<\/p>\n<p>Performanse. Zna\u010dajno smo pobolj\u0161ali performanse mypy-a zahvaljuju\u0107i kori\u0161tenju demona i mypyc-a. To je u\u010dinjeno kako bi se ubla\u017eile nelagode u procesu anotiranja i kako bi se omogu\u0107ilo rad s velikim koli\u010dinama koda.<\/p>\n<p>Integracija s urednicima. Stvorili smo alate za podr\u0161ku pokretanju mypy-a u urednicima koji su popularni u Dropboxu. Uklju\u010duje PyCharm, Vim i VS Code. To je znatno pojednostavilo proces rada na anotiranju koda i provjeri njegove funkcionalnosti. Ove aktivnosti su obi\u010dno karakteristi\u010dne za anotiranje postoje\u0107eg koda.<\/p>\n<p>Stati\u010dka analiza. Stvorili smo alat za ispis potpisa funkcija koriste\u0107i alate stati\u010dke analize. Ovaj alat mo\u017ee raditi samo u relativno jednostavnim situacijama, ali nam je pomogao da bez velikih napora pove\u0107amo pokrivenost koda tipovima.<\/p>\n<p>Podr\u0161ka za vanjske biblioteke. U mnogim na\u0161im projektima koristi se skup alata SQLAlchemy. U njemu se koriste dinami\u010dke mogu\u0107nosti Pythona koje tipovi PEP 484 ne mogu izravno modelirati. U skladu s PEP 561, stvorili smo odgovaraju\u0107i stub-datoteku i napisali dodatak za mypy.<noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/dropbox\/sqlalchemy-stubs\">open source<\/a><\/noindex>), pobolj\u0161avaju\u0107i podr\u0161ku za SQLAlchemy.<\/p>\n<h2>Izazovi s kojima smo se suo\u010dili<\/h2>\n<p>\nPut do 4 milijuna linija tipiziranog koda nije nam uvijek bio lak. Na tom putu nai\u0161li smo na brojne prepreke i napravili nekoliko gre\u0161aka. Ovo su neki od problema s kojima smo se suo\u010dili. Nadamo se da \u0107e pri\u010da o njima pomo\u0107i drugima da izbjegnu sli\u010dne pote\u0161ko\u0107e.<\/p>\n<p>Propu\u0161tene datoteke. Po\u010deli smo raditi s provjerom samo malog broja datoteka. Sve \u0161to nije uklju\u010deno u taj broj nije se provjeravalo. Datoteke su se dodavale na popis provjere kada su se pojavile prve anotacije. Ako je ne\u0161to bilo uvezeno iz modula izvan podru\u010dja provjere, radilo se o radu s tipovima vrednosti <code>Any<\/code>, koji se uop\u0107e nisu provjeravali. To je dovelo do zna\u010dajnog gubitka to\u010dnosti tipiziranja, posebno u ranim fazama migracije. Ovakav pristup iznena\u0111uju\u0107e je dobro funkcionirao, iako je tipi\u010dna situacija bila da dodavanje datoteka u podru\u010dje provjere otkriva probleme u drugim dijelovima kodne baze. U najgorem slu\u010daju, kada su se spojila dva izolirana podru\u010dja koda, u kojima su neovisno provjeravani tipovi, ispostavilo se da su tipovi tih podru\u010dja nespojivi jedni s drugima. To je dovelo do potrebe za brojnim promjenama u anotacijama. Sada, gledaju\u0107i unatrag, shva\u0107amo da smo trebali \u0161to ranije dodati u podru\u010dje provjere tipova mypy osnovne bibliote\u010dke module. To bi na\u0161 rad u\u010dinilo mnogo predvidljivijim.<\/p>\n<p>Annotiranje starog koda. Kada smo zapo\u010deli rad, imali smo oko 4 milijuna linija ve\u0107 postoje\u0107eg Python koda. Bilo je jasno da je annotiranje cijelog tog koda zadatak koji nije lak. Izradili smo alat, nazvan PyAnnotate, koji mo\u017ee prikupljati informacije o tipovima tijekom izvo\u0111enja testova i dodavati anotacije tipova u kod na temelju prikupljenih informacija. Me\u0111utim, nismo primijetili posebno \u0161iroku primjenu ovog alata. Prikupljanje informacija o tipovima bilo je sporo, a automatski generirane anotacije \u010desto su zahtijevale mnogo ru\u010dnih ispravaka. Razmi\u0161ljali smo o automatskom pokretanju ovog alata pri svakom pregledu koda ili o prikupljanju informacija o tipovima na temelju analize odre\u0111enog malog obujma stvarnih mre\u017enih zahtjeva, no odlu\u010dili smo to ne u\u010diniti, jer bi bilo koji od tih pristupa bio previ\u0161e rizi\u010dan.<\/p>\n<p>Na kraju se mo\u017ee primijetiti da je ve\u0107ina koda ru\u010dno anotirana od strane njegovih vlasnika. Kako bismo usmjerili ovaj proces u pravom smjeru, pripremamo izvje\u0161taje o posebno va\u017enim modulima i funkcijama koje treba anotirati. Na primjer, va\u017eno je obogatiti anotacijama tipa knji\u017eni\u010dni modul koji se koristi na stotinama mjesta. Dok stari servis koji se zamjenjuje novim vi\u0161e nije toliko va\u017ean za anotaciju. Tako\u0111er, eksperimentiramo s kori\u0161tenjem stati\u010dke analize za generiranje anotacija tipova za stari kod.<\/p>\n<p>Cikli\u010dki importi. Gore sam govorio o cikli\u010dkim importima (o \u201eklup\u010dicama ovisnosti\u201d), \u010dije je postojanje ote\u017ealo ubrzanje mypy-a. Osim toga, morali smo ozbiljno raditi na tome da mypy podr\u017ei sve vrste idiom\u00e2, \u010diji su uzrok ovi cikli\u010dki importi. Nedavno smo zavr\u0161ili veliki projekt redizajna sustava koji je ispravio ve\u0107inu problema mypy-a u vezi cikli\u010dnih uvoza. Ovi problemi, zapravo, potekli su iz vrlo ranih dana projekta, jo\u0161 iz Alore, obrazovnog jezika na koji je projekt mypy prvotno bio usmjeren. Sintaksa Alore olak\u0161ava rje\u0161avanje problema cikli\u010dkih uvoznih naredbi. Moderni mypy naslijedio je neka ograni\u010denja iz svoje rane, jednostavne implementacije (koja je odli\u010dno odgovarala za Alore). Python ote\u017eava rad s cikli\u010dnim importima uglavnom zbog dvosmislenosti izraza. Na primjer, tijekom operacije dodjele vrijednosti, mo\u017ee se zapravo odrediti pseudonim tipa. Mypy nije uvijek u stanju prepoznati takve stvari sve dok ve\u0107i dio ciklusa uvoza nije obra\u0111en. U Alore nije bilo takvih dvosmislenosti. Neuspje\u0161na rje\u0161enja donesena u ranim fazama razvoja sustava mogu programeru donijeti neugodno iznena\u0111enje mnogo godina kasnije.<\/p>\n<h2>Zaklju\u010dci: put do 5 milijuna linija koda i novih horizonta<\/h2>\n<p>\nProjekt mypy pro\u0161ao je dug put \u2014 od ranih prototipova do sustava kojim se kontroliraju tipovi produkcijskog koda obujma od 4 milijuna linija. Tijekom razvoja mypy-a standardizirana su tipovna podaci u Pythonu. U dana\u0161nje vrijeme razvila se sna\u017ena ekosustav oko tipiziranja Python koda. U njemu je prona\u0111eno mjesto za podr\u0161ku knji\u017enicama, postoje alati za IDE i ure\u0111iva\u010de, a tu su i nekoliko sustava za kontrolu tipova, od kojih svaki ima svoje prednosti i mane.<\/p>\n<p>Iako se provjera tipova ve\u0107 smatra ne\u010dim \u0161to se podrazumijeva u Dropboxu, siguran sam da jo\u0161 uvijek \u017eivimo na pragu tipiziranja Python koda. Mislim da \u0107e se tehnologije provjere tipova nastaviti razvijati i pobolj\u0161avati.<\/p>\n<p>Ako jo\u0161 niste koristili provjere tipova u svom velikom Python projektu, znajte da je sada pravo vrijeme za prelazak na stati\u010dku tipizaciju. Razgovarao sam s onima koji su napravili taj prelazak. Nitko od njih nije po\u017ealio. Kontrola tipova pretvara Python u jezik koji je mnogo prikladniji za razvoj velikih projekata nego \"obi\u010dni Python.\"<\/p>\n<p><b>Dragi \u010ditatelji!<\/b> Koristite li kontrolu tipova u svojim Python projektima?<\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/ruvds.com\/vps_start\/\"><img decoding=\"async\" alt=\"Put do provjere tipova 4 milijuna redaka Python koda. Dio 3\" src=\"\/wp-content\/uploads\/2019\/10\/bf2bc557ce4481dd87398515bff60e3f.png\" style=\"display:block;margin: 0 auto;\" \/><\/a><\/noindex><br \/>\n<noindex><a rel=\"nofollow\" href=\"https:\/\/ruvds.com\/ru-rub\/#order\"><img decoding=\"async\" alt=\"Put do provjere tipova 4 milijuna redaka Python koda. Dio 3\" src=\"\/wp-content\/uploads\/2019\/10\/098d481c25b3afaba9534c686e8f943a.png\" style=\"display:block;margin: 0 auto;\" \/><\/a><\/noindex><br \/>\n<br \/>Izvor: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/ruvds\/blog\/468237\/\">habr.com<\/a><\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c \u0432\u0430\u0448\u0435\u043c\u0443 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u044e \u0442\u0440\u0435\u0442\u044c\u044e \u0447\u0430\u0441\u0442\u044c \u043f\u0435\u0440\u0435\u0432\u043e\u0434\u0430 \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u0430 \u043e \u043f\u0443\u0442\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u043e\u0448\u043b\u0430 \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u044f Dropbox, \u0432\u043d\u0435\u0434\u0440\u044f\u044f \u0443 \u0441\u0435\u0431\u044f \u0441\u0438\u0441\u0442\u0435\u043c\u0443 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0442\u0438\u043f\u043e\u0432 Python-\u043a\u043e\u0434\u0430. \u2192 \u041f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u0435 \u0447\u0430\u0441\u0442\u0438: \u043f\u0435\u0440\u0432\u0430\u044f \u0438 \u0432\u0442\u043e\u0440\u0430\u044f \u0414\u043e\u0441\u0442\u0438\u0436\u0435\u043d\u0438\u0435 4 \u043c\u0438\u043b\u043b\u0438\u043e\u043d\u043e\u0432 \u0441\u0442\u0440\u043e\u043a \u0442\u0438\u043f\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430 \u0415\u0449\u0451 \u043e\u0434\u043d\u043e\u0439 \u0432\u0430\u0436\u043d\u043e\u0439 \u0437\u0430\u0434\u0430\u0447\u0435\u0439 (\u044d\u0442\u043e \u0431\u044b\u043b \u0432\u0442\u043e\u0440\u0430\u044f \u043f\u043e \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u043e\u0441\u0442\u0438 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430, \u0432\u043e\u043b\u043d\u043e\u0432\u0430\u0432\u0448\u0430\u044f \u0442\u0435\u0445, \u043a\u0442\u043e \u0443\u0447\u0430\u0441\u0442\u0432\u043e\u0432\u0430\u043b \u0432\u043e \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0438\u0445 \u043e\u043f\u0440\u043e\u0441\u0430\u0445) \u0431\u044b\u043b\u043e \u0443\u0432\u0435\u043b\u0438\u0447\u0435\u043d\u0438\u0435 \u043e\u0431\u044a\u0451\u043c\u0430 \u043a\u043e\u0434\u0430 \u0432 Dropbox, [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":28992,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-38649","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.5 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c \u0432\u0430\u0448\u0435\u043c\u0443 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u044e \u0442\u0440\u0435\u0442\u044c\u044e \u0447\u0430\u0441\u0442\u044c \u043f\u0435\u0440\u0435\u0432\u043e\u0434\u0430 \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u0430 \u043e \u043f\u0443\u0442\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u043e\u0448\u043b\u0430 \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u044f Dropbox, \u0432\u043d\u0435\u0434\u0440\u044f\u044f \u0443 \u0441\u0435\u0431\u044f \u0441\u0438\u0441\u0442\u0435\u043c\u0443 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0442\u0438\u043f\u043e\u0432 Python-\u043a\u043e\u0434\u0430.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/hr\/blog\/administrirovanie\/put-k-proverke-tipov-4-millionov-strok-python-koda-chast-3\" \/>\n\t\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.5\" \/>\n\t\t<meta property=\"og:locale\" content=\"hr_HR\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47\u041f\u0443\u0442\u044c \u043a \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0435 \u0442\u0438\u043f\u043e\u0432 4 \u043c\u0438\u043b\u043b\u0438\u043e\u043d\u043e\u0432 \u0441\u0442\u0440\u043e\u043a Python-\u043a\u043e\u0434\u0430. \u0427\u0430\u0441\u0442\u044c 3 | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c \u0432\u0430\u0448\u0435\u043c\u0443 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u044e \u0442\u0440\u0435\u0442\u044c\u044e \u0447\u0430\u0441\u0442\u044c \u043f\u0435\u0440\u0435\u0432\u043e\u0434\u0430 \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u0430 \u043e \u043f\u0443\u0442\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u043e\u0448\u043b\u0430 \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u044f Dropbox, \u0432\u043d\u0435\u0434\u0440\u044f\u044f \u0443 \u0441\u0435\u0431\u044f \u0441\u0438\u0441\u0442\u0435\u043c\u0443 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0442\u0438\u043f\u043e\u0432 Python-\u043a\u043e\u0434\u0430.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/hr\/blog\/administrirovanie\/put-k-proverke-tipov-4-millionov-strok-python-koda-chast-3\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2019-10-31T19:25:04+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2019-10-31T19:25:04+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47 Put do provjere tipova 4 milijuna linija Python koda. Dio 3 | ProHoster","description":"Predstavljamo vam tre\u0107i dio prijevoda materijala o putu koji je kompanija Dropbox pro\u0161la prilikom implementacije sustava provjere tipova Python koda.","canonical_url":"https:\/\/prohoster.info\/hr\/blog\/administrirovanie\/put-k-proverke-tipov-4-millionov-strok-python-koda-chast-3","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"hr_HR","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47\u041f\u0443\u0442\u044c \u043a \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0435 \u0442\u0438\u043f\u043e\u0432 4 \u043c\u0438\u043b\u043b\u0438\u043e\u043d\u043e\u0432 \u0441\u0442\u0440\u043e\u043a Python-\u043a\u043e\u0434\u0430. \u0427\u0430\u0441\u0442\u044c 3 | ProHoster","og:description":"\u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c \u0432\u0430\u0448\u0435\u043c\u0443 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u044e \u0442\u0440\u0435\u0442\u044c\u044e \u0447\u0430\u0441\u0442\u044c \u043f\u0435\u0440\u0435\u0432\u043e\u0434\u0430 \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u0430 \u043e \u043f\u0443\u0442\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u043e\u0448\u043b\u0430 \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u044f Dropbox, \u0432\u043d\u0435\u0434\u0440\u044f\u044f \u0443 \u0441\u0435\u0431\u044f \u0441\u0438\u0441\u0442\u0435\u043c\u0443 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0442\u0438\u043f\u043e\u0432 Python-\u043a\u043e\u0434\u0430.","og:url":"https:\/\/prohoster.info\/hr\/blog\/administrirovanie\/put-k-proverke-tipov-4-millionov-strok-python-koda-chast-3","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2019-10-31T19:25:04+00:00","article:modified_time":"2019-10-31T19:25:04+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"38649","title":null,"description":null,"keywords":null,"keyphrases":{"focus":[],"additional":[]},"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":"2026-01-23 22:54:19","breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-03-01 01:05:23","updated":"2026-08-11 12:50:30","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/posts\/38649","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/comments?post=38649"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/posts\/38649\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/media\/28992"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/media?parent=38649"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/categories?post=38649"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/tags?post=38649"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}