Menggunakan Pylint dengan Django

140

Saya sangat ingin mengintegrasikan pylint ke dalam proses pembangunan untuk proyek python saya, tetapi saya telah mengalami satu show-stopper: Salah satu jenis kesalahan yang saya temukan sangat berguna--: - E1101: *%s %r has no %r member*Terus-menerus melaporkan kesalahan saat menggunakan bidang Django umum , sebagai contoh:

E1101:125:get_user_tags: Class 'Tag' has no 'objects' member

yang disebabkan oleh kode ini:

def get_user_tags(username):
   """
   Gets all the tags that username has used.

   Returns a query set.
   """
   return Tag.objects.filter(  ## This line triggers the error.
       tagownership__users__username__exact=username).distinct()

# Here is the Tag class, models.Model is provided by Django:
class Tag(models.Model):
   """
   Model for user-defined strings that help categorize Events on
   on a per-user basis.
   """
   name = models.CharField(max_length=500, null=False, unique=True)

   def __unicode__(self):
       return self.name

Bagaimana saya bisa menyetel Pylint agar mengambil bidang seperti objek dengan benar? (Saya juga telah melihat ke sumber Django, dan saya tidak dapat menemukan implementasi objects, jadi saya menduga itu bukan "hanya" bidang kelas. Di sisi lain, saya cukup baru untuk python, jadi saya mungkin telah mengabaikan sesuatu.)

Edit: Satu-satunya cara yang saya temukan untuk memberitahu pylint untuk tidak memperingatkan tentang peringatan ini adalah dengan memblokir semua kesalahan jenis (E1101) yang bukan merupakan solusi yang dapat diterima, karena itu (menurut saya) merupakan kesalahan yang sangat berguna. Jika ada cara lain, tanpa menambah sumber pylint, harap tunjukkan saya secara spesifik :)

Lihat di sini untuk ringkasan masalah yang saya alami pycheckerdan pyflakes- mereka terbukti jauh dari tidak stabil untuk penggunaan umum. (Dalam kasus pychecker, crash berasal dari kode pychecker - bukan sumber yang dimuat / dipanggil.)

rcreswick
sumber
4
lihat posting @ talweiss untuk jawaban terkini!
Brendan
Menemukan solusi yang baik di stackoverflow.com/a/31000713/78234
shahjapan
1
Bisakah Anda menerima jawaban @talweiss? Ini adalah solusi yang paling mutakhir dan benar.
Vijay Varadan

Jawaban:

155

Jangan menonaktifkan atau melemahkan fungsionalitas Pylint dengan menambahkan ignoresatau generated-members.
Gunakan plugin Pylint yang dikembangkan secara aktif yang memahami Django.
Plugin Pylint untuk Django ini bekerja dengan sangat baik:

pip install pylint-django

dan saat menjalankan pylint tambahkan flag berikut ke perintah:

--load-plugins pylint_django

Posting blog terinci di sini .

Tal Weiss
sumber
2
Tautan ke posting blog sudah mati (segera). Berikut adalah beberapa tautan yang diarsipkan dari Internet Archive dan dari archive.is
Christian Long
3
Untuk membuatnya bekerja dengan plugin SublimeLinter Teks Sublime, saya harus menambahkan --load-plugins=pylint_djangopengaturan linters / pylint / args. Perhatikan tanda '=', itu tidak berfungsi tanpanya.
Dennis Golomazov
tidak bekerja. Saya mendapatkan kesalahan ini: E: 8, 0: Tidak ada nama 'model' dalam modul 'django.db' (tanpa-nama-dalam-modul)
maks
6
Anda juga dapat menambahkan ini di pylintrc Anda:[MASTER] load-plugins=pylint_django
azmeuk
3
Dalam vs kode itu dosis tidak bekerja untuk saya sampai saya Masukkan yang berikut di pengaturan pengguna: {"python.linting.pylintArgs": [ "--load-plugins=pylint_django" ],} jawaban tieuminh2510
ali-myousefi
63

Saya menggunakan yang berikut ini: pylint --generated-members=objects

Shai
sumber
man pylint (1) di bawah TYPECHECK --generated-members=<members names>Daftar anggota yang ditetapkan secara dinamis dan tidak terjawab oleh sistem inferensi pylint, dan karenanya tidak boleh memicu E0201 dan E1101 ketika diakses. [sekarang: REQUEST, acl_users, aq_parent]
Mark Mikofski
Saya menambahkan ini di PyDev di gerhana di bawah preferensi di bagian PyDev / PyLint .
Mark Mikofski
2
Menggunakan anggota yang dihasilkan hanya menyembunyikan kesalahan ini dari Anda, masih ada kesalahan ketika mencoba mengakses bidang objek pada objek yang salah. Gunakan plugin pylint-django sebagai gantinya.
Vajk Hermecz
5
Ini adalah cara yang salah untuk memperbaiki Pylint - dengan menonaktifkan sebagian fungsinya. Yang perlu Anda lakukan adalah menginstal plugin Pylint yang mengerti Django. Lihat stackoverflow.com/a/31000713/78234
Tal Weiss
31

My ~ / .pylintrc mengandung

[TYPECHECK]
generated-members=REQUEST,acl_users,aq_parent,objects,_meta,id

dua yang terakhir khusus untuk Django.

Perhatikan bahwa ada bug di PyLint 0.21.1 yang perlu ditambal untuk membuatnya berfungsi.

Sunting: Setelah mengacaukan ini sedikit lagi, saya memutuskan untuk meretas PyLint sedikit saja agar saya dapat memperluas hal di atas menjadi:

[TYPECHECK]
generated-members=REQUEST,acl_users,aq_parent,objects,_meta,id,[a-zA-Z]+_set

Saya hanya menambahkan:

    import re
    for pattern in self.config.generated_members:
        if re.match(pattern, node.attrname):
            return

setelah perbaikan disebutkan dalam laporan bug (yaitu, pada baris 129).

Hari hari menyenangkan!

simon
sumber
Anda harus mengirimkan tambalan Anda ke pylint kembali ke pengelola.
slacy
sebenarnya mereka sudah memasukkan tambalan ini di 0,24, tetapi mereka sudah mulai menggunakan shlexpaket, dan merusak sesuatu yang lain sekarang. Saya harus menambahkan gen.wordchars += "[]-+"pada baris 135 untuk membuatnya berfungsi ...
simon
4
Menggunakan anggota yang dihasilkan hanya menyembunyikan kesalahan ini dari Anda, masih ada kesalahan ketika mencoba mengakses bidang 'objek' pada objek yang salah. Gunakan plugin pylint-django sebagai gantinya.
Vajk Hermecz
4
Ini adalah cara yang salah untuk memperbaiki Pylint - dengan menonaktifkan sebagian fungsinya. Yang perlu Anda lakukan adalah menginstal plugin Pylint yang mengerti Django. Lihat stackoverflow.com/a/31000713/78234
Tal Weiss
3
@ Talweiss - dalam keadilan, jawaban ini tiga tahun lebih tua dari pylint-django, jadi downvote agak keras ...
simon
27

Jika Anda menggunakan Visual Studio Code lakukan ini:

pip install pylint-django

Dan tambahkan ke konfigurasi VSC:

"python.linting.pylintArgs": [
    "--load-plugins=pylint_django"
],
Thiago Falcao
sumber
2
Tanggapan terbaik sejauh ini: D
serfer2
19

django-lint adalah alat yang bagus yang membungkus pylint dengan pengaturan spesifik Django: http://chris-lamb.co.uk/projects/django-lint/

proyek github: https://github.com/lamby/django-lint

brankar alex
sumber
1
Saya suka gagasan pylint khusus-Django, tetapi tampaknya kereta besar terakhir kali saya mencobanya.
Wernight
3
Juga tidak tersedia melalui PyPI dan situs web sepertinya tidak memberikan cukup info seperti: Apa versi saat ini?
Wernight
1
Saya suka konsepnya, tetapi implementasi ini hanya setengah matang, dan merusak basis kode berukuran sedang. Masih banyak jalan yang harus ditempuh sebelum ini berguna.
Cerin
1
@ Gurney alex, Tautan sudah mati.
Antar jemput87
2
Sepertinya pylint-django lebih aktif sekarang, yang seharusnya menjadi solusi yang disarankan.
Vajk Hermecz
16

Karena cara kerja pylint (memeriksa sumbernya sendiri, tanpa membiarkan Python benar-benar mengeksekusinya), sangat sulit bagi pylint untuk mengetahui bagaimana metaclasses dan baseclasses kompleks benar-benar memengaruhi kelas dan instansnya. Alat 'pychecker' sedikit lebih baik dalam hal ini, karena memang demikian benar benar membiarkan Python mengeksekusi kode; itu mengimpor modul dan memeriksa objek yang dihasilkan. Namun, pendekatan itu memiliki masalah lain, karena itu benar-benar membiarkan Python mengeksekusi kode :-)

Anda bisa memperluas pylint untuk mengajarkannya tentang sihir yang digunakan Django, atau membuatnya lebih memahami metaclasses atau baseclasses kompleks, atau mengabaikan kasus-kasus seperti itu setelah mendeteksi satu atau lebih fitur yang tidak terlalu dipahami. Saya tidak berpikir itu akan sangat mudah. Anda juga bisa memberi tahu pylint untuk tidak memperingatkan tentang hal-hal ini, melalui komentar khusus pada sumber, opsi baris perintah atau file .pylintrc.

Thomas Wouters
sumber
3
Memang tidak mudah untuk mengajarkan Pylint tentang Django, tetapi telah dilakukan: Yang perlu Anda lakukan hanyalah menginstal plugin Pylint yang mengerti Django. Lihat stackoverflow.com/a/31000713/78234
Tal Weiss
Yah saya menginstalnya tetapi masih berisi tentang menipis seperti QuerySet tidak memiliki menghapus ...
Eino Mäkitalo
7

Saya mengundurkan diri dari menggunakan pylint / pychecker untuk menggunakan pyflakes dengan kode Django - itu hanya mencoba mengimpor modul dan melaporkan setiap masalah yang ditemukannya, seperti impor yang tidak digunakan atau nama lokal yang tidak diinisialisasi.

zgoda
sumber
menarik - saya akan memberikan pyflakes tampilan lain.
rcreswick
2
PyChecker menangkap jauh lebih sedikit daripada pylint. doughellmann.com/articles/CompletelyDifferent-2008-03-linters/…
Justin Abrahms
1
Tidak perlu menyerah pada Pylint - Yang perlu Anda lakukan adalah menginstal plugin Pylint yang mengerti Django. Lihat stackoverflow.com/a/31000713/78234
Tal Weiss
7

Ini bukan solusi, tetapi Anda dapat menambah objects = models.Manager()model Django Anda tanpa mengubah perilaku apa pun.

Saya sendiri hanya menggunakan pyflakes, terutama karena beberapa default bodoh di pylint dan kemalasan pada bagian saya (tidak ingin mencari cara mengubah default).

AdamKG
sumber
Ah ... terima kasih atas tipnya. Saya dapat mencoba menambahkannya ke Model.models di salinan lokal dari sumber Django, dan lihat apakah itu bisa.
rcreswick
Saya pikir ini solusi hebat karena tidak kompromi dengan peringatan.
Tom Leys
1
Ini solusi yang buruk . Mengulangi diri sendiri dan mengganti sesuatu yang layak akan berubah nanti (dengan demikian memperkenalkan masalah QA), hanya untuk memperbaiki alat QA yang tidak lengkap?
Chris Morgan
2
Saya tidak akan menyebut ini solusi yang buruk: eksplisit lebih baik daripada implisit. Mungkin objectsseharusnya tidak ditambahkan secara ajaib.
Will Hardy
1
Saya pikir ini adalah cara yang salah untuk memperbaiki Pylint - dengan menambal Django dalam arti tertentu. Yang perlu Anda lakukan adalah menginstal plugin Pylint yang mengerti Django. Lihat stackoverflow.com/a/31000713/78234
Tal Weiss
5

Coba jalankan pylint dengan

pylint --ignored-classes=Tags

Jika berhasil, tambahkan semua kelas Django lainnya - mungkin menggunakan skrip, misalnya, python: P

Dokumentasi untuk --ignore-classesadalah:

--ignored-classes=<members names>
Daftar nama kelas yang atribut anggota tidak boleh diperiksa (berguna untuk kelas dengan atribut yang ditetapkan secara dinamis). [saat ini:% default]

Saya harus menambahkan ini bukan solusi elegan khusus dalam pandangan saya, tetapi harus berhasil.

ruang bebas
sumber
Ini hanya berfungsi jika saya tidak pernah membuat kesalahan di kelas-kelas itu;). Saya ingin menghindari mengabaikan kode jika memungkinkan - saya pikir itu adalah ide yang sangat buruk untuk memiliki bagian yang berbeda dari basis kode dianalisis dengan berbagai tingkat pengawasan. Saya akan lupa yang mana, dan membuat asumsi yang salah saat debugging
rcreswick
1
Ini adalah cara yang salah untuk memperbaiki Pylint - dengan menonaktifkan sebagian fungsinya. Yang perlu Anda lakukan adalah menginstal plugin Pylint yang mengerti Django. Lihat stackoverflow.com/a/31000713/78234
Tal Weiss
3

Solusi yang diajukan dalam pertanyaan lain ini adalah menambahkan get_attr ke kelas Tag Anda. Jelek, tapi berhasil.

eric
sumber
1

Sejauh ini saya belum menemukan solusi nyata untuk itu tetapi bekerja di sekitar:

  • Di perusahaan kami, kami membutuhkan skor pylint> 8. Ini memungkinkan praktik pengkodean pylint tidak mengerti sambil memastikan bahwa kode tersebut tidak terlalu "tidak biasa". Sejauh ini kami belum melihat contoh di mana E1101 mencegah kami mencapai skor 8 atau lebih tinggi.
  • Target 'make check' kami memfilter pesan "untuk tidak memiliki anggota 'objek' untuk menghapus sebagian besar gangguan yang disebabkan oleh pylint yang tidak memahami Django.
maks
sumber
0

Untuk neovim & vim8menggunakan w0rp's aleplugin. Jika Anda telah menginstal semuanya dengan benar termasuk w0rp's ale, pylint& pylint-django. Di vimrcbaris Anda tambahkan & bersenang-senang mengembangkan aplikasi web menggunakan Django. Terima kasih.

let g:ale_python_pylint_options = '--load-plugins pylint_django'
Ganesha
sumber