Некорректно работает exclude при вызове mypy

Есть тестовая структура проекта:

├── app
|   └── db
|       └── postgres.py
|   └── postgres.py
└── postgres.py

Если не устанавливать конфигурацию, то вызов poetry run mypy . | grep postgres дает следующее:

postgres.py:2: error: Unsupported operand types for + ("str" and 
"float")  [operator]

app/postgres.py:2: error: Unsupported operand types for + ("str" 
and "float")  [operator]

app/db/postgres.py:11: error: "Constraint" has no attribute 
"columns"  [attr-defined]

Однако моя цель исключить директорию db или хотя бы файл app/db/postgres.py, поэтому в pyproject.toml добавляю:

[tool.mypy]    
exclude = ["postgres.py", "db", "app/db", "db/postgres.py", "app/db/postgres.py"]

И вызываю poetry run mypy . | grep postgres. Вывод:

app/db/postgres.py:11: error: "Constraint" has no attribute "columns"  [attr-defined]

Почему-то на втором уровне вложенности mypy никак не хочет респектить exclude. Кажется, проблема даже не в этом параметре. Кто-нибудь может помочь?


Ответы (2 шт):

Автор решения: Amgarak

Параметр exclude — это строка с регулярным выражением:

#pyproject.toml
[tool.mypy]
exclude = "^app/db/.*$"

В .toml можно использовать список, но важно учесть, что это должен быть список регулярных выражений.

Пример из документации:

[tool.mypy]
exclude = [
    "^one\\.py$",  # TOML's double-quoted strings require escaping backslashes
    'two\.pyi$',  # but TOML's single-quoted strings do not
    '^three\.',
]

Эквивалентен выражению в одну строчку:

^one\.py$|two\.pyi$|^three\.

#mypy.ini 
[mypy]
exclude = ^app/db/.*$

Такая регулярка исключает:

  • app/db/all_file.py
  • Все подкаталоги внутри app/db

Если использовать просто имена файлов или директорий, это может рано или поздно выйти боком.

→ Ссылка
Автор решения: Silent Mind

Благодарю за ответы. Проблема оказалась в следующем: https://mypy.readthedocs.io/en/stable/running_mypy.html#following-imports

Mypy по умолчанию проверяет все встреченные в импортах модули, даже если они подходят под заданный exclude. Данное поведение можно изменить, но это не является рекомендуемой практикой.

Таким образом, при вызове mypy из корня проекта, исключить app/db можно следующими способами:

  1. Задать в exclude регулярку и вызывать mypy без проверки встреченных импортов (не рекомендутеся) poetry run mypy . --follow-imports silent

  2. Отключить проверку импортируемого модуля в overrides

    [[tool.mypy.overrides]]
    module = "app.db.*"
    ignore_errors = true
  1. Явно указывать проверяемые модули, с учетом того, что mypy будет проверять импорты рекурсивно.
→ Ссылка