Ich würde gerne pylint in den Build-Prozess fürmy Python-Projekte integrieren, aber ich habe einen Show-Stopper gefunden: Einen der Fehlertypen, die ich äußerst nützlich finde--: E1101: *%s %r has no %r
member*
-- meldet ständig Fehler, wenn übliche Django-Felder verwendet werden... Zum Beispiel:
E1101:125:get_user_tags: Class 'Tag' has no 'objects' member
was durch diesen Code verursacht wird:
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
Wie kann ich Pylint so einstellen, dass Felder wie Objekte korrekt berücksichtigt werden? (Ich habe mir auch die Django-Quelle angesehen und konnte die Implementierung von objects
nicht finden, daher vermute ich, dass es nicht "nur" ein Klassenfeld ist. Auf der anderen Seite bin ich mit Python relativ neu Ich habe vielleicht etwas übersehen.)
Edit: Die einzige Möglichkeit, pylint mitzuteilen, dass es nicht vor diesen Warnungen gewarnt werden soll, ist das Blockieren aller Fehler des Typs (E1101). Dies ist keine akzeptable Lösung, da dies (meiner Meinung nach) extrem ist nützlicher Fehler. Wenn es einen anderen Weg gibt, ohne die Pylint-Quelle zu vergrößern, weisen Sie mich bitte auf Einzelheiten :)
Unter hier finden Sie eine Zusammenfassung der Probleme, die ich mit pychecker
und pyflakes
hatte - sie haben sich für den allgemeinen Gebrauch als sehr instabil erwiesen. (Im Fall von pychecker entstanden die Abstürze im pychecker-Code - nicht in der Quelle, in der sie geladen/aufgerufen wurden.)
Deaktivieren oder schwächen Sie die Pylint-Funktion nicht, indem Sie ignores
oder generated-members
hinzufügen.
Verwenden Sie ein aktiv entwickeltes Pylint-Plugin, das versteht Django.
Dieses Pylint-Plugin für Django funktioniert sehr gut:
pip install pylint-Django
und wenn Sie pylint ausführen, fügen Sie dem Befehl das folgende Flag hinzu:
--load-plugins pylint_Django
Ausführlicher Blogbeitrag hier .
Ich verwende Folgendes: pylint --generated-members=objects
Mein ~/.pylintrc enthält
[TYPECHECK]
generated-members=REQUEST,acl_users,aq_parent,objects,_meta,id
die letzten beiden sind speziell für Django.
Beachten Sie, dass es einen Fehler in PyLint 0.21.1 gibt, für den Patches erforderlich sind, damit dies funktioniert.
Edit: Nachdem ich mich damit ein wenig herumgemischt hatte, beschloss ich, PyLint ein wenig zu hacken, um mir zu erlauben, das oben genannte zu erweitern:
[TYPECHECK]
generated-members=REQUEST,acl_users,aq_parent,objects,_meta,id,[a-zA-Z]+_set
Ich fügte einfach hinzu:
import re
for pattern in self.config.generated_members:
if re.match(pattern, node.attrname):
return
nach dem im Fehlerbericht erwähnten Fix (d. h. in Zeile 129).
Glückliche Tage!
Django-Flusen sind ein schönes Werkzeug, das Pylint mit Django-spezifischen Einstellungen umschließt: http://chris-lamb.co.uk/projects/Django-lint/
github-Projekt: https://github.com/lamby/Django-lint
Aufgrund der Funktionsweise von Pylint (es untersucht die Quelle selbst, ohne dass Python sie tatsächlich ausführt) ist es für Pylint sehr schwierig, herauszufinden, wie sich Metaklassen und komplexe Basisklassen tatsächlich auf eine Klasse und ihre Instanzen auswirken. Das 'pychecker'-Tool ist in dieser Hinsicht etwas besser, weil es does tatsächlich Python den Code ausführen lässt; Es importiert die Module und untersucht die resultierenden Objekte. Dieser Ansatz hat jedoch andere Probleme, da Python den Code tatsächlich ausführen kann :-)
Sie können pylint erweitern, um die Verwendung von Magie Django zu erläutern, um Metaklassen oder komplexe Basisklassen besser zu verstehen, oder um solche Fälle einfach zu ignorieren, nachdem Sie ein oder mehrere Features entdeckt haben, die nicht ganz verstanden werden. Ich denke nicht, dass es besonders einfach wäre. Sie können pylint auch einfach anweisen, nicht vor diesen Dingen zu warnen, indem Sie spezielle Kommentare in der Quelle, in den Befehlszeilenoptionen oder in einer .pylintrc-Datei eingeben.
Wenn Sie Visual Studio-Code verwenden, gehen Sie folgendermaßen vor:
pip install pylint-Django
Und zur VSC-Konfiguration hinzufügen:
"python.linting.pylintArgs": [
"--load-plugins=pylint_Django"
],
Ich habe den Einsatz von pylint/pychecker zugunsten der Verwendung von Pyflakes mit Django-Code aufgegeben - es versucht lediglich, das Modul zu importieren und meldet alle Probleme, die es findet, wie ungenutzte Importe oder nicht initialisierte lokale Namen.
Dies ist keine Lösung, Sie können jedoch objects = models.Manager()
zu Ihren Django-Modellen hinzufügen, ohne das Verhalten zu ändern.
Ich selbst benutze nur Pyflakes, hauptsächlich aufgrund einiger dummer Defekte in Pylint und Faulheit meinerseits (ich möchte nicht nachsehen, wie man die Standardeinstellungen ändert).
Versuchen Sie, Pylint mit auszuführen
pylint --ignored-classes=Tags
Wenn dies funktioniert, fügen Sie alle anderen Django-Klassen hinzu - möglicherweise mithilfe eines Skripts, z. B. Python: P
Die Dokumentation für --ignore-classes
lautet:
--ignored-classes=<members names>
Liste der Klassennamen für welches Mitglied Attribute sollten nicht geprüft werden (nützlich für Klassen mit Attributen Dynamiksatz). [aktuell:% default]
Ich sollte hinzufügen, dass dies meiner Meinung nach keine besonders elegante Lösung ist, aber es sollte funktionieren.
Die in diesem andere Frage vorgeschlagene Lösung enthält einfach get_attr zu Ihrer Tag-Klasse. Hässlich, aber funktioniert.
Bisher habe ich keine wirkliche Lösung dafür gefunden, sondern arbeite herum:
Für neovim & vim8
verwenden Sie w0rp's ale
-Plugin. Wenn Sie alles korrekt installiert haben, einschließlich w0rp's ale
, pylint
& pylint-Django
. Fügen Sie in Ihrer vimrc
die folgende Zeile hinzu und viel Spaß beim Entwickeln von Web-Apps mit Django .
let g:ale_python_pylint_options = '--load-plugins pylint_Django'