Utiliser Pylint avec Django

140

J'aimerais beaucoup intégrer pylint dans le processus de construction de mes projets python, mais je me suis heurté à un seul show-stopper: l'un des types d'erreur que je trouve extrêmement utile--: E1101: *%s %r has no %r member*- signale en permanence des erreurs lors de l'utilisation de champs django courants , par exemple:

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

qui est causé par ce code:

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

Comment puis-je régler Pylint pour prendre correctement en compte des champs tels que des objets? (J'ai également regardé dans la source de Django, et je n'ai pas pu trouver l'implémentation de objects, donc je soupçonne que ce n'est pas "juste" un champ de classe. D'un autre côté, je suis assez nouveau en python, donc je peut très bien avoir oublié quelque chose.)

Edit: Le seul moyen que j'ai trouvé pour dire à pylint de ne pas avertir de ces avertissements est de bloquer toutes les erreurs du type (E1101), ce qui n'est pas une solution acceptable, car c'est (à mon avis) une erreur extrêmement utile. S'il y a un autre moyen, sans augmenter la source pylint, veuillez m'indiquer les détails :)

Voir ici pour un résumé des problèmes que j'ai rencontrés pycheckeret pyflakes- ils se sont avérés être très instables pour une utilisation générale. (Dans le cas de Pychecker, les plantages proviennent du code de Pychecker - et non de la source qu'il charge / invoque.)

rcreswick
la source
4
voir le post de @ talweiss pour une réponse à jour!
Brendan le
Bonne solution trouvée sur stackoverflow.com/a/31000713/78234
shahjapan
1
Pouvez-vous accepter la réponse de @talweiss? C'est la solution la plus à jour et la plus correcte.
Vijay Varadan

Réponses:

155

Ne désactivez pas ou n'affaiblissez pas la fonctionnalité Pylint en ajoutant ignoresou generated-members.
Utilisez un plugin Pylint développé activement qui comprend Django.
Ce plugin Pylint pour Django fonctionne assez bien:

pip install pylint-django

et lors de l'exécution de pylint, ajoutez l'indicateur suivant à la commande:

--load-plugins pylint_django

Article de blog détaillé ici .

Tal Weiss
la source
2
Le lien vers le billet de blog est mort (si tôt). Voici quelques liens archivés de l' Internet Archive et de archive.is
Christian Long
3
Pour le faire fonctionner avec le plugin SublimeLinter de Sublime Text, j'ai dû ajouter --load-plugins=pylint_djangoau paramètre linters / pylint / args. Notez le signe '=', cela ne fonctionnait pas sans lui.
Dennis Golomazov
ça ne marche pas. J'obtiens cette erreur: E: 8, 0: pas de nom 'modèles' dans le module 'django.db' (pas de nom dans le module)
max
6
Vous pouvez également ajouter ceci dans votre pylintrc:[MASTER] load-plugins=pylint_django
azmeuk
3
Dans vs code, cela ne fonctionnera pas pour moi jusqu'à ce que je mette ce qui suit dans les paramètres utilisateur: {"python.linting.pylintArgs": [ "--load-plugins=pylint_django" ],} réponse de tieuminh2510
ali-myousefi
63

J'utilise ce qui suit: pylint --generated-members=objects

Shai
la source
man pylint (1) under TYPECHECK --generated-members=<members names>Liste des membres qui sont définis dynamiquement et manqués par le système d'inférence pylint, et qui ne devraient donc pas déclencher E0201 et E1101 lors de l'accès. [actuel: REQUEST, acl_users, aq_parent]
Mark Mikofski
J'ajoute ceci dans PyDev dans eclipse sous les préférences de la section PyDev / PyLint .
Mark Mikofski
2
L'utilisation des membres générés ne fait que vous cacher ces erreurs, il peut toujours y avoir des erreurs lorsque vous essayez d'accéder au champ d'objets sur le mauvais objet. Utilisez plutôt le plugin pylint-django.
Vajk Hermecz
5
Ce n'est pas la bonne façon de réparer Pylint - en désactivant certaines de ses fonctionnalités. Tout ce que vous avez à faire est d'installer un plugin Pylint qui comprend Django. Voir stackoverflow.com/a/31000713/78234
Tal Weiss
31

Mon ~ / .pylintrc contient

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

les deux derniers sont spécifiquement pour Django.

Notez qu'il existe un bogue dans PyLint 0.21.1 qui a besoin d' être corrigé pour que cela fonctionne.

Edit: Après avoir déconné un peu plus avec cela, j'ai décidé de pirater un tout petit peu PyLint pour me permettre d'étendre ce qui précède en:

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

J'ai simplement ajouté:

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

après le correctif mentionné dans le rapport de bogue (c'est-à-dire à la ligne 129).

Jours heureux!

Simon
la source
Vous devez soumettre votre patch à pylint aux responsables.
slacy
en fait, ils ont inclus ce patch dans la version 0.24, mais ils ont commencé à utiliser le shlexpaquet et ont cassé autre chose maintenant. J'ai dû ajouter gen.wordchars += "[]-+"à la ligne 135 pour que cela fonctionne ...
simon
4
L'utilisation des membres générés ne fait que vous cacher ces erreurs, il peut toujours y avoir des erreurs lorsque vous essayez d'accéder au champ «objets» sur le mauvais objet. Utilisez plutôt le plugin pylint-django.
Vajk Hermecz
4
Ce n'est pas la bonne façon de réparer Pylint - en désactivant certaines de ses fonctionnalités. Tout ce que vous avez à faire est d'installer un plugin Pylint qui comprend Django. Voir stackoverflow.com/a/31000713/78234
Tal Weiss
3
@TalWeiss - pour être honnête, cette réponse a trois ans de plus que pylint-django, donc le vote négatif est un peu dur ...
Simon
27

Si vous utilisez Visual Studio Code, procédez comme suit:

pip install pylint-django

Et ajoutez à la configuration VSC:

"python.linting.pylintArgs": [
    "--load-plugins=pylint_django"
],
Thiago Falcao
la source
2
Meilleure réponse de loin: D
serfer2
19

django-lint est un bel outil qui enveloppe pylint avec des paramètres spécifiques à django: http://chris-lamb.co.uk/projects/django-lint/

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

gurney alex
la source
1
J'aime l'idée d'un pylint spécifique à Django, mais cela me semble un gros buggy la dernière fois que je l'ai essayé.
Wernight
3
De plus, il n'est pas disponible via PyPI et le site Web ne semble pas donner suffisamment d'informations comme: Quelle est la version actuelle?
Wernight
1
J'aime le concept, mais cette implémentation n'est qu'à moitié cuite et se brise sur n'importe quelle base de code de taille moyenne. Il a encore un long chemin à parcourir avant d'être réellement utile.
Cerin
1
@gurney alex, Link est mort.
navette87
2
On dirait que pylint-django est plus actif maintenant, cela devrait être la solution conseillée.
Vajk Hermecz
16

En raison du fonctionnement de pylint (il examine la source elle-même, sans laisser Python l'exécuter), il est très difficile pour pylint de comprendre comment les métaclasses et les classes de base complexes affectent réellement une classe et ses instances. L'outil «pychecker» est un peu meilleur à cet égard, car il permet en fait à Python d'exécuter le code; il importe les modules et examine les objets résultants. Cependant, cette approche présente d'autres problèmes, car elle permet en fait à Python d'exécuter le code :-)

Vous pouvez étendre pylint pour lui apprendre la magie utilisée par Django, ou pour lui faire mieux comprendre les métaclasses ou les classes de base complexes, ou simplement ignorer de tels cas après avoir détecté une ou plusieurs fonctionnalités qu'il ne comprend pas tout à fait. Je ne pense pas que ce serait particulièrement facile. Vous pouvez également simplement dire à pylint de ne pas avertir de ces choses, via des commentaires spéciaux dans la source, des options de ligne de commande ou un fichier .pylintrc.

Thomas Wouters
la source
3
Il n'est pas facile d'enseigner Django à Pylint, mais cela a été fait: il vous suffit d'installer un plugin Pylint qui comprend Django. Voir stackoverflow.com/a/31000713/78234
Tal Weiss
Eh bien, je l'ai installé mais il contient toujours des minces comme QuerySet n'a pas de suppression ...
Eino Mäkitalo
7

J'ai démissionné de l'utilisation de pylint / pychecker en faveur de l'utilisation de pyflakes avec le code Django - il essaie juste d'importer le module et signale tout problème qu'il trouve, comme des importations inutilisées ou des noms locaux non initialisés.

zgoda
la source
intéressant - je vais donner un autre regard aux pyflakes.
rcreswick le
2
PyChecker attrape beaucoup moins que pylint. doughellmann.com/articles/CompletelyDifferent-2008-03-linters/…
Justin Abrahms
1
Pas besoin d'abandonner Pylint - Tout ce que vous avez à faire est d'installer un plugin Pylint qui comprend Django. Voir stackoverflow.com/a/31000713/78234
Tal Weiss
7

Ce n'est pas une solution, mais vous pouvez ajouter objects = models.Manager()à vos modèles Django sans changer de comportement.

Je n'utilise moi-même que des pyflakes, principalement en raison de certains défauts stupides dans pylint et de la paresse de ma part (ne voulant pas chercher comment changer les valeurs par défaut).

AdamKG
la source
Ah ... merci pour le tuyau. Je peux essayer d'ajouter cela à Model.models dans la copie locale de la source de django, et voir si cela le fait.
rcreswick le
Je pense que c'est une excellente solution car elle ne fait aucun compromis sur les avertissements.
Tom Leys
1
C'est une mauvaise solution. Se répéter et remplacer quelque chose qui est faisable changera plus tard (introduisant ainsi un problème d'AQ), juste pour corriger un outil d'AQ incomplet?
Chris Morgan du
2
Je n'appellerais pas cela une mauvaise solution: l'explicite vaut mieux que l'implicite. Peut objects-être ne devrait pas être ajouté par magie de toute façon.
Will Hardy
1
Je pense que ce n'est pas la bonne façon de réparer Pylint - en corrigeant Django dans un sens. Tout ce que vous avez à faire est d'installer un plugin Pylint qui comprend Django. Voir stackoverflow.com/a/31000713/78234
Tal Weiss
5

Essayez d'exécuter pylint avec

pylint --ignored-classes=Tags

Si cela fonctionne, ajoutez toutes les autres classes Django - éventuellement en utilisant un script, par exemple python: P

La documentation pour --ignore-classesest:

--ignored-classes=<members names>
Liste des noms de classes pour lesquels les attributs membres ne doivent pas être vérifiés (utile pour les classes avec des attributs définis dynamiquement). [actuel:% par défaut]

Je dois ajouter que ce n'est pas une solution particulièrement élégante à mon avis, mais cela devrait fonctionner.

espace libre
la source
Cela ne fonctionne que si je ne fais jamais d'erreur dans ces classes;). Je veux éviter d'ignorer le code dans la mesure du possible - je pense que c'est une très mauvaise idée de faire analyser différentes parties de la base de code à différents degrés d'examen. J'oublierai qui est qui et ferai de fausses hypothèses lors du débogage
rcreswick
1
Ce n'est pas la bonne façon de réparer Pylint - en désactivant certaines de ses fonctionnalités. Tout ce que vous avez à faire est d'installer un plugin Pylint qui comprend Django. Voir stackoverflow.com/a/31000713/78234
Tal Weiss
3

La solution proposée dans cette autre question est d'ajouter simplement get_attr à votre classe Tag. Moche, mais ça marche.

Eric
la source
1

Jusqu'à présent, je n'ai trouvé aucune vraie solution à cela, mais contourner:

  • Dans notre entreprise, nous exigeons un score pylint> 8. Cela permet des pratiques de codage que pylint ne comprend pas tout en s'assurant que le code n'est pas trop "inhabituel". Jusqu'à présent, nous n'avons vu aucun exemple où E1101 nous a empêchés d'atteindre un score de 8 ou plus.
  • Nos cibles 'make check' filtrent les messages "car n'a aucun membre" objets "pour supprimer la plupart des distractions causées par pylint ne comprenant pas Django.
max
la source
0

Pour neovim & vim8utiliser le w0rp's aleplugin. Si vous avez tout installé correctement, y compris w0rp's ale, pylint& pylint-django. Dans votre vimrcajoutez la ligne suivante et amusez-vous à développer des applications Web à l'aide de django. Merci.

let g:ale_python_pylint_options = '--load-plugins pylint_django'
Ganesh
la source