Использование Pylint с Django

142

Я очень хотел бы интегрировать pylint в процесс сборки для моих проектов python, но я столкнулся с одним show-stopper: один из типов ошибок, которые я считаю чрезвычайно полезными -: - E1101: *%s %r has no %r member*постоянно сообщает об ошибках при использовании общих полей django , например:

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

что вызвано этим кодом:

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

Как настроить Pylint для правильного учета таких полей, как объекты? (Я также изучил исходный код Django, и мне не удалось найти реализацию objects, поэтому я подозреваю, что это не «просто» поле класса. С другой стороны, я новичок в python, поэтому я вполне мог что-то пропустить.)

Изменить: единственный способ, который я нашел, чтобы сообщить pylint не предупреждать об этих предупреждениях, - это заблокировать все ошибки типа (E1101), что не является приемлемым решением, поскольку это (на мой взгляд) чрезвычайно полезная ошибка. Если есть другой способ, без дополнения источника pylint, укажите мне конкретику :)

См. Здесь краткое изложение проблем, с которыми я столкнулся, pycheckerи pyflakes- они оказались очень нестабильными для общего использования. (В случае pychecker сбои возникли в коде pychecker, а не в источнике, который он загружал / вызывал.)

Rcreswick
источник
4
см. сообщение @talweiss для получения актуального ответа!
Брендан
Нашел хорошее решение на stackoverflow.com/a/31000713/78234
shahjapan
2
Не могли бы вы принять ответ @talweiss? Это самое актуальное и правильное решение.
Виджей Варадан

Ответы:

157

Не отключайте и не ослабляйте функциональность Pylint, добавляя ignoresили generated-members.
Используйте активно разрабатываемый плагин Pylint, который понимает Django.
Этот плагин Pylint для Django работает неплохо:

pip install pylint-django

и при запуске pylint добавьте к команде следующий флаг:

--load-plugins pylint_django

Подробное сообщение в блоге здесь .

Тал Вайс
источник
2
Ссылка на сообщение в блоге мертва (так скоро). Вот некоторые заархивированные ссылки из Интернет-архива и из archive.is
Кристиан Лонг
3
Чтобы он работал с плагином SublimeLinter Sublime Text, мне пришлось добавить --load-plugins=pylint_djangoнастройку linters / pylint / args. Обратите внимание на знак «=», без него ничего не получилось.
Денис Голомазов
это не работает. Я получаю эту ошибку: E: 8, 0: Нет имени 'models' в модуле 'django.db' (no-name-in-module)
максимум
7
Вы также можете добавить это в свой pylintrc:[MASTER] load-plugins=pylint_django
azmeuk
3
В коде vs это не сработает для меня, пока я не {"python.linting.pylintArgs": [ "--load-plugins=pylint_django" ],} введу
ali-myousefi
63

Я использую следующее: pylint --generated-members=objects

Шай
источник
man pylint (1) в TYPECHECK --generated-members=<members names>Список элементов, которые устанавливаются динамически и пропускаются системой вывода pylint, поэтому не должны запускать E0201 и E1101 при доступе. [current: REQUEST, acl_users, aq_parent]
Марк Микофски
Я добавляю это в PyDev в eclipse в настройках в разделе PyDev / PyLint .
Марк Микофски
2
Использование сгенерированных членов просто скрывает эти ошибки от вас, все еще могут быть ошибки при попытке доступа к полю объектов не того объекта. Вместо этого используйте плагин pylint-django.
Vajk Hermecz
5
Это неправильный способ исправить Pylint - отключив некоторые его функции. Все, что вам нужно сделать, это установить плагин Pylint, который понимает Django. См. Stackoverflow.com/a/31000713/78234
Tal Weiss
32

Если вы используете Visual Studio Code, сделайте следующее:

pip install pylint-django

И добавляем в конфиг VSC:

"python.linting.pylintArgs": [
    "--load-plugins=pylint_django"
],
Тьяго Фалькао
источник
2
Лучший ответ на сегодняшний день: D
serfer2
31

Мой ~ / .pylintrc содержит

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

последние два предназначены специально для Django.

Обратите внимание, что в PyLint 0.21.1 есть ошибка, которую нужно исправить, чтобы это работало.

Изменить: немного поработав с этим, я решил немного взломать PyLint, чтобы позволить мне расширить приведенное выше до:

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

Я просто добавил:

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

после исправления, упомянутого в отчете об ошибке (т. е. в строке 129).

Счастливые дни!

Саймон
источник
Вам следует отправить патч в pylint обратно разработчикам.
slacy
на самом деле они включили этот патч в 0.24, но они начали использовать shlexпакет и сломали кое-что еще. Мне пришлось добавить gen.wordchars += "[]-+"в строку 135, чтобы заставить его работать ...
Саймон
4
Использование сгенерированных членов просто скрывает эти ошибки от вас, все еще могут быть ошибки при попытке доступа к полю «объекты» не того объекта. Вместо этого используйте плагин pylint-django.
Vajk Hermecz
4
Это неправильный способ исправить Pylint - отключив некоторые его функции. Все, что вам нужно сделать, это установить плагин Pylint, который понимает Django. См. Stackoverflow.com/a/31000713/78234
Tal Weiss
3
@TalWeiss - честно говоря, этот ответ на три года старше pylint-django, так что отрицательный голос немного резок ...
Саймон
19

django-lint - хороший инструмент, который обертывает pylint специфическими настройками django: http://chris-lamb.co.uk/projects/django-lint/

проект github: https://github.com/lamby/django-lint

Герни Алекс
источник
1
Мне нравится идея pylint, специфичного для Django, но в последний раз, когда я ее пробовал, она показалась мне большой ошибкой.
Wernight,
3
Кроме того, он недоступен через PyPI, и на сайте, похоже, недостаточно информации, например: Какая текущая версия?
Wernight
1
Мне нравится эта концепция, но эта реализация является лишь недоработанной и не работает на любой кодовой базе среднего размера. Ему предстоит пройти долгий путь, прежде чем он станет действительно полезным.
Cerin
1
@gurney alex, линк мертв.
Shuttle87
2
Похоже, что pylint-django сейчас более активен, это должно быть рекомендуемым решением.
Vajk Hermecz
16

Из-за того, как работает pylint (он проверяет сам исходный код, не позволяя Python выполнить его на самом деле), для pylint очень сложно выяснить, как метаклассы и сложные базовые классы на самом деле влияют на класс и его экземпляры. «Pychecker» инструмент немного лучше в этом отношении, потому что он делает на самом деле пусть Python выполнения кода; он импортирует модули и проверяет полученные объекты. Однако у этого подхода есть другие проблемы, потому что он действительно позволяет Python выполнять код :-)

Вы можете расширить pylint, чтобы научить его магии, которую использует Django, или чтобы он лучше понимал метаклассы или сложные базовые классы, или просто игнорировал такие случаи после обнаружения одной или нескольких функций, которые он не совсем понимает. Не думаю, что это будет особенно легко. Вы также можете просто указать pylint не предупреждать об этих вещах с помощью специальных комментариев в исходном коде, параметров командной строки или файла .pylintrc.

Томас Воутерс
источник
3
Научить Pylint работе с Django непросто, но это было сделано: все, что вам нужно сделать, это установить плагин Pylint, который понимает Django. См. Stackoverflow.com/a/31000713/78234
Tal Weiss
Ну, я установил его, но он по-прежнему жалуется на тонкости, например, QuerySet не имеет удаления ...
Эйно Мякитало
7

Я отказался от использования pylint / pychecker в пользу использования pyflakes с кодом Django - он просто пытается импортировать модуль и сообщает о любых обнаруженных проблемах, таких как неиспользуемый импорт или неинициализированные локальные имена.

zgoda
источник
интересно - еще раз посмотрю на пифлейк.
rcreswick,
2
PyChecker ловит гораздо меньше, чем pylint. doughellmann.com/articles/CompletelyDifferent-2008-03-linters/…
Джастин Абрамс
1
Не нужно отказываться от Pylint - все, что вам нужно сделать, это установить плагин Pylint, который понимает Django. См. Stackoverflow.com/a/31000713/78234
Tal Weiss
7

Это не решение, но вы можете добавлять objects = models.Manager()в свои модели Django, не меняя поведения.

Я сам использую только pyflakes, в первую очередь из-за некоторых глупых значений по умолчанию в pylint и моей лени (не желая искать, как изменить значения по умолчанию).

AdamKG
источник
Ах ... спасибо за подсказку. Я могу попробовать просто добавить это в Model.models в локальную копию источника django и посмотреть, поможет ли это.
rcreswick
Я думаю, что это отличное решение, потому что оно не снижает предупреждений.
Том Лейс,
1
Это плохое решение. Повторение себя и замена того, что возможно, изменится позже (таким образом, возникнет проблема контроля качества), просто чтобы исправить неполный инструмент контроля качества?
Крис Морган
2
Я бы не назвал это плохим решением: явное лучше, чем неявное. Возможно, в objectsлюбом случае не следует добавлять волшебным образом.
Уилл Харди
1
Я думаю, что это неправильный способ исправить Pylint - в некотором смысле исправляя Django. Все, что вам нужно сделать, это установить плагин Pylint, который понимает Django. См. Stackoverflow.com/a/31000713/78234
Тал Вайс
5

Попробуйте запустить pylint с

pylint --ignored-classes=Tags

Если это сработает, добавьте все остальные классы Django - возможно, используя скрипт, скажем, python: P

Документация для --ignore-classes:

--ignored-classes=<members names>
Список имен классов, атрибуты членов которых не следует проверять (полезно для классов с динамически установленными атрибутами). [текущий:% по умолчанию]

Я должен добавить, что это не особо элегантное решение, на мой взгляд, но оно должно работать.

свободное место
источник
Это работает, только если я никогда не делаю ошибок в этих классах;). Я хочу избегать игнорирования кода, если это вообще возможно - я считаю, что проводить анализ разных частей кодовой базы с разной степенью тщательности - очень плохая идея. Я забуду, что есть что, и сделаю ложные предположения при отладке
rcreswick
1
Это неправильный способ исправить Pylint - отключив некоторые его функции. Все, что вам нужно сделать, это установить плагин Pylint, который понимает Django. См. Stackoverflow.com/a/31000713/78234
Tal Weiss
3

Решение, предложенное в этом другом вопросе, - просто добавить get_attr в ваш класс Tag. Некрасиво, но работает.

Эрик
источник
1

Пока я не нашел реального решения для этого, но работаю:

  • В нашей компании нам требуется оценка pylint> 8. Это позволяет практикам кодирования, которые pylint не понимает, при этом гарантируя, что код не будет слишком «необычным». До сих пор мы не видели ни одного случая, когда E1101 не позволял нам набрать 8 или больше баллов.
  • Наши цели 'make check' отфильтровывают сообщения «for has no 'objects' member», чтобы убрать большую часть отвлекающих факторов, вызванных тем, что pylint не понимает Django.
Максимум
источник
1

Для neovim & vim8использования w0rp's aleплагина. Если вы установили все правильно в том числе w0rp's ale, pylintи pylint-django. В вашем vimrcдобавить следующую строку и весело провести время разработки веб - приложений с использованием Django. Спасибо.

let g:ale_python_pylint_options = '--load-plugins pylint_django'
Ганеш
источник
1
действительно работал идеально для меня, на купленных vim и neovim, спасибо.
Флавио Оливейра,