Pip: Menuju PEP 518

Dibuat pada 21 Okt 2017  ·  101Komentar  ·  Sumber: pypa/pip

Saya AWOL akhir pekan ini tetapi seperti yang saya pahami, perlu ada diskusi tentang PEP 518 dan implementasinya di pip.

Saya telah membuka masalah ini, karena saya tidak dapat menemukan di mana diskusi itu terjadi, jika memang demikian. Plus, memilikinya di satu tempat yang bukan pypa-dev/distutils-sig akan menyenangkan?

auto-locked maintenance

Komentar yang paling membantu

Anda memerlukan instalasi pip terpisah untuk dijalankan di dalam subproses secara umum, karena cache di tempat-tempat seperti pkg_resources Saya percaya (walaupun saya bisa saja salah di sana).

Itu tidak berarti Anda perlu memanggil pip , Anda dapat membuat API yang membuat serial data melalui CLI dan memanggil python -c "from pip._internals import coolapithing; coolapithing(sys.stdin.read())" dan membaca lebih banyak data dari stdout. Dimungkinkan untuk mengubah solusi rekursif dari panggilan pip pips memanggil pips memanggil pips dengan mengubahnya menjadi tumpukan menggunakan API semacam itu (karena semua rekursi juga dapat digambarkan sebagai tumpukan), pada dasarnya Anda hanya akan membuat API pribadi yang dipanggil sebagai proses.

Saya masih berencana membaca utas ini (akhir-akhir ini banyak piring berputar!), tetapi satu hal: Kami tidak benar-benar memiliki jadwal rilis, kami merilis ketika sudah siap tidak pada beberapa tanggal target. Kami terkadang memiliki beberapa gagasan umum tentang kapan kami ingin merilis, tetapi itu tidak pernah ditetapkan.

Semua 101 komentar

4799 adalah tempat banyak perdebatan terjadi. Itu sebagian besar didorong oleh:

  1. Saya mengerti bahwa satu-satunya pemblokir luar biasa untuk dukungan PEP 518 adalah #4764 (melalui https://github.com/pypa/pip/pull/4144#issuecomment-302711736)
  2. Kemudian #4799 muncul, dan saya melihatnya untuk melihat apakah saya dapat memahami semua pekerjaan yang sedang berlangsung yang dilakukan @xoviat .
  3. Dalam perjalanan itu, #4647 muncul sebagai pemblokir rilis yang mengatakan bahwa dukungan PEP 518 rusak.

Saat saya mencoba mencari tahu apa yang dikatakan @xoviat di #4799, menjadi jelas bahwa kami memiliki beberapa masalah seputar pembangunan rekursif dari lingkungan pembangunan (X membutuhkan Y untuk membangun, dan Y membutuhkan Z, ...) meskipun saya' Saya masih belum jelas apakah ini bug implementasi, masalah desain yang lebih dalam, atau kasus sudut buruk yang dapat kami tunda tanpa terlalu banyak masalah.

Secara pribadi, saya berada pada titik di mana saya berada di luar kedalaman saya. Saya tidak mengerti implementasi @xoviat untuk menilai apakah itu diperlukan, atau jika kita masih perlu menggabungkan #4764 dan memperbaiki #4647 agar siap digunakan. Saya juga tidak tahu betapa mudahnya memperbaiki #4647 ( @xoviat sepertinya mengatakan bahwa kita perlu menggabungkan #4799 untuk memperbaiki #4647, tetapi itu membawa masalahnya sendiri).

Saya sudah kehabisan waktu dan energi untuk melanjutkan diskusi lebih lanjut akhir pekan ini, jadi saya akan keluar pada saat ini (setidaknya untuk sementara waktu). Bagi saya, poin utamanya adalah bahwa kita menginginkan tingkat dukungan PEP 518 yang dapat diterima untuk pip 10. Saya ingin seseorang memberi saya perasaan apakah kita hampir sampai, atau apakah kita beberapa minggu lagi, sehingga saya dapat menghindari membuat orang bersemangat bahwa pip 10 akan datang hanya untuk kemudian mengatakan itu tidak akan sampai tahun baru ...

Terima kasih atas ringkasan yang sangat membantu @pfmoore.

@ncoghlan @dstufft @xoviat Bolehkah kami membawa diskusinya ke sini? Melakukannya pada PR tertutup terasa aneh bagi saya. ._.

Tentu saja.

@pradyunsg Saya tahu Anda tidak punya waktu untuk ini. Tetapi Anda lebih berhasil mendapatkan persetujuan PR daripada saya, jadi jika Anda mau, saya akan dengan senang hati memandu Anda melalui implementasi saat ini, cara kerjanya, dan potensi masalah yang ada. Saya akan menjelaskan bagaimana saya memecahkan beberapa (tetapi tidak semua) masalah ini dan ide-ide saya untuk perbaikan lengkap (yang sekali lagi, saya dapat lakukan setelah PEP 517 jika tidak selesai). Sejujurnya saya tidak peduli siapa yang melakukan pekerjaan selama itu selesai.

Sebenarnya, Anda AWOL, jadi izinkan saya menulis ringkasan:

pip memiliki hierarki objek, seperti yang umum di sebagian besar proyek Python. Semuanya dimulai dengan perintah, yang membuat referensi baru ke objek, yang membuat referensi baru ke objek yang lebih rendah. Ini seperti pohon.

Saya akan mendefinisikan "ruang lingkup" suatu objek sebagai semacam masa hidup. Ini adalah durasi keberadaan suatu objek. Saat ini, ruang lingkup PEP 518 dalam pip adalah WheelBuilder . Lingkungan PEP 518 diatur untuk bdist_wheel , kemudian bdist_wheel dijalankan dalam lingkungan itu, dan kemudian lingkungan dirobohkan.

Jadi apa masalahnya dengan itu? Masalahnya adalah cakupan lingkungan PEP 518 harus sama atau lebih besar dari cakupan semua panggilan ke setup.py . Lebih khusus lagi, ia perlu merangkum objek yang ada selama durasi panggilan setup.py . Objek itu adalah Requirement .

Keputusan jelas pertama yang akan Anda temui adalah: apa yang seharusnya memiliki referensi ke BuildEnvironment , dan Requirement adalah tempat yang bagus. Faktanya, ini adalah tempat terbaik IMHO untuk meletakkan referensi karena setup.py dipanggil jika dan hanya jika Requirement ada.

Masalah berikutnya yang mungkin Anda temui adalah ini: bagaimana cara menginstal persyaratan BuildEnvironment ? Kami hanya bisa membayar pip . Dan itulah keputusan yang dibuat oleh pelaksana asli. Tetapi ada masalah dengan itu: pip tidak memiliki cara untuk mengetahui berapa banyak panggilan shell yang dibuatnya karena setiap pip dapat memanggil dirinya sendiri lagi. Faktanya, paket yang dibuat dengan jahat dengan dependensi melingkar dapat membuat komputer seseorang crash jika pip menghasilkan terlalu banyak proses.

Masalah lain adalah panggilan shell apa yang harus kita lakukan? Ini sebenarnya lebih rumit dari yang Anda kira, karena mendapatkan parameter baris perintah sejujurnya adalah PITA di mana Anda perlu melakukan panggilan itu. Jadi, Anda mungkin mengalami masalah dalam meneruskan parameter asli yang diteruskan pengguna ke anak. Solusi yang digunakan oleh pelaksana asli yang terlibat menggunakan finder , tapi saya pikir Anda tahu masalahnya dengan itu.

Memotong anak Anda sendiri tanpa semacam kelas manajer yang dapat membunuh anak-anak ketika pengguna menekan ctrl+C tidak hanya salah, itu berbahaya, terutama ketika Anda tidak tahu berapa banyak proses yang telah Anda buat. Saya pribadi tidak tahu apakah anak-anak mati dalam implementasi saat ini (ini mungkin FUD), tetapi jika tidak, IMHO implementasi saat ini salah (selain dari masalah lain).

Beberapa solusi yang mungkin untuk masalah tersebut adalah sebagai berikut:

  1. Jika Anda ingin mengeluarkan PEP 518, taruhan terbaik Anda mungkin adalah semacam file kunci yang hanya memungkinkan hingga 10 kunci atau lebih untuk memastikan bahwa pip tidak berlipat ganda tanpa batas. Kemudian Anda bisa memberikan persyaratan yang tepat ke anak bersama dengan argumen baris perintah.

  2. Solusi yang tepat, yang ingin saya terapkan setelah PEP 517, adalah memiliki kelas BuildEnvironmentManager yang diinisialisasi langsung dalam perintah install . BuildEnvironmentManager akan memiliki referensi ke semua objek di sana ( RequirementPreparer , WheelBuilder , dll.), dan akan memiliki satu metode: get_build_environment(requirement_set) . Anda kemudian dapat mengimplementasikan metode pada RequirementPreparer seperti set_build_environment_manager , yang kemudian dapat digunakan untuk mendapatkan lingkungan build. BuildEnvironmentManager bahkan dapat mendeteksi beberapa penggunaan lingkungan yang sama (paling sering ['setuptools', 'wheel'] ) dan menyediakan lingkungan yang sama jika diperlukan beberapa kali sehingga Anda tidak perlu membuatnya (pada awalnya sangat umum dengan proyek yang tidak memiliki pyproject.toml ). Idealnya juga akan ada beberapa desain OOP untuk mencoba menghapus referensi melingkar (tidak sepele).

@xoviat Meskipun mungkin tidak mencakup kasus kedengkian yang disengaja, apakah saya benar dalam berpikir bahwa cache build (yang digunakan bahkan ketika --no-binary :all: telah ditentukan) dengan kemampuan untuk melacak tidak hanya build yang telah selesai, tetapi juga dalam -progress, apakah cukup untuk memastikan bahwa siklus ketergantungan build dihentikan? Ini akan menjadi varian dari saran pertama Anda (batas lintas proses pada jumlah pemanggilan pip bersamaan), tetapi dirumuskan kembali sebagai:

  1. Hanya satu proses pada mesin yang diizinkan untuk membangun paket yang sama pada waktu yang sama
  2. Ada "ID build" tingkat atas yang diturunkan pip ke sub-build mana pun yang dihasilkannya (mis. PID dari proses tingkat atas digabungkan dengan nama paket yang sedang dibangun)
  3. Jika cache build menunjukkan bahwa ada sesuatu yang sedang dibangun oleh ID build yang berbeda , maka tunggu hingga build itu selesai
  4. Jika cache build menunjukkan bahwa ada sesuatu yang sedang dibangun untuk ID build yang sama , lalu keluar dengan kesalahan melaporkan ketergantungan melingkar, dan menunjukkan bahwa --binary <name> akan diperlukan agar build berfungsi

pip juga perlu mengimplementasikan saran @pfmoore untuk mengecualikan setuptools & wheel dari logika default yang membutuhkan setuptools dan wheel sebagai dependensi build, jika tidak, injeksi dependensi build implisit secara inheren akan memicu logika deteksi dependensi melingkar.

Menggunakan disk untuk menghindari keharusan mencari tahu masalah desain OOP bukanlah ide yang buruk. Itu seperti opsi perantara antara menerapkan PEP 518 sepenuhnya dengan benar dan hanya meretas sesuatu bersama-sama.

Itu juga akan berinteraksi dengan baik dengan lingkungan kemas dan chroot secara umum, karena kami akan dapat menggunakan alat level sistem operasi untuk menjaga tingkat Python yang berbeda tetap terisolasi satu sama lain, jadi pip hanya perlu mencari cara untuk memastikan subprosesnya sendiri bekerja sama satu sama lain.

@xoviat terima kasih atas ringkasan di atas. Seperti yang saya katakan, saya telah mencapai batas pemahaman saya tentang kode di area ini, dan penjelasan Anda sangat membantu saya.

Saya belum pernah melihat kode #4144 sebelumnya. Saya baru saja melakukannya dan saya benar-benar tidak ingin itu dikirim.

menerapkan PEP 518 sepenuhnya dengan benar dan hanya meretas sesuatu bersama-sama.

Sejujurnya, saya pikir itu turun ke ini. Menerapkan PEP 518 secara lengkap dan benar adalah tugas yang akan/mungkin menunda pip 10 a (wajar) sedikit jika kita melakukannya.

Saya pikir jalan tengah yang aman di sini adalah membutuhkan dependensi build untuk tersedia sebagai roda. Dengan begitu, kita dapat menghindari masalah rekursi karena dependensi build (dan semua dependensinya) tidak perlu dibangun melalui proses ini.

Bagaimana ini terdengar?

Ini dibatasi tetapi saya pikir implementasi pertama yang dibatasi lebih baik daripada implementasi pertama Anda-dapat-tembak-sendiri-di-kaki-jika-Anda-tidak-hati-hati.

Menerapkan PEP 518 secara lengkap dan benar adalah tugas yang akan/mungkin menunda pip 10 a (wajar) sedikit jika kita melakukannya.

Terima kasih telah mengonfirmasi itu - itulah ketakutan saya.

Namun, sekarang saya bingung, karena saya pikir setidaknya sebagian PEP 518 sudah di master. Secara khusus, seperti yang saya pahami #4647 menunjukkan bug dalam dukungan PEP 518 di master - jadi jelas kami sudah memiliki sesuatu , karena apa pun itu tidak benar ...

Jadi kita harus melakukan sesuatu, dan sepertinya pilihannya adalah:

  1. Keluarkan apa pun yang kami miliki untuk dukungan PEP 518 saat ini.
  2. Rapikan apa yang kita miliki dan kirimkan dukungan parsial.
  3. Implementasikan PEP 518 sepenuhnya sebelum kami merilis pip 10.

Seperti yang Anda katakan (3) berarti penundaan yang lama sebelum pip 10 dan kami memiliki perbaikan lain yang saya benar-benar ingin lihat dirilis (perbaikan Unicode menjadi salah satu yang sering kami selesaikan masalah). Jadi saya tidak tertarik dengan itu. Anda tidak menyebutkan (1), dan saya tidak yakin apakah itu karena Anda pikir kami tidak memiliki dukungan PEP 518, atau apakah Anda menganggap mundur bukanlah pilihan. Secara pribadi, saya tidak menyukai gagasan itu - ini adalah langkah mundur, dan itu mengirimkan pesan yang cukup negatif tentang PEP itu sendiri, jika itu sulit untuk diterapkan dengan benar. Tapi saya pikir kita harus tegas menolaknya.

Proposal Anda untuk (2), bahwa kami mengirimkan versi PEP 518 yang hanya mendukung roda sebagai dependensi build (kami masih perlu memperbaiki #4647, karena demonstrasi yang menggunakan dependensi build adalah roda) tampaknya masuk akal , dalam arti praktis untuk kita terapkan. Reservasi utama saya adalah saya tidak tahu betapa bermasalahnya pembatasan itu bagi orang-orang yang ingin menggunakan PEP 518.

Jadi saya rasa saya merasa seperti kami terjebak apa pun yang kami lakukan, tetapi dukungan parsial hanya mencakup roda karena dependensi build adalah pilihan terbaik dari banyak yang buruk :-(

Penulis PEP (dalam https://github.com/pypa/pip/pull/4799#issuecomment-338331267 dan https://github.com/pypa/pip/pull/4799#issuecomment-338332575 sebagai tanggapan atas pertanyaan saya di https://github.com/pypa/pip/pull/4799#issuecomment-338325354) cukup pasti bahwa dukungan PEP penuh memerlukan membangun dependensi build apa pun, jadi itu harus hanya sementara.

Tapi bukan saya yang akan menerapkan ini, jadi saya senang untuk pergi dengan penilaian siapa pun yang melakukannya. Satu hal yang telah saya lakukan adalah membuat #4803 dan menandainya sebagai pemblokir rilis, sebagai pengingat bahwa kita harus mendokumentasikan bagaimana kita menyimpang dari spesifikasi, jika perlu.

(Dan di luar topik untuk masalah ini, tetapi dapatkah saya menyarankan agar kita berhati-hati untuk tidak membuat kesalahan yang sama ketika kita mulai menerapkan PEP 517? Mari kita pastikan bahwa kita memahami semua implikasi implementasi sebelum kita terlalu mendalami pengkodean - insting saya adalah bahwa PEP 517 akan menjadi masalah desain yang lebih kompleks daripada PEP 518...)

Saya paling akrab dengan distro dalam hal perspektif "membangun semuanya dari sumber", dan kami pasti memisahkan proses "bootstrap buildroot" dari pembuatan paket biasa. Bootstrap otomatis penuh dari sumber itu sulit , karena Anda akhirnya harus melakukan hal-hal seperti bootstrap kompiler C Anda.

Jadi untuk pip, saya pikir masuk akal untuk mengatakan bahwa dependensi build akan selalu dapat diinstal dari file roda. Penyempurnaan yang dapat Anda perkenalkan pada posting 10.x adalah memiliki cache build yang berbeda dari cache roda biasa, sehingga pengguna cache dapat yakin bahwa semua roda di dalamnya dibangun di lingkungan yang terkendali, daripada diunduh dari PyPI atau server indeks lainnya.

Secara pribadi, saya tidak menyukai gagasan itu - ini adalah langkah mundur, dan itu mengirimkan pesan yang cukup negatif tentang PEP itu sendiri, jika itu sulit untuk diterapkan dengan benar.

Saya belum tentu setuju dengan itu. Sulit untuk diterapkan dengan benar untuk pip. Tapi pip seperti yang dinyatakan dalam PEP adalah satu-satunya ujung depan yang akan digunakan orang. Saya pikir itu tugas kita sebagai pelaksana bahasa, dan pip benar-benar bahasa yang digunakan orang untuk mengemas proyek python mereka, untuk membuatnya sesederhana mungkin untuk membuat sistem pembangunan tanpa harus memikirkan semua masalah sulit ini. Bagi mereka itu seharusnya berjalan mulus karena kami telah melakukan kerja keras.

Saya pikir jalan tengah yang aman di sini adalah membutuhkan dependensi build untuk tersedia sebagai roda.

Sebenarnya itulah yang dilakukan #4799. Jika Anda mau, saya dapat memulihkan cabang itu dan kemudian Anda dapat memotongnya dan mengirimkannya sebagai PR.

Dua hal di sisi implementasi dari hal-hal (2) masih bertahan -- seperti yang ditunjukkan @xoviat di atas:

  1. mencari tahu cara membuat subproses (argumen et al)
    Saya pikir harus bisa dilakukan.

  2. versi paket mana yang akan diinstal.
    Ini mungkin harus dilakukan dalam proses induk yang sama meskipun saya tidak yakin bagaimana tepatnya itu akan terjadi mengingat fakta bahwa kode resolver saat ini masih terkait dengan kode di pip._internal.operations.prepare . Saya akan memeriksanya minggu ini.

Saya tidak yakin siapa yang punya waktu untuk melakukan ini.


itu mengirimkan pesan yang cukup negatif tentang PEP itu sendiri, jika itu sulit untuk diterapkan dengan benar.

Mungkin tidak sulit untuk diterapkan dengan benar. Hanya saja dengan cara basis kode pip hari ini, tidak sepele untuk diterapkan di pip -- ada hal-hal yang terjadi di tempat-tempat aneh dan saya pikir jika itu dibersihkan, itu akan menjadi hal yang sepele.

Anda tidak menyebutkan (1), dan saya tidak yakin apakah itu karena Anda pikir kami tidak memiliki dukungan PEP 518, atau apakah Anda menganggap mundur bukanlah pilihan.

Saya berasumsi mundur bukanlah pilihan.

Sekarang saya memikirkannya -- seberapa pentingkah mengirimkan PEP 518 di pip 10? Saya merasa jika itu dapat ditunda ke rilis besar berikutnya, itu akan (selain menjadi jalan keluar yang mudah dari situasi ini) menjadi mudah dan keduanya 517 + 518 dapat mendarat dalam satu rilis besar. Ini terasa cukup bersih sehingga saya tidak akan menjadi orang yang mengatakan ini bukan jalan yang harus ditempuh.

@dstufft @xavfernandez pikiran?


Ide @ncoghlan tentang build-cache terdengar seperti ide yang bagus untuk saya meskipun saya tidak yakin saya mengerti semua implikasinya.


Jika Anda mau, saya dapat memulihkan cabang itu dan kemudian Anda dapat memotongnya dan mengirimkannya sebagai PR.

Saya mungkin tidak akan punya waktu dan bahkan jika saya melakukannya, saya mungkin tidak akan menggunakan kembali komitmen yang ada. Tetapi memulihkan cabang itu tidak ada salahnya. :)

Reservasi utama saya adalah saya tidak tahu betapa bermasalahnya pembatasan itu bagi orang-orang yang ingin menggunakan PEP 518.

Kami telah melakukan diskusi yang tepat ini kecuali bahwa Anda mungkin bahkan tidak mengetahuinya. Situasi ini adalah situasi X. Memanggil egg_info sebelum lingkungan build diatur adalah situasi Y (#4799).

Tapi bukan saya yang akan menerapkan ini, jadi saya senang untuk pergi dengan penilaian siapa pun yang melakukannya.

Saya kira itu berarti #4799 sudah kembali? Selama itu melewati semua tes dan melakukan apa yang diklaimnya?

Aargh, X dan Y itu kembali menghantui saya lagi :wink: Ya, saya katakan saya tidak memiliki perasaan untuk kemungkinan relatif dari 2 kasus. Saya mengerti Anda mengatakan bahwa persyaratan pembuatan yang bukan roda cukup langka sehingga kami boleh mengabaikan kasus itu. Begitu juga satu suara "tidak apa-apa" dan satu suara "tidak tahu" di antara kami, pada dasarnya. Saya tidak mencoba untuk memblokir opsi ini, hanya mengatakan di mana batas-batas intuisi saya, itu saja.

@xoviat Saya punya beberapa pertanyaan. Akan luar biasa jika Anda akan menjawabnya sebelum Anda membuat PR baru. :)

  • Bagaimana Anda akan menentukan paket mana yang diinstal?
  • Apakah Anda akan membatasi dependensi build hanya biner?

Saya telah bekerja dengan banyak proyek ilmiah sehingga bisa jadi saya bias. Tetapi saya dapat menyebutkan daftar proyek dengan dependensi pembuatan roda dan saya benar-benar tidak dapat memikirkan satu proyek dengan dependensi sumber. Mungkin aku salah.

@rgommers apakah Anda akan baik-baik saja dengan PEP 518 yang hanya mendukung dependensi build yang tersedia sebagai roda jika ada di pip berikutnya?

Bagaimana Anda akan menentukan paket mana yang diinstal?

Subproses mendapatkan daftar persyaratan persis seperti yang ditentukan. Dengan cara itu ia melewati resolver.

Apakah Anda akan membatasi dependensi build hanya biner?

Ya itu sebenarnya mengapa tes itu gagal. Ketergantungan build dalam pengujian bukanlah roda.

Sekarang saya memikirkannya -- seberapa pentingkah mengirimkan PEP 518 di pip 10? Saya merasa jika itu dapat ditunda ke rilis besar berikutnya, itu akan (selain menjadi jalan keluar yang mudah dari situasi ini) menjadi mudah dan keduanya 517 + 518 dapat mendarat dalam satu rilis besar. Ini terasa cukup bersih sehingga saya tidak akan menjadi orang yang mengatakan ini bukan jalan yang harus ditempuh.

Apa perasaan kita apakah kita akan mendapatkan siapa pun dengan waktu untuk melakukan PEP 517 dan 518 untuk pip 11? Saya tidak optimis. Tampak bagi saya bahwa keduanya adalah bagian besar dari pekerjaan, dan kami juga memiliki pekerjaan resolver yang sedang berlangsung. Sementara saya tidak mendukung untuk menahan pip 10 lebih lama dari yang diperlukan, saya sama tidak nyamannya dengan membiarkan semua rencana fitur utama kami melayang sementara kami merilis serangkaian rilis yang pada dasarnya kecil.

Dengan kata lain, mengatakan "mari kita pergi untuk rilis pip 10" mendorong kebangkitan aktivitas pada pekerjaan PEP 518. Jika kita menghapusnya dari pip 10, saya akan fokus pada persiapan untuk rilis, dan saya menduga kemungkinan PEP 518 kehilangan momentum lagi. Apa yang membuat sesuatu menjadi aktif lagi? @xoviat sedang mengerjakan implementasi, tetapi dia mengalami masalah saat mencoba membuat kita semua memahami masalah yang dia perjuangkan sampai sekarang. Saya tidak ingin meninggalkan dia bekerja tanpa umpan balik lagi.

Apa yang dapat kami lakukan adalah merilis "pip 9.1" hanya dengan perbaikan tambahan yang telah kami siapkan, dan mencadangkan nomor versi "pip 10" untuk implementasi (setidaknya satu dari) 3 fitur tiket besar yang ada di dalam pipa. Tetapi jika kita melakukannya, saya ingin mencoba[1] untuk berkomitmen pada rilis 10 pip pada kuartal pertama tahun 2018. Saya akan setuju dengan itu sebagai pendekatan. Tetapi apakah ada yang merasakan apa yang akan terlibat dalam mendukung dukungan parsial yang kita miliki saat ini di master? Atau dalam mendokumentasikan apa yang kami miliki dan apa batasannya (agar orang tidak mencoba menggunakannya dengan asumsi sudah lengkap, terkena bug dan mengangkat masalah yang harus kami tanggapi dengan "fitur ini belum lengkap, maaf tapi tunggu pip 10")? Apakah kita hanya menukar satu pekerjaan besar dengan pekerjaan lain?

[1] Sejauh kami dapat berkomitmen untuk apa pun dengan sumber daya sukarelawan yang sangat terbatas karena semua yang kami miliki tersedia.

Saya telah bekerja dengan banyak proyek ilmiah sehingga bisa jadi saya bias

Terima kasih, terkadang sulit untuk mengetahui latar belakang orang. Jika Anda akrab dengan proyek ilmiah, itu sangat mengurangi kekhawatiran saya.

Apa yang dapat kami lakukan adalah merilis "pip 9.1" hanya dengan perbaikan tambahan yang telah kami siapkan, dan mencadangkan nomor versi "pip 10" untuk implementasi (setidaknya satu dari) 3 fitur tiket besar yang ada di dalam pipa.

Saya sangat menyukai ini. +1 ke pip 9.1.0 bukannya pip 10.0.0

Saya ingin mencoba[1] untuk berkomitmen pada rilis pip 10 pada kuartal pertama tahun 2018. Saya akan setuju dengan itu sebagai pendekatan.

Saya mengalami gelombang otak yang sangat menarik -- pip berusia 10 tahun pada 12 Okt 2018. Itu akan menjadi tanggal yang tepat untuk melakukan rilis pip 10.0.0. Ini adalah garis waktu yang sama sekali berbeda. Saya tidak mengatakan bahwa kita harus menunda fitur paus putih sampai saat itu, tetapi beberapa bagian dari diri saya benar-benar ingin nomor versi dan usia ini bertepatan juga.

Saya menduga kemungkinan PEP 518 kehilangan momentum lagi.

Saya akan melakukan apa yang saya bisa untuk memastikan itu tidak terjadi. Semoga @xoviat mau juga. :)

adakah yang bisa merasakan apa yang akan terlibat dalam mendukung dukungan parsial yang kita miliki saat ini di master?

Saya tidak keberatan melihat ini besok. Karena @dstufft adalah yang diulas di #4144, saya pikir masukannya tentang ini akan berharga.

Catatan - Saya tidak ingin melakukan sesuatu yang drastis seperti mundur tanpa persetujuan dari @dstufft dan @xavfernandez - jadi mari kita lihat apa yang mereka katakan juga.

@dstufft tidak punya cukup waktu dalam sehari. Dia juga harus memastikan gudang itu tidak ambruk.

mari kita lihat apa yang mereka katakan juga.

Ya silahkan. :)

Dari perspektif UX: secara komprehensif melawan serangan "trusting trust" benar- benar menyakitkan [1], dan Anda akan menemukan banyak orang yang mengatakan "Saya mengkompilasi semuanya dari sumber" sebenarnya tidak melakukannya - di suatu tempat dalam proses mereka di sana akan menjadi langkah bootstrap di mana mereka memercayai biner yang disediakan oleh orang lain (misalnya lingkungan runtime dan membangun rantai alat dari penyedia sistem operasi mereka), atau dari generasi sebelumnya dari platform mereka sendiri (misalnya, buildroot untuk versi baru Fedora dan RHEL diunggulkan dari versi Fedora dan RHEL sebelumnya, mereka tidak memulai sepenuhnya dari awal). Bahkan distro Linux berbasis sumber seperti Gentoo dimulai dengan penginstal untuk memberi Anda lingkungan build yang berfungsi dengan kernel Linux, kompiler C, driver perangkat keras, dll.

Jadi saya pikir sepenuhnya masuk akal untuk pip 10 untuk mengatakan bahwa --no-binary :all: hanya berlaku untuk dependensi runtime, bukan untuk membangun dependensi. Jika orang ingin secara eksplisit membangun buildroot mereka dari sumber, mereka masih bisa - hanya saja pip 10 tidak akan secara implisit mengotomatiskannya untuk mereka karena masalah bootstrap rekursif yang melekat dalam mengizinkan build sumber implisit untuk dependensi build Anda.

Untuk memungkinkan orang menunjukkan bahwa mereka mengharapkan lingkungan build untuk sepenuhnya dikonfigurasikan sebelumnya, masuk akal untuk menambahkan opsi --no-implicit-builddeps terpisah agar instalasi gagal langsung jika bootstrap biner implisit diperlukan sebagai bagian dari build sumber . Dengan begitu, orang yang mencoba memastikan semuanya dibangun dari sumber (termasuk dependensi build) dapat melakukan hal yang setara dengan:

pip install --no-binary :all: --no-implicit-builddeps -r build-requirements.txt
pip install --no-binary :all: --no-implicit-builddeps -r requirements.txt

Dan tentukan sebanyak mungkin grup penginstalan berbeda yang mereka perlukan untuk mencapai titik di mana yang pertama tidak memerlukan apa pun selain CPython dan rantai alat build non-Python apa pun yang sudah diinstal sebelumnya.

Pelengkap potensial di masa depan untuk konsep itu adalah memungkinkan orang mengatakan --buildenv <path> untuk menentukan lingkungan build yang telah dikonfigurasi sebelumnya untuk digunakan untuk setiap build sumber yang diperlukan, daripada melakukan setiap build di lingkungan yang terisolasi. Namun, saya tidak akan mencoba memasukkannya ke pip 10 - Saya sarankan membatasi 10.x ke jalur bahagia "ketergantungan build biner diizinkan" dan opsi alternatif "gagalkan build jika dependensi build biner diperlukan dan belum tersedia di penerjemah yang sedang berjalan".

[1] https://www.schneier.com/blog/archives/2006/01/countering_trus.html

Saya telah memikirkan opsi lain, yang tampaknya masuk akal dan tidak memerlukan terlalu banyak refactoring: pada dasarnya menggunakan multi-threading untuk menahan utas utama sementara lingkungan build diatur. Idenya seperti ini: di install.py , Anda akan memiliki BuildEnvironmentManager :

class BuildEnvironmentManager(Thread):
    '''Has references to literally everything (cache, resolver, etc.)'''
    def run(self):
        while True:
            requirement_list, future = self.build_environment_queue.get()

            # install the requirements using all of the things
            # that we have

            # then put the build environment in the future
            future.put(BuildEnvironment())

Anda kemudian akan memiliki file lain, (saya menggunakan backend.py karena tidak cukup penuh dan mungkin bisa menggunakan lebih banyak hal di dalamnya, dan itu ada di ujung bawah pohon):

class Future(Queue):
    pass

class BuildEnvironmentQueue(object):
    def __init__(self):
        self._queue = Queue()

    def request_build_environment(self, requirement_list):
        f = Future()
        self._queue.put((requirement_list, f))
        return f.get()

    def get():
        return self._queue.get()

Dan dalam operasi/prepare.py:

# This call will put the thread to sleep until we have a build environment
# with the requirements installed
self.build_environment_queue.request_build_environment(requirement_list)

Ini memiliki keuntungan membutuhkan refactoring minimal, memiliki serial BuildEnvironmentManager (sehingga lingkungan build dapat dioptimalkan dan Anda tahu persis permintaan apa yang telah dibuat dalam satu objek) dan menjaga semua yang terkandung dalam satu proses (sehingga skenario terburuk adalah kebuntuan). Tentu saja, logging perlu dinonaktifkan untuk utas lainnya, tetapi itu tidak terlalu menjadi masalah.

Menjawab pertanyaan saya sendiri tentang pendekatan berbasis antrian. Antrian: sebaiknya hindari mengandalkan konkuren.futures, karena menggunakan itu akan membutuhkan vendor https://pypi.org/project/futures/ di Python 2.7.

Tanpa mengetahui basis kode pip dengan baik, gagasan untuk mengonsolidasikan manajemen lingkungan build di satu tempat tampaknya masih merupakan opsi yang menarik.

concurrent.futures tidak diperlukan untuk pendekatan itu. Future hanyalah pembungkus yang lebih deskriptif.

Hanya primitif yang diperlukan adalah Antrian: https://docs.python.org/2/library/queue.html

Saya kira kita bisa memindahkan baris ini ke BuildEnvironmentManager .

Saya telah bekerja dengan banyak proyek ilmiah sehingga bisa jadi saya bias. Tetapi saya dapat menyebutkan daftar proyek dengan dependensi pembuatan roda dan saya benar-benar tidak dapat memikirkan satu proyek dengan dependensi sumber. Mungkin aku salah.

Nah, untuk satu ada setiap OS yang tidak [Windows, macOS, Linux], IIRC yang tidak dicakup oleh manylinux1 .

@rgommers apakah Anda akan baik-baik saja dengan PEP 518 yang hanya mendukung dependensi build yang tersedia sebagai roda jika ada di pip berikutnya?

Bukan panggilan saya, tetapi saya akan senang dengan langkah maju apa pun di sini. Dukungan PEP 518 adalah opsional, jadi hanya berfungsi ketika roda tersedia (mencakup> 90% kasus menurut saya) di pip 10 masih merupakan peningkatan yang signifikan.

Perhatikan bahwa bahkan platform yang tidak mengizinkan roda pada PyPI masih akan memiliki cache roda lokal, yang berarti bahkan jika pip tidak dapat secara implisit mem-bootstrap, ia mungkin masih dapat mencetaknya dan mengatakan "dapatkan dependensi build ini diinstal entah bagaimana , dan kemudian ini akan berhasil".

Tetapi apakah ada yang merasakan apa yang akan terlibat dalam mendukung dukungan parsial yang kita miliki saat ini di master?

Saya melihat ke dalam ini; sepertinya tidak terlalu sulit. Saya akan senang untuk membuat PR untuk itu jika kita memutuskan untuk pergi dengan cara ini.

+1 ke pip 9.1.0 bukannya pip 10.0.0

Saya akhirnya punya waktu untuk membaca utas distutils-sig dengan benar dan melihat PR dan diskusi yang relevan (#4351, #4144, #4799 dan banyak lainnya). Saya sekarang berpikir karena kami telah mengumumkan pip 10; itulah yang harus kita lakukan, dengan dukungan parsial PEP 518 -- no 9.1.0.

nomor versi dan usia ini bertepatan

Kekecewaan. :(

@ncoghlan Mungkin komentar ini menyelinap di bawah radar -- https://github.com/pypa/pip/pull/4799#issuecomment -338416543

Jika tidak, alangkah baiknya jika Anda dapat menjelaskan mengapa itu tidak berhasil karena saya agak memahami pengaturan semacam itu dan saya pasti terbuka untuk mempelajari lebih lanjut tentangnya. :)

@pradyunsg Saya pikir itu sebagian besar akan berhasil, karena ini adalah implementasi spesifik dari ide cache build. Satu aspek yang tidak tercakup adalah membangun loop ketergantungan, karena tidak ada cara untuk mendeteksi "Saya baru saja diminta untuk membangun sesuatu yang sudah saya coba buat".

Perhatikan bahwa pip tidak perlu secara ajaib menyelesaikan loop ketergantungan - itu hanya perlu mendeteksinya dan gagal segera setelah menemukannya, daripada benar-benar masuk ke loop tak terbatas.

itu tidak mencakup membangun loop ketergantungan,

Itu tidak akan terjadi dengan dependensi build hanya biner?

@pradyunsg Komentar tertaut adalah tentang cara mengizinkan build sumber untuk membangun dependensi, yang berarti dependensi melingkar menjadi masalah potensial. Jika kita membutuhkan dependensi biner, maka pip hanya dapat mengandalkan cache roda yang ada untuk saat ini.

Benar. Terima kasih! :)

Saya mendukung pip 10 dengan implementasi PEP 518 parsial terbatas pada dependensi build biner saja (atau sudah tersedia dalam cache roda pip) jika hanya itu yang berhasil kami sertakan.

Saya belum membaca seluruh utasnya, tetapi saya hanya ingin menunjukkan bahwa satu efek samping dari membatasi dependensi build biner adalah ~ tidak mungkin memiliki ketergantungan C di deps build Anda dalam banyak kasus. Ya, kami memiliki roda biner di Windows, macOS, dan beberapa versi Linux, tetapi kami tidak memilikinya di:

  • Linux apa pun yang tidak menggunakan glibc (Linux Alpine di dalam Docker menjadi yang populer).
  • Sistem operasi *nix apa pun yang bukan Linux, seperti FreeBSD dll.

Ini berarti bahwa setiap proyek berbasis CFFI misalnya tidak akan dapat menggunakan PEP 518 atau tidak dapat dicopot pada platform tersebut.

Ini mungkin sudah diangkat! Saya akan membaca utas ini nanti.

@dstufft Itu benar. Tapi apa yang kami usulkan adalah bahwa menggunakan cache pip adalah sebuah pilihan. Jadi Anda bisa pip wheel atau pip install dependensi build Anda terlebih dahulu dan kemudian akan disimpan dalam cache.

Ini mungkin sudah diangkat!

Tidak. :)

Ini berarti bahwa setiap proyek berbasis CFFI misalnya tidak akan dapat menggunakan PEP 518 atau tidak dapat dicopot pada platform tersebut.

Memang. :-(

Cara mengatasinya di kepala saya adalah bahwa kita dapat membuat perilaku PEP 518 opt-in -- jika ada file pyproject.toml , kita menggunakan isolasi + lingkungan build jika tidak, kembali ke perilaku saat ini menggunakan setup.py .

Saya akan membaca utas ini nanti.

Silakan lakukan. :)

Saya memiliki komentar yang sama persis dengan Donald; pemahaman saya tentang utas ini adalah bahwa biner-saja bersifat sementara karena tidak ada waktu untuk mengimplementasikannya untuk pip 10. Benar?

Jika diusulkan sebagai keputusan permanen, maka -1 tentu saja.

Saya memiliki komentar yang sama persis dengan Donald; pemahaman saya tentang utas ini adalah bahwa biner-saja bersifat sementara karena tidak ada waktu untuk mengimplementasikannya untuk pip 10. Benar?

Itu benar. pip seharusnya mendukung dependensi sumber tetapi kami kekurangan tenaga.

Cara mengatasinya di kepala saya adalah kita dapat membuat keikutsertaan perilaku PEP 518 -- jika ada file pyproject.toml, kita menggunakan lingkungan isolasi + build jika tidak, kembali ke perilaku saat ini menggunakan setup.py.

Saya membaca ulang komentar ini dan saya akan tidak setuju di sini. Dukungan PEP 518 seharusnya tidak opsional, (untuk alasan implementasi terkait dengan PEP 517) IMHO, tetapi proyek tidak boleh dihapus pada platform ini.

Lebih khusus lagi, proyek tertentu yang Anda instal seharusnya tidak menentukan apakah Anda mendapatkan PEP 518. Itu harus ditentukan oleh apakah dependensi build Anda tersedia sebagai roda atau dalam cache. Selanjutnya, kami dapat membuat dukungan PEP 518 wajib untuk platform tersebut juga jika kami hanya mengeluarkan pesan seperti berikut:

Error: build dependency X is not in the pip cache. Run "pip install X" before installing Y.

Meringkas perspektif saya sendiri:

  1. Saya melihat "Tidak ada dukungan build implisit untuk dependensi build" sebagai batasan sementara di pip 10 untuk membuat kelas masalah tertentu (mis. membangun loop dependensi) tidak mungkin ditemukan dalam iterasi fitur yang dirilis pertama kali. Iterasi mendatang dari dukungan backend build yang dapat dicolokkan dapat memungkinkan build sumber implisit untuk dependensi build, sambil menerapkan langkah-langkah yang sesuai untuk menghindari masalah baru yang muncul setelah Anda mengizinkannya.
  2. Memancarkan perintah python -m pip wheel X Y Z yang relevan dalam pesan kesalahan tanpa benar-benar menjalankan build secara implisit adalah solusi yang memadai untuk saat ini, karena ini memastikan pip tidak dapat secara tidak sengaja melakukan fork bomb pada mesin.
  3. Build yang terisolasi mungkin belum menjadi default, kecuali wheel tertentu yang sedang dibuat memiliki file pyproject.toml , atau build yang terisolasi secara eksplisit diminta dari baris perintah. Ini adalah masalah kompatibilitas mundur, karena proyek yang ada akan mengharapkan perilaku yang tidak terisolasi. Setelah build yang terisolasi telah tersedia untuk satu atau dua rilis, dan masalah kegunaan apa pun dengan mereka telah diselesaikan, maka mereka dapat menjadi default secara umum (mungkin dengan opsi baris perintah untuk menentukan lingkungan build tertentu untuk digunakan daripada secara implisit menghasilkan terisolasi yang)

@ncoghlan Hanya untuk memberi Anda peringatan: tidak ada isolasi build default berarti tidak ada PEP 517 (setidaknya dengan pendekatan saya) karena hanya versi terbaru dari setuptools yang mendukungnya (kita perlu menginstal setuptools yang lebih baru terlepas dari apa yang ada di perangkat orang tersebut komputer). Secara praktis saya pikir itu mungkin menunda PEP 517 setidaknya satu tahun karena itu akan secara dramatis meningkatkan jumlah upaya yang diperlukan untuk mengimplementasikannya (membutuhkan kode PEP 517 dan non-PEP 517).

Ini adalah masalah kompatibilitas mundur, karena proyek yang ada akan mengharapkan perilaku yang tidak terisolasi.

Kebanyakan orang memiliki skrip CI yang menjalankan pip install X dan kemudian menjalankan pip install Y . Proyek-proyek ini perlu menambahkan pypproject.toml . Tetapi menambahkan pyproject.toml tidak terlalu berhasil, dan kita dapat menambahkan flag baris perintah untuk menonaktifkan isolasi build jika perlu.

Kami setidaknya harus mengeluarkan peringatan jika sebuah proyek tidak memiliki pyproject.toml di pip 10 (yang sepertinya tidak akan memiliki dukungan PEP 517).

@xoviat "Tidak akan banyak pekerjaan untuk menyesuaikan" bukan cara kerja kompatibilitas mundur. Jika ya, pip akan beralih ke --user sebagai model instalasi non-venv default sekarang :)

Sejauh PEP 517 berjalan, Anda tidak dapat bergantung pada PEP 517 sebagai penerbit paket tanpa menambahkan file pyproject.toml , jadi tidak masalah jika proyek setup.py -only tidak mendapatkan dukungan PEP 517 secara default.

Apakah Anda baik-baik saja dengan mengeluarkan peringatan?

Saya akan melihatnya sebagai masalah jika build yang saat ini berfungsi dengan baik mulai mengeluarkan peringatan hanya karena pip ditingkatkan, bahkan jika proyek itu sendiri maupun dependensinya tidak berubah.

PEP 518 dan 517 sengaja dirancang untuk menyebabkan gangguan nol untuk proyek yang ada di mana semua penerbit yang terlibat terus hanya mengandalkan alat penyiapan.

Masuk akal jika pip bertujuan untuk mengkonsolidasikan kembali ke satu jalur build PEP 518 bahkan untuk proyek berbasis setuptools, tetapi waktu untuk itu adalah setelah build yang terisolasi telah melihat satu atau dua rilis penggunaan praktis, bukan di versi pertama yang mendukung mereka sama sekali.

Saya memiliki komentar yang sama persis dengan Donald; pemahaman saya tentang utas ini adalah bahwa biner-saja bersifat sementara karena tidak ada waktu untuk mengimplementasikannya untuk pip 10. Benar?

Ya. Tepat.


Masuk akal jika pip bertujuan untuk mengkonsolidasikan kembali ke satu jalur build PEP 518 bahkan untuk proyek berbasis setuptools, tetapi waktu untuk itu adalah setelah build yang terisolasi telah melihat satu atau dua rilis penggunaan praktis, bukan dalam versi pertama yang mendukung mereka sama sekali.

+1

Saya pikir kita harus bertujuan untuk menghapus jalur lama, seperti 2 rilis utama. Ketika pip mendarat dukungan PEP 518 penuh dan tepat; kita harus menghentikan logika build lama dan menghapusnya sesuai dengan kebijakan penghentian standar.

Saya setuju dengan ringkasan Nick dan...

karena itu akan secara dramatis meningkatkan jumlah upaya yang diperlukan untuk mengimplementasikannya

Tidak. Saya tidak berpikir menerapkan PEP 518 dengan cara ini memiliki hambatan besar; Saya membuat komentar singkat melalui https://github.com/pypa/pip/pull/4799#issuecomment -339219397 tentang bagaimana ini dapat diterapkan dalam pip.


Apa yang ingin kami lakukan adalah memberi orang transisi yang bersih dari yang lama ke yang baru. Jadi, kita perlu menjaga logika pemasangan pip 9 saat ini tidak berubah -- yang pada dasarnya akan mendukung semua yang kita lakukan saat ini dengan cara yang sama persis seperti yang kita lakukan.

Memasukkan file pyproject.toml ke dalam arsip berarti paket tersebut ikut serta ke standar yang lebih baru dan bersedia menguji dukungan untuk perilaku baru -- melalui lingkungan build dengan isolasi dan build hanya biner -dependensi (untuk saat ini).

Tidak. Saya tidak berpikir menerapkan PEP 518 dengan cara ini memiliki hambatan besar;

Membahas PEP 517 di sini. Maaf bila membingungkan.

Kami harus menjalankan tes dua kali untuk memeriksa kedua jalur kode. Ah, baiklah PEP 517 mungkin ditangguhkan.

IM,

  1. Peringatan jika sebuah proyek tidak memiliki pyproject.toml terdengar seperti ide yang sangat buruk. Lagi pula, 99% proyek di PyPI saat ini tidak memiliki pyproject.toml , dan kami tidak dapat mengirim spam kepada pengguna akhir dengan peringatan bahwa mereka tidak dapat melakukan apa-apa (selain melaporkan masalah ke proyek ). Apakah saya melewatkan sesuatu?
  2. Saya tidak percaya bahwa isolasi bangunan disebutkan sama sekali di PEP 518. Ini adalah fitur tambahan yang ingin disertakan oleh pip untuk beberapa waktu sekarang, tetapi itu tidak terkait dengan dukungan PEP 518, kecuali oleh fakta kebetulan bahwa PR yang sama diimplementasikan keduanya (AFAIR). Jadi, jika membangun isolasi adalah yang memberi kami masalah di sini, saya baik-baik saja dengan hanya memiliki PEP 518 pada awalnya, dan menambahkan isolasi sebagai fase 2. Saya akan menyerahkan keputusan itu kepada orang-orang yang mengimplementasikannya.

Apakah saya melewatkan sesuatu?

Tidak.

Saya setuju dengan hanya memiliki PEP 518 pada awalnya, dan menambahkan isolasi sebagai fase 2.

Saya pikir kita harus melakukan PEP 518 dan membangun isolasi bersama, karena ini adalah cara yang bagus untuk membuat orang beralih ke bangunan terisolasi.

Meskipun PEP 518 atau PEP 517 tidak memerlukan build yang terisolasi, PEP 517 merekomendasikannya untuk alasan yang masuk akal: https://www.python.org/dev/peps/pep-0517/#recommendations -for-build-frontends-non-normative

Tanpa cache artefak biner lokal, lingkungan build yang terisolasi tidak praktis, tetapi begitu Anda memiliki salah satunya (seperti pip sekarang), mereka jauh lebih layak, karena:

  1. Pada sebagian besar penginstalan, Anda bahkan tidak perlu melakukan pembuatan sumber sejak awal
  2. Saat Anda perlu melakukan build sumber, Anda biasanya akan mengatur lingkungan build dari cache

Pada saat yang sama, lingkungan build yang terisolasi memang memerlukan sedikit lebih banyak pekerjaan dari penerbit, karena itu berarti metadata buggy akan merusak build milik penerbit dengan cara yang mengharuskan mereka untuk secara eksplisit mengatakan "Ketergantungan build saya tidak sepenuhnya dideklarasikan" untuk melakukan membangun.

Jadi membuat build berbasis pyproject.toml diisolasi dari awal memberikan titik peralihan alami, karena keseluruhan PEP adalah tentang menyediakan cara untuk mendeklarasikan dependensi build secara jelas dan konsisten secara terpisah dari dependensi runtime. Itu berarti orang-orang yang beralih dari setup.py mungkin melakukannya karena mereka peduli melakukan hal semacam itu, sementara orang-orang yang datang ke sana baru untuk proyek baru hanya akan memperlakukannya sebagai lingkaran lain yang mengharuskan mereka untuk melompati alat pengemasan melalui.

Jadi, hanya beberapa hal yang ingin saya konfirmasi sebelum saya mulai menulis kode:

  • Dukungan PEP 517 bukan pemblokir untuk pip 10
  • PEP 518 dalam pip 10

    • ikut serta melalui pyproject.toml

    • hanya mendukung dependensi build hanya biner

    • bangunan terisolasi

PEP 517 tidak dapat menjadi pemblokir untuk pip 10 karena belum siap, dan tidak ada jalur maju yang jelas pada saat ini (ada jalur ke depan tetapi tidak jelas).

Saya memiliki komentar dan pertanyaan sebagai tanggapan atas komentar @xoviat di sini yang merangkum tantangan implementasi serta setelah membaca utas ini dengan cepat.

Pertama, mengenai masalah rekursi dari hal-hal yang mungkin meledak, secara umum fungsi rekursif apa pun dapat "diterjemahkan" menjadi fungsi berulang. Saya bertanya-tanya apakah pendekatan itu dapat membantu di sini dengan memberikan lebih banyak kontrol.

Kedua, apa gunanya membeli sebagai lawan memanggil fungsi pip dari dalam Python? Apakah ada alasan fungsi API internal tidak dapat dibuat/difaktorkan ulang yang akan melakukan apa pun yang ingin dicapai oleh shelling? Itu akan memberikan lebih banyak fleksibilitas saat menjalankan panggilan (dibandingkan dengan parameter CLI). Ini juga dapat memberikan lebih banyak kontrol dengan memungkinkan seseorang untuk lebih mudah mengelola keadaan proses secara keseluruhan.

Apakah ada alasan fungsi API internal tidak dapat dibuat/difaktorkan ulang yang akan melakukan apa pun yang ingin dicapai oleh shelling?

Kedua, apa gunanya membeli sebagai lawan memanggil fungsi pip dari dalam Python?

Itu membeli waktu yang saat ini tidak kita miliki. pip sudah terlambat dari jadwal rilisnya.

Pertama, mengenai masalah rekursi dari hal-hal yang mungkin meledak, secara umum fungsi rekursif apa pun dapat "diterjemahkan" menjadi fungsi berulang.

Saya bukan anti rekursi. Saya anti proses-rekursi. Saya pikir tidak apa-apa jika Anda ingin menggunakan CPU 100% (yah, itu akan menjadi 20% dengan Python), tetapi pada akhirnya pengguna harus dapat membuka pengelola tugas dan mematikan maksimal 15 proses yang ada. Bagi saya, situasi yang berpotensi menyebabkan ledakan proses tidak dapat diterima.

Itu tidak menjawab pertanyaan mengapa ia membeli waktu. Apa yang membuat sulit untuk membuat fungsi API internal yang melakukan hal yang sama?

Bagaimanapun, jika mengupas menyelesaikan beberapa masalah tertentu, satu kemungkinan untuk membuat pendekatan ini lebih mudah adalah dengan mengekspos sementara perintah CLI pribadi/internal yang membuatnya lebih mudah untuk meneruskan informasi apa pun yang diperlukan (misalnya itu bahkan bisa menjadi objek Python serial , dll).

Itu tidak menjawab pertanyaan mengapa ia membeli waktu. Apa yang membuat sulit untuk membuat fungsi API internal yang melakukan hal yang sama?

Jika Anda pikir itu mudah, silakan saja. Saya tidak mengatakan itu secara sarkastik: silakan, silakan, karena itu akan menyelesaikan semua masalah.

Saya tidak berpikir itu mudah. Saya mengajukan pertanyaan untuk mendapatkan wawasan mengapa itu sulit. (Saya berasumsi Anda telah memikirkan hal ini karena Anda mengatakan itu akan menghemat waktu.)

Anda memerlukan instalasi pip terpisah untuk dijalankan di dalam subproses secara umum, karena cache di tempat-tempat seperti pkg_resources Saya percaya (walaupun saya bisa saja salah di sana).

Itu tidak berarti Anda perlu memanggil pip , Anda dapat membuat API yang membuat serial data melalui CLI dan memanggil python -c "from pip._internals import coolapithing; coolapithing(sys.stdin.read())" dan membaca lebih banyak data dari stdout. Dimungkinkan untuk mengubah solusi rekursif dari panggilan pip pips memanggil pips memanggil pips dengan mengubahnya menjadi tumpukan menggunakan API semacam itu (karena semua rekursi juga dapat digambarkan sebagai tumpukan), pada dasarnya Anda hanya akan membuat API pribadi yang dipanggil sebagai proses.

Saya masih berencana membaca utas ini (akhir-akhir ini banyak piring berputar!), tetapi satu hal: Kami tidak benar-benar memiliki jadwal rilis, kami merilis ketika sudah siap tidak pada beberapa tanggal target. Kami terkadang memiliki beberapa gagasan umum tentang kapan kami ingin merilis, tetapi itu tidak pernah ditetapkan.

Pada akhirnya meskipun Python memiliki kedalaman rekursi maksimum untuk memastikan bahwa segala sesuatunya tidak lepas kendali. Kita perlu menerapkan itu jika kita pergi dengan pendekatan itu.

Ya-ish, pendekatan berbasis tumpukan membuatnya cukup efisien untuk masuk cukup dalam (jauh lebih dalam daripada apa pun selain loop ketergantungan yang pernah dilakukan, misalnya kita dapat memiliki sesuatu yang bergantung pada setiap paket dan masih baik-baik saja), hal utama lakukan adalah untuk mendeteksi loop.

Salah satu cara yang cukup naif dan mudah untuk melakukan deteksi loop adalah dengan hanya menempatkan batas atas jumlah item di tumpukan dan mengatakan bahwa jika Anda mencapai batas ini maka Anda pasti berada dalam situasi loop dan error out. Kelemahannya tentu saja loop tidak terdeteksi sedini mungkin, dan paket dengan rantai ketergantungan build yang lebih dalam maka batasnya tidak berfungsi.

Opsi yang umumnya lebih baik (karena jika Anda menggunakan pendekatan berbasis tumpukan, Anda dapat mengakses seluruh tumpukan) adalah dengan melintasi tumpukan dan melihat apakah item yang kami coba instal sudah ada di tumpukan di mana saja, dan apakah break out dan error karena kita telah mencapai satu lingkaran (kesalahan ini dapat disajikan kepada pengguna akhir, atau dapat menggelembung ke resolver pada akhirnya untuk mencoba versi yang berbeda-- meskipun itu membuatnya jauh lebih lambat).

Dan untuk langsung menjawab pertanyaan @cjerdonek : pada prinsipnya ini tidak sulit, yang membuat segalanya menjadi rumit adalah beberapa asumsi arsitektur yang tertanam dalam cara kerja pip saat ini yang tidak lagi berlaku di dunia di mana setiap sumber membangun mendapatkan lingkungan pembuatannya sendiri yang terisolasi, bukan hanya berjalan langsung di lingkungan instalasi.

Itu berarti cara termudah untuk menggunakan kembali logika manajemen ketergantungan pip yang ada tanpa tersandung pada batasan arsitektur internal tersebut dan tanpa mengambil risiko melanggar kode yang sedang bekerja adalah dengan menjalankan instance pip lain dalam subproses. Itu sebagian besar baik-baik saja, kecuali untuk konsekuensi bahwa gagal mendeteksi dan keluar dari loop ketergantungan dapat membuat bom fork sistem yang menjalankan build.

Saya suka ide @dstufft untuk mengonversi ke pendekatan berbasis iteratif / stack dan keluar ke fungsi pip internal menggunakan pola python -c "from pip._internals import coolapithing; coolapithing(sys.stdin.read())" . Itu tampaknya paling sederhana berdasarkan diskusi, dan juga kuat.

Saya pikir langkah pertama menuju ini adalah merebus pendekatan rekursif langsung ke fungsi Python rekursif tunggal dengan input dan output yang diharapkan (setidaknya membuat sketsa), dan kemudian ini dapat diterjemahkan/dikonversi ke pendekatan berulang. Dan ya, Anda dapat mempertahankan set dari panggilan yang dikunjungi untuk mencegah pengulangan, yang sepertinya merupakan salah satu aspek yang lebih mudah untuk dipecahkan.

Saya melihat ke / berpikir lebih banyak tentang mengubah pendekatan rekursif menjadi pendekatan berulang. Pekerjaan parsial @xoviat pada PEP 518 (PR #4799) membantu saya menemukan titik rekursi (yang mungkin sudah Anda kenal). Ada di komentar kodenya:

# TODO: Use single process with recursion handling

di mana ia kemudian memanggil pip install ... .

Ide saya adalah sepertinya ini mungkin bisa diselesaikan dengan varian pip install (untuk dependensi build) dengan sesuatu seperti perubahan berikut:

  • Jika penginstalan tidak memerlukan sub-instalasi apa pun, maka lakukan penginstalan.
  • Jika tidak, kembali dengan daftar (mungkin sebagian) dari sub-pemasangan yang diperlukan (misalnya dengan menulis info ke file yang disepakati jika menulis ke stdout belum berhasil).

Dengan cara ini, proses root tingkat atas dapat secara progresif menghasilkan pohon dependensi build. Dan dapat memproses daun seperti yang ditemukan. Saat daun diproses, simpul yang sebelumnya bukan daun akan menjadi daun, dan seterusnya. Dengan implementasi ini, pada titik mana pun hanya akan ada paling banyak satu pip-install yang terjadi dalam sebuah subproses.

Sedikit variasi dari apa yang saya sarankan di atas adalah bahwa perintah pip/panggilan subproses yang diperlukan dapat mengembalikan/memancarkan daftar doa sub-instal yang akan dibutuhkan oleh kandidat instal ( pip get-subinstalls atau cukup pip subinstalls memerintah). Satu-satunya perbedaan dengan apa yang saya sarankan di atas adalah bahwa perintah ini akan terbatas pada pelaporan informasi. Itu tidak akan benar-benar menginstal. Jadi mengimplementasikannya bisa lebih sederhana/lebih mudah untuk diuji.

@cjerdonek Saya tidak melihat ada masalah dengan ide itu. Tetapi pada akhirnya seseorang perlu mengimplementasikannya (saya pikir @pradyunsg akan mengerjakan sesuatu akhir pekan ini?) dan seperti biasa lebih banyak kesulitan mungkin ditemukan saat itu.

Sesuatu telah muncul. Jika ada orang lain yang ingin mengambil ini, saya tidak punya
masalah. :)

Saya juga menyukai ide @dstufft .

Pada Minggu, 29 Oktober 2017, 08:47 xoviat, [email protected] menulis:

@cjerdonek https://github.com/cjerdonek Saya tidak melihat ada masalah dengan
ide itu. Tetapi pada akhirnya seseorang perlu mengimplementasikannya (saya pikir
@pradyunsg https://github.com/pradyunsg akan mengerjakan sesuatu
akhir pekan ini?) dan seperti biasa lebih banyak kesulitan dapat ditemukan saat itu.


Anda menerima ini karena Anda disebutkan.

Balas email ini secara langsung, lihat di GitHub
https://github.com/pypa/pip/issues/4802#issuecomment-340234567 , atau bisukan
benang
https://github.com/notifications/unsubscribe-auth/ADH7SYImpWgJGg-DzQRcO_9hHfE6ZxEAks5sw-5RgaJpZM4QBdSg
.

Kembali ke sini, apakah kita ingin melanjutkan dengan pendekatan pemanggilan stack+internal yang disarankan oleh @dstufft?

/ping @ncoghlan @pfmoore @xavfernandez

Ya silahkan. Apa pun untuk memajukan ini.

Adakah orang yang dapat meringkas di mana kita berdiri dengan PEP 517 dan PEP 518 sehubungan dengan rilis pip 10? Secara khusus:

  1. Apakah master saat ini dalam keadaan dapat dirilis? Terakhir saya dengar, dukungan PEP 518 rusak (setidaknya ada satu masalah pemblokir rilis terbuka terkait dengan PEP 518 - #4647).
  2. Apakah kita mungkin memiliki implementasi PEP 517 dan/atau PEP 518 yang berfungsi dalam skala waktu yang memungkinkan untuk menunda pip 10 hingga tersedia?
  3. Dengan asumsi kita memperbaiki hal-hal di (1), apakah kita ingin melakukan rilis pip 10 tanpa PEP 517/518? Kami membuat email pendahuluan tentang rilis tersebut, sehingga orang-orang tahu itu akan datang. Dan ada beberapa perbaikan yang cukup signifikan di sana (misalnya, perbaikan penyandian untuk Windows) yang akan menyenangkan untuk dirilis.

Perasaan saya adalah bahwa kita sedang menunggu rilis blocker, tapi kita tidak cukup dekat dengan dukungan PEP 517/518 untuk memblokir pip 10 pada mereka. Tapi saya rasa tidak ada yang mengerjakan #4647 kecuali sebagai bagian dari implementasi PEP 518.

Salah satu opsi alternatif adalah mendokumentasikan batasan dukungan PEP 518 saat ini, dan menurunkan versi #4647 dari menjadi pemblokir rilis. Saya tidak cukup tahu tentang kasus penggunaan untuk mengetahui apakah itu layak.

Saya baru saja melihat diskusi ini - permintaan maaf atas implementasi awal yang setengah matang yang dapat dianggap sebagai bom garpu, dan terima kasih kepada Anda semua yang telah meluangkan waktu untuk memahaminya dan menghasilkan ide yang lebih baik.

FWIW, saya pikir membatasinya untuk memasang roda untuk persyaratan build akan menjadi kompromi yang dapat diterima untuk versi pertama.

Ini juga mengingatkan saya bahwa saya mungkin harus memperbaiki masalah sehingga flit bukan persyaratan build itu sendiri.

permintaan maaf atas implementasi awal yang setengah matang yang dapat dianggap sebagai bom garpu,

Tidak perlu meminta maaf. Seperti yang saya katakan, Anda tidak dapat memprediksi masalah ini pada percobaan pertama. Bahkan mengetahui apa yang kita ketahui sekarang, menunda PR hanya akan menunda diskusi ini.

Apakah master saat ini dalam keadaan dapat dirilis?

IIUC, ia dapat melakukan fork-bomb sistem seperti sekarang; Apakah itu benar? Kalau menurut saya sih tidak.

Apakah kita mungkin memiliki implementasi PEP 517 dan/atau PEP 518 yang berfungsi dalam skala waktu yang memungkinkan untuk menunda pip 10 hingga tersedia?

Saya pikir, solusi (jangka pendek) yang mudah adalah dengan membatasi ke roda untuk membangun dependensi. Saya akan mencoba untuk mengambil menusuk itu kadang-kadang minggu depan. Jika itu tidak terwujud, saya akan baik-baik saja jika kita menghapus dukungan PEP 518 saat ini dari master dan memotong 10.0.0 dari itu.

Saya tidak berpikir ada orang yang mengerjakan #4647 kecuali sebagai bagian dari penerapan PEP 518.

Saya pikir maksud Anda, implementasi lengkap PEP 518 dengan dependensi build sumber diizinkan?

Oh, dan tentang #4647 -- Deskripsi @xoviat di atas mengatakan, perbaikan yang akan membutuhkan perubahan/pemindahan kode dan kepemilikan/visibilitas objek (khususnya BuildEnvironment ), yang tidak sepele.

Saya pikir membatasi ke roda harus sesederhana mengubah baris ini:

https://github.com/pypa/pip/blob/fc6b2c192088737f81259b6446f627f20ce46443/src/pip/_internal/wheel.py#L696

ke:

finder.format_control = FormatControl(set(), set([':all:']))

Bidang kedua ada satu set paket yang hanya ditemukan sebagai binari, dengan kasus khusus untuk ':all:' berarti semua paket.

Ya. Tapi itu saja tidak akan membahas #4647. Juga, tidak ada kode ini yang berfungsi
melalui penyelesai.

Pada Sabtu, 2 Des 2017 pukul 01:23 Thomas Kluyver [email protected] menulis:

Saya pikir membatasi ke roda harus sesederhana mengubah ini
garis:

https://github.com/pypa/pip/blob/fc6b2c192088737f81259b6446f627f20ce46443/src/pip/_internal/wheel.py#L696

ke:

finder.format_control = FormatControl(set(), set([':all:']))

Bidang kedua ada satu set paket untuk ditemukan hanya sebagai binari, dengan
kasus khusus untuk ':all:' yang berarti semua paket.


Anda menerima ini karena Anda disebutkan.

Balas email ini secara langsung, lihat di GitHub
https://github.com/pypa/pip/issues/4802#issuecomment-348598368 , atau bisu
benang
https://github.com/notifications/unsubscribe-auth/ADH7SUi0QMS3rr5Iba90XWZmFweGmqeBks5s8FlEgaJpZM4QBdSg
.

Benar, ada banyak hal lain yang salah dengan itu. Tapi itu harus mencegahnya dari fork-bombing, yang menurut saya merupakan masalah yang paling mendesak.

Jika seseorang ingin mengambil alih PR asli saya ("memperbaiki masalah PEP 518"),
seharusnya tidak sulit untuk mengubahnya sehingga membangun isolasi tidak
diaktifkan tanpa pyproject.toml. Alasan asli mengapa itu tidak digabung
adalah bahwa itu menjatuhkan dukungan untuk menginstal dependensi dari sumber dengan
PEP 518. Namun, sekarang orang-orang mulai menyadari bahwa PEP 518 mungkin
tidak berada di pip 10 sama sekali, mereka mungkin lebih dapat menerima PR itu. Saya
secara pribadi tidak punya waktu untuk memperjuangkannya, tetapi itu seharusnya tidak menghentikan orang lain
dari membawanya ke depan, karena hanya beberapa baris perubahan yang diperlukan
(selain gagal dalam tes PEP 518).

Sebenarnya, bertentangan dengan penilaian saya yang lebih baik, saya bersedia mengimplementasikan PEP 517 dan 518 segera jika pengembang pip setuju dengan kondisi saya:

  1. Ketergantungan hanya akan dari roda pada awalnya
  2. pip akan memiliki backend build internal pada awalnya, meskipun pada akhirnya akan dihapus

Saya tidak punya masalah dengan 1; Saya tidak punya preferensi untuk 2.

Pada Minggu, 3 Des 2017 pukul 02:36 xoviat [email protected] menulis:

Sebenarnya, bertentangan dengan penilaian saya yang lebih baik, saya bersedia menerapkan kedua PEP
517 dan 518 segera jika pengembang pip akan setuju dengan kondisi saya:

  1. Ketergantungan hanya akan dari roda pada awalnya
  2. pip akan memiliki backend build internal pada awalnya, meskipun itu
    akhirnya akan dihapus


Anda menerima ini karena Anda disebutkan.

Balas email ini secara langsung, lihat di GitHub
https://github.com/pypa/pip/issues/4802#issuecomment-348720096 , atau bisu
benang
https://github.com/notifications/unsubscribe-auth/ADH7ST6riptZkYMap5Z5SstRf-VmE7eAks5s8bu5gaJpZM4QBdSg
.

FYI kondisinya tidak sewenang-wenang tetapi ada untuk memungkinkan implementasi awal. Apakah @pfmoore baik-baik saja dengan ini?

Saya, tidak terlalu nyaman dengan nada tawaran "melawan penilaian saya yang lebih baik ... setuju dengan kondisi saya". Saya tidak akan keberatan jika pengembang pip lain dengan senang hati menerima tawaran ini, tetapi secara pribadi saya tidak punya waktu saat ini untuk memulai kembali seluruh perdebatan tentang detail implementasi. Pada dasarnya, saya akan tunduk pada @dstufft dan @xavfernandez dalam hal ini ( @pradyunsg telah memberikan pandangannya).

Nada penawarannya seperti itu karena metode implementasi ditutup karena ketidaksepakatan mendasar tentang seperti apa implementasi awal. Saya lebih suka menyetujui prinsip-prinsip sekarang daripada beralih ke debat implementasi lain.

Saya hanya akan menyatakan bahwa saya juga tidak terlalu nyaman dengan nadanya, itu
hanya saja, saya tidak punya waktu atau energi untuk menjelaskan mengapa nada itu digunakan
dll. Alasan yang sama untuk jawaban singkat dari saya.

Mungkin juga layak untuk dinyatakan, saya keren dengan biner hanya membangun dependensi di
implementasi pertama, bukan untuk jangka panjang. Ini tidak berlaku untuk
dependensi runtime (karena itu juga entah bagaimana muncul di yang lain
diskusi).

Pada Minggu, 3 Des 2017, 23:37 xoviat, [email protected] menulis:

Nada penawarannya seperti itu karena metode
implementasi ditutup karena ketidaksepakatan mendasar tentang apa yang
implementasi awal akan terlihat seperti. Saya lebih suka menyetujui
prinsip sekarang daripada beralih ke debat implementasi lain.


Anda menerima ini karena Anda disebutkan.

Balas email ini secara langsung, lihat di GitHub
https://github.com/pypa/pip/issues/4802#issuecomment-348802032 , atau bisukan
benang
https://github.com/notifications/unsubscribe-auth/ADH7ScUh-BveonoTxZ5FkkeSynFvoLb8ks5s8uNRgaJpZM4QBdSg
.

Sejujurnya, ini mungkin bukan penggunaan waktu yang efektif untuk membahas nada posting lebih lanjut, karena tidak relevan untuk memasukkan fitur-fitur ini di pip 10. Namun, saya perlu jaminan bahwa kondisi saya dapat diterima untuk bergabung dari @pfmoore ( yang telah menunjukkan bahwa dia tidak dapat membuat jaminan seperti itu, yang dapat diterima mengingat tidak ada yang dibayar untuk waktu mereka di sini), @dstufft , atau @xavfernandez.

Sekali lagi, kondisinya bukan pendapat pribadi saya, tetapi didorong oleh implementasi. Jika saya melonggarkan kondisi ini, maka saya tidak bisa menjanjikan implementasi, jadi tidak ada gunanya menghabiskan waktu untuk menyiapkan PR, dan kemudian orang membaca perbedaan dan bertanya "oh, mengapa baris ini ada di sini?" dan kemudian "oh, jadi ini tidak bisa digabung?" karena ada miskomunikasi tentang apa sebenarnya tujuan dari PR itu.

Setuju kembali nadanya. Maksud saya hanyalah bahwa saya tidak akan menggabungkan perubahan[1], jadi pandangan saya tidak terlalu penting di sini.

[1] Jelas, saya mengatakan itu tanpa melihat implementasinya, jadi saya harap jelas bahwa alasan saya tidak berkaitan dengan kekhawatiran tentang kualitas kode - ini tentang tidak memiliki waktu untuk memastikan saya memahami kode dengan cukup baik untuk bersedia untuk bergabung, pada dasarnya.

@xoviat Apa rencana implementasi Anda sehubungan dengan pendekatan berulang vs. rekursif yang kita diskusikan di atas?

Juga, untuk memperjelas, apakah Anda mengatakan bahwa Anda akan terlebih dahulu menyelesaikan sebagian implementasi PEP 517 dan 518 yang dapat digabungkan, diikuti oleh implementasi penuh yang dapat digabungkan? Atau apakah Anda mengatakan bahwa Anda hanya akan melakukan implementasi sebagian, atau apakah Anda mengatakan bahwa Anda akan melakukan implementasi penuh melalui tahap-tahap awal yang belum tentu dapat digabungkan? (Saya sebagian mencoba untuk lebih memahami apa yang Anda maksud dengan "awalnya" dan "akhirnya" dalam komentar Anda .)

Kondisi pertama menghilangkan seluruh masalah rekursi.

Juga, untuk memperjelas, apakah Anda mengatakan bahwa Anda akan terlebih dahulu menyelesaikan sebagian implementasi PEP 517 dan 518 yang dapat digabungkan, diikuti oleh implementasi penuh yang dapat digabungkan?

Apa yang saya katakan adalah bahwa saya akan menyelesaikan implementasi parsial ini akan bekerja untuk 95% kasus penggunaan; khususnya dalam kasus di mana dependensi memiliki roda (sangat umum sekarang) dan Anda menggunakan platform manylinux/windows/OSX (sebagian besar pengguna).

Ini bukan implementasi penuh. Tetapi cara Anda mendapatkan PR yang tidak dapat digabungkan adalah mencoba melakukan pendekatan "semua atau tidak sama sekali" di mana Anda mematuhi standar atau tidak.

Ingatlah bahwa implementasi penuh akan memerlukan penyortiran beberapa masalah yang cukup buruk yang masing-masing memerlukan PR terpisah (karena memiliki PR dengan 100+ komentar biasanya berarti kode tidak ditinjau dengan baik). [1]

[1] https://github.com/btc1/bitcoin/pull/11#issuecomment -313843216

Saya akan menutup masalah ini sekarang -- kami memiliki dukungan awal untuk PEP 518 di pip 10 yang hanya mendukung roda sebagai dependensi build. Saya akan membuka edisi baru untuk membahas tentang dukungan penuh dan satu lagi untuk dukungan PEP 517 (dikutip dari sini jika relevan).

Terima kasih @ncoghlan @rgommers @cjerdonek atas wawasan dan bantuan Anda di sini. Terima kasih @takluyver untuk implementasi awal PEP 518. Terima kasih @xoviat (yang sekarang menjadi @ghost ) atas semua bantuannya dalam mengimplementasikan perubahan ini. Terima kasih @benoit-pierre atas bantuan Anda dalam meningkatkan dukungan saat ini.

PS: komentar ke-100! :tada:

Utas ini telah dikunci secara otomatis karena tidak ada aktivitas terbaru setelah ditutup. Silakan buka edisi baru untuk bug terkait.

Apakah halaman ini membantu?
0 / 5 - 0 peringkat