Cara mengetik memeriksa 4 juta baris kode Python. Bagian 3

Kami sampaikan kepada Anda, bagian ketiga dari terjemahan materi di jalur yang telah dilakukan Dropbox, memperkenalkan sistem untuk memeriksa jenis-jenis kode Python.



→ Bagian sebelumnya: pertama dan kedua

Mencapai 4 juta baris kode yang diketik


Tugas penting lainnya (ini adalah masalah terpopuler kedua yang mengkhawatirkan mereka yang berpartisipasi dalam jajak pendapat internal) adalah meningkatkan jumlah kode di Dropbox yang dicakup dengan pemeriksaan jenis. Kami mencoba beberapa pendekatan untuk mengatasi masalah ini - dari pertumbuhan alami volume basis kode yang diketik hingga fokus upaya tim mypy pada inferensi tipe otomatis statis dan dinamis. Akibatnya, tampaknya tidak ada strategi kemenangan yang sederhana, tetapi kami dapat mencapai pertumbuhan cepat dalam volume kode beranotasi dengan menggabungkan banyak pendekatan.

Akibatnya, dalam repositori Python terbesar kami (dengan kode backend), jumlah baris kode beranotasi telah mencapai hampir 4 juta. Pekerjaan pengetikan kode secara statis dilakukan dalam waktu sekitar tiga tahun. Mypy sekarang mendukung berbagai jenis laporan cakupan kode yang membuatnya lebih mudah untuk memantau kemajuan pengetikan. Secara khusus, kami dapat membuat laporan tentang kode dengan ketidakpastian jenis, seperti, misalnya, penggunaan eksplisit dari jenis apa pun dalam anotasi yang tidak dapat diverifikasi, atau dengan mengimpor perpustakaan pihak ketiga yang tidak memiliki anotasi jenis. Sebagai bagian dari proyek untuk meningkatkan akurasi pengecekan tipe di Dropbox, kami telah berkontribusi untuk meningkatkan definisi tipe (yang disebut file rintisan) untuk beberapa pustaka sumber terbuka populer di repositori Python terpusat yang diketik.

Kami telah menerapkan (dan standar dalam PEP berikutnya) fitur baru dari sistem tipe, yang memungkinkan kami untuk menggunakan tipe yang lebih tepat untuk beberapa pola Python tertentu. Contoh penting dari ini adalah TypeDict , yang menyediakan jenis untuk kamus seperti JSON yang memiliki seperangkat kunci string yang tetap, masing-masing memiliki nilai jenisnya sendiri. Kami akan terus memperluas sistem tipe. Mungkin langkah kita selanjutnya adalah meningkatkan dukungan bagi kemampuan Python untuk bekerja dengan angka.


Jumlah baris kode beranotasi: server


Jumlah baris kode beranotasi: klien


Jumlah total baris kode beranotasi

Berikut adalah ikhtisar fitur utama dari tindakan yang kami lakukan untuk meningkatkan volume kode beranotasi di Dropbox:

Kerasnya anotasi. Kami secara bertahap meningkatkan persyaratan kerasnya anotasi kode baru. Kami mulai dengan kiat linter yang menyarankan menambahkan anotasi ke file yang sudah memiliki beberapa anotasi. Sekarang kita memerlukan anotasi jenis dalam file Python baru dan di sebagian besar file yang ada.

Mengetik laporan. Kami mengirimkan laporan mingguan ke tim tentang tingkat pengetikan kode mereka dan memberikan kiat mengenai apa yang seharusnya dijelaskan.

Mempopulerkan mypy. Kami berbicara tentang mypy di berbagai acara dan berkomunikasi dengan tim untuk membantu mereka mulai menggunakan anotasi jenis.

Polling. Kami melakukan survei pengguna secara berkala untuk mengidentifikasi masalah utama. Kami siap melangkah cukup jauh untuk menyelesaikan masalah ini (hingga menciptakan bahasa baru demi mempercepat mypy!).

Performa. Kami telah sangat meningkatkan kinerja mypy melalui penggunaan daemon dan mypyc. Ini dilakukan untuk memuluskan ketidaknyamanan yang muncul selama proses anotasi, dan agar dapat bekerja dengan sejumlah besar kode.

Integrasi dengan editor. Kami telah menciptakan alat untuk mendukung peluncuran mypy di editor yang populer di Dropbox. Ini termasuk PyCharm, Vim, dan VS Code. Ini sangat menyederhanakan proses anotasi kode dan memverifikasi kinerjanya. Tindakan seperti itu biasanya khas ketika membubuhi keterangan kode yang ada.

Analisis Statis Kami membuat alat untuk mengeluarkan tanda tangan fungsi menggunakan alat analisis statis. Alat ini hanya dapat bekerja dalam situasi yang relatif sederhana, tetapi telah membantu kami meningkatkan cakupan jenis dengan sedikit usaha.

Dukungan untuk perpustakaan pihak ketiga. Banyak proyek kami menggunakan toolkit SQLAlchemy. Ia menggunakan kemampuan dinamis Python, yang jenis PEP 484 tidak dapat memodelkan secara langsung. Menurut PEP 561, kami membuat file rintisan yang sesuai dan menulis sebuah plugin untuk mypy ( open source ) yang meningkatkan dukungan SQLAlchemy.

Kesulitan yang kami temui


Jalur menuju 4 juta baris kode yang diketik tidak selalu mudah bagi kami. Dalam perjalanan ini kami bertemu banyak lubang dan membuat beberapa kesalahan. Berikut adalah beberapa masalah yang kami temui. Kami berharap kisah tentang mereka akan membantu orang lain menghindari masalah seperti itu.

File yang dilewati. Kami mulai dengan memeriksa hanya sejumlah kecil file. Segala sesuatu yang tidak termasuk dalam jumlah file-file ini tidak diperiksa. File ditambahkan ke daftar periksa ketika anotasi pertama muncul di dalamnya. Jika ada sesuatu yang diimpor dari modul yang terletak di luar lingkup pemeriksaan, maka kami berbicara tentang bekerja dengan nilai-nilai tipe Any , yang tidak diperiksa sama sekali. Hal ini menyebabkan hilangnya akurasi pengetikan yang signifikan, terutama pada tahap awal migrasi. Pendekatan ini sejauh ini telah bekerja dengan sangat baik, meskipun itu khas bahwa menambahkan file ke area pemindaian akan mengungkapkan masalah di bagian lain dari basis kode. Dalam skenario terburuk, ketika dua area kode yang terisolasi digabungkan, di mana, terlepas dari satu sama lain, jenis sudah diperiksa, ternyata jenis area ini tidak kompatibel satu sama lain. Ini membuatnya perlu untuk membuat banyak perubahan pada anotasi. Sekarang, melihat ke belakang, kami memahami bahwa kami harus menambahkan modul perpustakaan dasar ke area pemeriksaan tipe mypy sedini mungkin. Ini akan membuat pekerjaan kami jauh lebih mudah diprediksi.

Membubuhi keterangan kode lama. Ketika kami mulai, kami memiliki sekitar 4 juta baris kode Python yang ada. Jelas bahwa menjelaskan semua kode ini bukanlah tugas yang mudah. Kami membuat alat yang disebut PyAnnotate, yang dapat mengumpulkan informasi jenis selama pelaksanaan pengujian dan dapat menambahkan anotasi jenis ke kode berdasarkan informasi yang dikumpulkan. Namun, kami tidak melihat pengenalan yang luas dari alat ini. Mengetik informasi tentang tipe lambat, anotasi yang dibuat secara otomatis sering membutuhkan banyak pengeditan manual. Kami berpikir untuk meluncurkan alat ini secara otomatis setiap kali Anda memeriksa kode, atau tentang mengumpulkan informasi jenis berdasarkan analisis dari sejumlah kecil permintaan jaringan nyata, tetapi memutuskan untuk tidak melakukannya, karena salah satu dari pendekatan ini terlalu berisiko.

Akibatnya, dapat dicatat bahwa sebagian besar kode dianotasi secara manual oleh pemiliknya. Untuk mengarahkan proses ini ke arah yang benar, kami menyiapkan laporan tentang modul dan fungsi penting yang perlu dijelaskan. Misalnya, penting untuk menyediakan anotasi jenis dengan modul perpustakaan yang digunakan di ratusan tempat. Tetapi layanan lama, yang digantikan oleh yang baru, annotating tidak lagi begitu penting. Kami juga bereksperimen menggunakan analisis statis untuk menghasilkan anotasi jenis untuk kode lama.

Impor lingkaran. Sebelumnya, saya berbicara tentang impor siklik ("kusut dependensi"), keberadaannya yang mempersulit percepatan mypy. Selain itu, kami harus bekerja keras untuk menyediakan mypy dengan dukungan untuk semua jenis idiom yang disebabkan oleh impor siklik ini. Kami baru-baru ini menyelesaikan proyek perancangan ulang sistem utama yang memperbaiki sebagian besar masalah impor siklik impor. Masalah-masalah ini, pada kenyataannya, muncul dari hari-hari awal proyek, kembali dari Alore, bahasa pendidikan yang mypy awalnya berorientasi. Sintaks lain membuatnya mudah untuk memecahkan masalah perintah impor siklik. Mypy modern telah mewarisi beberapa batasan dari implementasi awal yang cerdas (yang bekerja sangat baik untuk Alore). Python membuatnya sulit untuk bekerja dengan impor melingkar, terutama karena ambiguitas ekspresi. Misalnya, selama operasi penugasan, jenis alias sebenarnya dapat ditentukan. Mypy tidak selalu dapat mendeteksi hal-hal seperti itu sampai sebagian besar siklus impor telah diproses. Alore tidak memiliki ambiguitas seperti itu. Keputusan yang gagal dibuat pada tahap awal pengembangan sistem dapat memberikan kejutan yang tidak menyenangkan bagi seorang programmer setelah bertahun-tahun.

Ringkasan: Jalur menuju 5 juta baris kode dan cakrawala baru


Proyek mypy telah berjalan jauh - dari prototipe awal ke sistem yang mengontrol jenis kode produksi dengan volume 4 juta baris. Saat mypy berkembang, tip petunjuk distandarkan dalam Python. Ekosistem yang kuat telah berkembang sekitar mengetik kode Python hari ini. Itu menemukan tempat untuk mendukung perpustakaan, itu berisi alat bantu untuk IDE dan editor, ia memiliki beberapa jenis sistem kontrol, yang masing-masing memiliki pro dan kontra.

Terlepas dari kenyataan bahwa pengecekan tipe sudah diterima begitu saja di Dropbox, saya yakin bahwa kita masih hidup pada awal mengetik kode Python. Saya pikir teknologi pengecekan tipe akan terus berkembang dan meningkat.

Jika Anda belum pernah menggunakan pemeriksaan jenis dalam proyek Python skala besar, maka Anda harus tahu bahwa sekarang adalah waktu yang tepat untuk memulai transisi ke pengetikan statis. Saya berbicara dengan mereka yang melakukan transisi serupa. Tidak ada yang menyesal. Kontrol tipe mengubah Python menjadi bahasa yang jauh lebih baik daripada "Python normal" untuk mengembangkan proyek besar.

Pembaca yang budiman! Apakah Anda menggunakan kontrol tipe dalam proyek Python Anda?


Source: https://habr.com/ru/post/id468237/


All Articles