Usando Pylint con Django

140

Me gustaría mucho integrar pylint en el proceso de compilación para mis proyectos de Python, pero me he encontrado con un show-stopper: uno de los tipos de error que encuentro extremadamente útil: E1101: *%s %r has no %r member*- informa constantemente errores al usar campos comunes de django , por ejemplo:

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

que es causado por este código:

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

¿Cómo puedo ajustar Pylint para tener en cuenta correctamente campos como los objetos? (También busqué en la fuente de Django y no pude encontrar la implementación objects, por lo que sospecho que no es "solo" un campo de clase. Por otro lado, soy bastante nuevo en Python, así que puede muy bien haber pasado por alto algo).

Editar: La única forma en que he encontrado decirle a pylint que no advierta sobre estas advertencias es bloqueando todos los errores del tipo (E1101) que no es una solución aceptable, ya que es (en mi opinión) un error extremadamente útil. Si hay otra forma, sin aumentar la fuente de pylint, indíqueme detalles :)

Vea aquí un resumen de los problemas que he tenido pycheckery pyflakesque han demostrado ser muy inestables para uso general. (En el caso de pychecker, los bloqueos se originaron en el código de pychecker, no en el origen que se estaba cargando / invocando).

rcreswick
fuente
44
¡Vea la publicación de @talweiss para obtener una respuesta actualizada!
Brendan
Encontramos una buena solución en stackoverflow.com/a/31000713/78234
shahjapan el
1
¿Pueden aceptar la respuesta de @talweiss? Es la solución más actualizada y correcta.
Vijay Varadan

Respuestas:

155

No deshabilite ni debilite la funcionalidad de Pylint agregando ignoreso generated-members.
Use un complemento Pylint desarrollado activamente que entienda Django.
Este complemento de Pylint para Django funciona bastante bien:

pip install pylint-django

y cuando ejecute pylint agregue la siguiente bandera al comando:

--load-plugins pylint_django

Publicación detallada del blog aquí .

Tal Weiss
fuente
2
El enlace a la publicación del blog está muerto (muy pronto). Aquí hay algunos enlaces archivados de Internet Archive y de archive.is
Christian Long
3
Para que funcione con el complemento SublimeLinter de Sublime Text, tuve que agregar --load-plugins=pylint_djangoa la configuración linters / pylint / args. Tenga en cuenta el signo '=', no funcionó sin él.
Dennis Golomazov
No funciona. Me sale este error: E: 8, 0: Sin nombre 'modelos' en el módulo 'django.db' (sin nombre en el módulo)
máx
66
También puede agregar esto en su pylintrc:[MASTER] load-plugins=pylint_django
azmeuk
3
En el código vs no me funciona hasta que pongo lo siguiente en la configuración del usuario: {"python.linting.pylintArgs": [ "--load-plugins=pylint_django" ],} respuesta de tieuminh2510
ali-myousefi
63

Yo uso lo siguiente: pylint --generated-members=objects

Shai
fuente
man pylint (1) en TYPECHECK --generated-members=<members names>Lista de miembros configurados dinámicamente y omitidos por el sistema de inferencia pylint, por lo que no deberían activar E0201 y E1101 cuando se accede a ellos. [actual: SOLICITUD, acl_users, aq_parent]
Mark Mikofski
Agrego esto en PyDev en eclipse bajo preferencias en la sección PyDev / PyLint .
Mark Mikofski
2
El uso de miembros generados simplemente le oculta estos errores, aún puede haber errores al intentar acceder al campo de objetos en el objeto incorrecto. Utilice el complemento pylint-django en su lugar.
Vajk Hermecz
55
Esta es la forma incorrecta de arreglar Pylint, deshabilitando algunas de sus funciones. Todo lo que necesita hacer es instalar un complemento Pylint que entienda Django. Ver stackoverflow.com/a/31000713/78234
Tal Weiss
31

Mi ~ / .pylintrc contiene

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

Los dos últimos son específicamente para Django.

Tenga en cuenta que hay un error en PyLint 0.21.1 que necesita parches para que esto funcione.

Editar: Después de jugar un poco más con esto, decidí piratear PyLint solo un poco para permitirme expandir lo anterior en:

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

Simplemente agregué:

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

después de la corrección mencionada en el informe de error (es decir, en la línea 129).

¡Días felices!

Simón
fuente
Debería enviar su parche a pylint a los encargados de mantenimiento.
Slacy
en realidad, incluyeron este parche en 0.24, pero comenzaron a usar el shlexpaquete y ahora rompieron algo más. Tuve que agregar gen.wordchars += "[]-+"en la línea 135 para que funcione ...
Simon
44
El uso de miembros generados solo te oculta estos errores, aún puede haber errores al intentar acceder al campo 'objetos' en el objeto incorrecto. Utilice el complemento pylint-django en su lugar.
Vajk Hermecz
44
Esta es la forma incorrecta de arreglar Pylint, deshabilitando algunas de sus funciones. Todo lo que necesita hacer es instalar un complemento Pylint que entienda Django. Ver stackoverflow.com/a/31000713/78234
Tal Weiss
3
@TalWeiss - para ser justos, esta respuesta es tres años mayor que pylint-django, por lo que el downvote es un poco duro ...
Simon
27

Si usa Visual Studio Code, haga esto:

pip install pylint-django

Y agregue a la configuración de VSC:

"python.linting.pylintArgs": [
    "--load-plugins=pylint_django"
],
Thiago Falcao
fuente
2
Mejor respuesta con diferencia: D
serfer2
19

django-lint es una buena herramienta que envuelve pylint con configuraciones específicas de django: http://chris-lamb.co.uk/projects/django-lint/

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

camilla alex
fuente
1
Me gusta la idea de un pylint específico de Django, pero parece un gran error la última vez que lo probé.
Wernight
3
Además, no está disponible a través de PyPI y el sitio web no parece proporcionar suficiente información como: ¿Cuál es la versión actual?
Wernight
1
Me gusta el concepto, pero esta implementación solo está a medias y se rompe en cualquier base de código de tamaño moderado. Tiene un largo camino por recorrer antes de que sea realmente útil.
Cerin
1
@gurney alex, Link está muerto.
shuttle87
2
Parece que pylint-django está más activo ahora, esa debería ser la solución recomendada.
Vajk Hermecz
16

Debido a cómo funciona pylint (examina la fuente en sí, sin dejar que Python realmente lo ejecute) es muy difícil para pylint descubrir cómo las metaclases y las clases base complejas realmente afectan a una clase y sus instancias. La herramienta 'pychecker' es un poco mejor en este sentido, ya que no en realidad dejó Python ejecutar el código; importa los módulos y examina los objetos resultantes. Sin embargo, ese enfoque tiene otros problemas, porque en realidad permite que Python ejecute el código :-)

Puede extender pylint para enseñarle sobre la magia que usa Django, o para que comprenda mejor las metaclases o las clases base complejas, o simplemente ignore estos casos después de detectar una o más características que no comprende del todo. No creo que sea particularmente fácil. También puede decirle a pylint que no advierta sobre estas cosas, a través de comentarios especiales en la fuente, opciones de línea de comandos o un archivo .pylintrc.

Thomas Wouters
fuente
3
No es fácil enseñarle a Pylint sobre Django, pero se ha hecho: todo lo que necesita hacer es instalar un complemento de Pylint que entienda Django. Ver stackoverflow.com/a/31000713/78234
Tal Weiss
Bueno, lo instalé pero todavía se compara con cosas delgadas como QuerySet no tiene quitar ...
Eino Mäkitalo
7

Renuncié a usar pylint / pychecker a favor de usar pyflakes con código Django: solo intenta importar el módulo e informa cualquier problema que encuentre, como importaciones no utilizadas o nombres locales no inicializados.

zgoda
fuente
interesante: le echaré otra mirada a pyflakes.
rcreswick
2
PyChecker atrapa mucho menos que pylint. doughellmann.com/articles/CompletelyDifferent-2008-03-linters/…
Justin Abrahms el
1
No es necesario renunciar a Pylint: todo lo que necesita hacer es instalar un complemento de Pylint que comprenda Django. Ver stackoverflow.com/a/31000713/78234
Tal Weiss
7

Esta no es una solución, pero puede agregarla objects = models.Manager()a sus modelos de Django sin cambiar ningún comportamiento.

Yo solo uso pyflakes, principalmente debido a algunos valores predeterminados tontos en pylint y pereza de mi parte (no queriendo buscar cómo cambiar los valores predeterminados).

AdamKG
fuente
Ah ... gracias por el consejo. Puedo intentar simplemente agregar eso a Model.models en la copia local de la fuente django, y ver si eso lo hace.
rcreswick
Creo que esta es una gran solución porque no compromete las advertencias.
Tom Leys
1
Esta es una mala solución. Repitiéndose y reemplazando algo que es factible cambiará más tarde (por lo tanto, se presenta un problema de control de calidad), ¿solo para arreglar una herramienta de control de calidad incompleta?
Chris Morgan
2
No llamaría a esto una mala solución: explícito es mejor que implícito. Quizás objectsno debería agregarse mágicamente de todos modos.
Will Hardy
1
Creo que esta es la forma incorrecta de arreglar Pylint, parcheando a Django en cierto sentido. Todo lo que necesita hacer es instalar un complemento Pylint que entienda Django. Ver stackoverflow.com/a/31000713/78234
Tal Weiss
5

Intenta ejecutar pylint con

pylint --ignored-classes=Tags

Si eso funciona, agregue todas las otras clases de Django, posiblemente utilizando un script, por ejemplo, python: P

La documentación para --ignore-classeses:

--ignored-classes=<members names>
Lista de nombres de clases para los que no se deben verificar los atributos de los miembros (útil para clases con atributos establecidos dinámicamente). [actual:% predeterminado]

Debo agregar que, en mi opinión, esta no es una solución elegante en particular, pero debería funcionar.

espacio libre
fuente
Solo funciona si nunca cometo ningún error en esas clases;). Si es posible, quiero evitar ignorar el código; creo que es una muy mala idea que diferentes partes de la base de código analicen diferentes grados de escrutinio.
Olvidaré
1
Esta es la forma incorrecta de arreglar Pylint, deshabilitando algunas de sus funciones. Todo lo que necesita hacer es instalar un complemento Pylint que entienda Django. Ver stackoverflow.com/a/31000713/78234
Tal Weiss
3

La solución propuesta en esta otra pregunta es simplemente agregar get_attr a su clase Tag. Feo, pero funciona.

eric
fuente
1

Hasta ahora no he encontrado una solución real para eso, pero evite:

  • En nuestra empresa, requerimos un puntaje de pylint> 8. Esto permite prácticas de codificación que pylint no comprende al tiempo que garantiza que el código no sea demasiado "inusual". Hasta ahora no hemos visto ninguna instancia en la que E1101 nos haya impedido alcanzar un puntaje de 8 o más.
  • Nuestros objetivos 'make check' filtran los mensajes "porque no tiene miembros 'objetos'" para eliminar la mayor parte de la distracción causada por pylint que no comprende Django.
max
fuente
0

Para neovim & vim8uso del w0rp's alecomplemento. Si ha instalado todo correctamente w0rp's ale, incluyendo , pylint& pylint-django. En su vimrccomplemento, la siguiente línea y diviértase desarrollando aplicaciones web usando django. Gracias.

let g:ale_python_pylint_options = '--load-plugins pylint_django'
Ganesh
fuente