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

Мне бы очень хотелось интегрировать pylint в процесс сборки для моих проектов на python, но я столкнулся с одним ограничителем показа: один из типов ошибок, который я считаю чрезвычайно полезным: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 - не исходный код, который он загружал / вызывал.)

14 ответов

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

pip install pylint-django

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

--load-plugins pylint_django

Подробный пост в блоге здесь.

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

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

pip install pylint-django

И добавьте в конфиг VSC:

"python.linting.pylintArgs": [
    "--load-plugins=pylint_django"
],

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

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

последние два специально для Джанго.

Обратите внимание, что в 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).

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

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

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

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

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

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

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

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

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

pylint --ignored-classes=Tags

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

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

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

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

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

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

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

До сих пор я не нашел реального решения этого, но обойти:

  • В нашей компании мы требуем, чтобы показатель pylint> 8. Это позволяет использовать методы кодирования, которые Pylint не понимает, при этом гарантируя, что код не слишком "необычен". До сих пор мы не видели ни одного случая, когда E1101 мешал нам набрать 8 или выше.
  • Наши цели 'make check' отфильтровывают сообщения 'for has not member'objects', чтобы устранить большую часть отвлекающего эффекта, вызванного тем, что pylint не понимает Django.
  1. Перейти к настройкам в VSC, нажав Ctrl +,
  2. Нажмите Ctrl + Shift + p, введите Python: выберите Linter
  3. Выберите Mypy из выпадающего
  4. Установите Mypy, если будет предложено.

Для пользователей heroku вы также можете использовать ответ Тала Вайса на этот вопрос, используя следующий синтаксис для запуска pylint с плагином pylint-django (замените своим приложением/пакетом):

      # run on the entire timekeeping app/package
heroku local:run pylint --load-plugins pylint_django timekeeping

# run on the module timekeeping/report.py
heroku local:run pylint --load-plugins pylint_django timekeeping/report.py

# With temporary command line disables
heroku local:run pylint --disable=invalid-name,missing-function-docstring --load-plugins pylint_django timekeeping/report.py

Примечание. Мне не удалось запустить без указания каталогов проекта/пакета.

Если у вас есть проблемы сE5110: Django was not configured., вы также можете вызвать следующим образом, чтобы попытаться обойти это (опять же, изменитеtimekeepingк вашему приложению/пакету):

      heroku local:run python manage.py shell -c 'from pylint import lint; lint.Run(args=["--load-plugins", "pylint_django", "timekeeping"])'

# With temporary command line disables, specific module
heroku local:run python manage.py shell -c 'from pylint import lint; lint.Run(args=["--load-plugins", "pylint_django", "--disable=invalid-name,missing-function-docstring", "timekeeping/report.py"])'
Другие вопросы по тегам