Perintah pip install requests selalu memasang versi terbaru yang tersedia saat perintah itu dijalankan. Artinya, Budi yang menginstal bulan Januari dan Siti yang menginstal bulan Maret bisa mendapat versi berbeda — dan aplikasi yang sama berperilaku berbeda tanpa satu baris kode pun berubah. Pinning versi adalah praktik menyatakan secara eksplisit versi apa saja yang boleh dipasang. Pada chapter ini kita pelajari bahasanya (semantic versioning dan operator specifier) lalu strateginya (aplikasi versus library).

Semantic Versioning #

Kebanyakan package Python mengikuti SemVer — format tiga segmen MAJOR.MINOR.PATCH, misalnya 2.32.5:

SegmenNaik ketikaContoh perubahan
MAJOR (2)ada perubahan yang merusak kompatibilitas2.32.5 menjadi 3.0.0; kode lama bisa gagal jalan
MINOR (32)ada fitur baru yang mundur-kompatibel2.32.5 menjadi 2.33.0; kode lama tetap aman
PATCH (5)ada perbaikan bug tanpa fitur baru2.32.5 menjadi 2.32.6; pengganti drop-in

Janji utamanya ada pada dua baris terakhir: menaikkan PATCH tidak boleh merusak apa pun, dan menaikkan MINOR hanya menambah kemampuan. Karena itu specifier ~=2.32 dan >=2.32 dianggap aman untuk rutinitas pemeliharaan — keduanya berhenti sebelum 3.0.0, tempat janji kompatibilitas berakhir.

Operator Penentu Versi #

Pada Chapter Menggunakan pip kita sudah melihat tabel singkatnya; berikut semantik lengkap ketiga operator terpenting. Aturan membaca ~=: naikkan segmen terakhir yang ditulis menjadi batas atas terbuka.

SpecifierRentang versi yang diterima2.28.12.29.03.0.0
==2.28.1hanya 2.28.1yatidaktidak
>=2.282.28 ke atas, tanpa batasyayaya
~=2.28.1>=2.28.1 dan <2.29.0yatidaktidak
~=2.28>=2.28 dan <3.0yayatidak
==2.28.*seluruh rilis 2.28.xyatidaktidak

Perhatikan perbedaan halus dua bentuk ~=: ~=2.28.1 menulis dua segmen belakang sehingga batas atasnya 2.29.0, sedangkan ~=2.28 hanya menulis satu segmen sehingga batas atasnya 3.0. Operator ~= adalah jalan tengah: menerima pembaruan rutin (bug fix, fitur kecil) tetapi menolak lompatan MAJOR yang berisiko merusak kode.

Specifier bukan sekadar saran — pip menolak memasang versi yang tidak memenuhinya. Berikut hasil nyata meminta versi yang tidak pernah ada:

bash
pip install "build==99.99"

Output yang Dihasilkan:

text
ERROR: Ignored the following yanked versions: 0.6.0, 0.6.1, 1.1.0, 1.2.0, 1.5.1
ERROR: Could not find a version that satisfies the requirement build==99.99 (from versions: 0.0.1, 0.0.2, ..., 1.5.0, 1.6.0, 1.6.1)

ERROR: No matching distribution found for build==99.99

Dua hal bisa dibaca dari galat ini. Pertama, pip mencantumkan seluruh versi yang tersedia — versi tertinggi build saat materi ini diuji adalah 1.6.1, bukan 99.99. Kedua, baris pertama menyebut versi yanked: rilis yang penulisnya telah menarik dari peredaran; pip mengabaikannya secara otomatis, sebuah perilaku yang kita bahas lagi pada Chapter Mendistribusikan Python Package.

Strategi Pinning: Aplikasi versus Library #

Berapa ketat versi harus dipilih, jawabannya bergantung pada jenis proyeknya:

AspekAplikasiLibrary
Siapa yang menginstal dependencykita sendiri, di venv milik aplikasipengguna library, bersama dependency lain
Strategi yang tepatpin eksak == atau lockfilerentang longgar >= / ~=
Alasanperilaku harus identik di semua mesinpin eksak akan bertabrakan dengan library lain

Alasan baris terakhir perlu ditelusuri. Bayangkan library kita menulis dependencies = ["requests==2.31.0"], lalu aplikasi memakai library kita bersama library lain yang menuntut requests>=2.32. Kedua syarat tidak mungkin dipenuhi bersamaan, dan pemasangan gagal hanya karena kita terlalu kaku. Library yang baik menyatakan syarat minimum lalu membiarkan penggunanya yang menentukan versi akhir.

Aplikasi berkebalikan penuh. Kita menguji aplikasi dengan satu kombinasi versi tertentu, dan kombinasi itulah yang harus terpasang di server produksi. Karena itu file requirements.txt hasil pip freeze pada Chapter requirements.txt — yang seluruh barisnya memakai == — adalah strategi yang tepat untuk aplikasi.

Menulis pin eksak satu per satu untuk puluhan transitive dependency bukan pekerjaan manusia. Tool seperti pip-tools memulai dari daftar direct dependency yang longgar, lalu menghitung dan membekukan seluruh pohonnya secara otomatis. Hasil perhitungan itulah yang disebut lockfile — topik lengkap pada Chapter Memahami Lockfiles.