Использование 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, а не в источнике, который он загружал/вызывал.)

Ответ 1

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

pip install pylint-django

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

--load-plugins pylint_django

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

Ответ 2

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

Ответ 3

My ~/.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).

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

Ответ 5

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

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

Ответ 6

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

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

Ответ 7

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

Ответ 8

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

pylint --ignored-classes=Tags

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

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

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

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

Ответ 9

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

  • В нашей компании нам нужна пилинга оценкa > 8. Это позволяет кодировать практики pylint не понимает гарантируя, что код не слишком "необычный". До сих пор мы не видели любой случай, когда E1101 держал нас от достижения 8 баллов или выше.
  • Наши цели "проверить" отфильтровать "для не имеет" объектов "члена", чтобы удалить большую часть отвлечение, вызванное pylint not понимая Django.

Ответ 10

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

Ответ 11

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

pip install pylint-django

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

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