Как pylint использует easy_install во время выполнения?

Извините, это длинный вопрос. См. предложение, выделенное жирным шрифтом внизу, для версии TL;DR.

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

Я использую pylint 1.7.2 на Ubuntu 16.04. (Версия, доступная из apt, была 1.5.2, но установка через pip дает 1.7.2.)

Обычно мы запускаем pylint из tox с tox.ini, который выглядит примерно так (это урезанная версия):

[tox]
envlist = py35
[testenv]
setenv =
    MODULE_NAME=our_module
ignore_errors = True
deps =
    -r../requirements.txt
whitelist_externals = bash
commands =
    pip install --editable=file:///{toxinidir}/../our_other_module
    pip install -e .
    bash -c \'set -o pipefail; pylint --rcfile=../linting/pylint.cfg our_module | tee pylint.log\'

Помимо прочего, файл ../requirements.txt содержит строку для pylint==1.7.2.

Поведение такое:

  • [неправильно] Когда присутствует строка, которая импортирует our_other_module, кажется, что pylint завершается успешно и не сообщает о каких-либо предупреждениях, даже если в коде our_module есть ошибки, которые он должен обнаружить.

  • [правильно] Когда эта строка закомментирована, pylint генерирует ожидаемые предупреждения.

В рамках отслеживания этого я взял две копии папки .tox с импортом модуля и без него, назвав их .tox-no-errors-reported и .tox-with-errors-reported соответственно.

Так что теперь, даже без поиска их соответствующих tox virtualenv, я могу сделать следующее:

  • $ .tox-no-errors-reported/py35/bin/pylint --rcfile=../linting/pylint.cfg our_module -- сообщает об отсутствии предупреждений о линтинге

  • $ .tox-with-errors-reported/py35/bin/pylint --rcfile=../linting/pylint.cfg our_module -- сообщает об ожидаемых предупреждениях о линтинге

(где я просто изменил строку #! сценария pylint в каждом случае, чтобы ссылаться на python3.5 внутри этого конкретного каталога .tox вместо безымянного .tox)

Сравнив .tox-no-errors-reported и .tox-with-errors-reported, я обнаружил, что они очень похожи. Но я могу заставить версию "без ошибок" начать сообщать об ошибках, удалив путь к our_other_module из .tox-no-errors-reported/py35/lib/python3.5/site-packages/easy-install.pth.

Итак, мой вопрос: почему pylint использует easy_install во время выполнения и что он получает от другого нашего компонента, что заставляет его не сообщать о некоторых ошибках.

Насколько я понимаю, у pylint есть зависимости от astroid и logilab-common, но включение их в requirements.txt не имеет никакого значения.


person Matthew Strawbridge    schedule 08.09.2017    source источник


Ответы (1)


Одной из возможных причин неожиданного поведения pylint является опция --editable.

он создает специальный файл .egg-link в каталоге развертывания, который ссылается на исходный код вашего проекта. И, ..., он также обновит файл easy-install.pth, чтобы включить исходный код вашего проекта.

Затем файл pth влияет на файл sys.path, который влияет на логика импорта модуля из astroid и глубоко скрыта в стеке вызовов pylint.expand_files через pylint.utils.expand_modules. Также pylint идентифицирует части модуля и имена функций в AST, используя astroid.modutils.get_module_part.

Чтобы проверить теорию, вы можете попробовать вызвать некоторые из затронутых функций астроида вручную:

import sys, astroid
print(sys.path)
print(astroid.modutils.get_module_part('your_package.sub_package.module'))
astroid.modutils.file_from_modpath(['your_package', 'sub_package', 'module'])
person gdlmx    schedule 08.09.2017