pyproject.toml и ruff.toml
Файлы конфигурации — где живут настройки Ruff.
Обзор конфигурации Ruff
Ruff поддерживает три формата конфигурационных файлов: pyproject.toml, ruff.toml и .ruff.toml. Все они используют TOML-синтаксис и позволяют централизованно управлять настройками линтинга и форматирования.
Конфигурация Ruff включает в себя несколько логических секций:
- Общие настройки —
line-length,exclude,include,src - Линтинг —
[tool.ruff.lint]:select,ignore,extend-select - Форматирование —
[tool.ruff.format]:quote-style,indent-style - Per-file ignores —
[tool.ruff.lint.per-file-ignores] - Наследование —
extendдля заимствования настроек из другого файла
Все настройки можно переопределить через CLI-флаги, но конфигурационный файл — наиболее удобный и воспроизводимый способ.
pyproject.toml — стандартный подход
Если в проекте уже есть pyproject.toml (стандартный конфигурационный файл для современных Python-проектов), настройки Ruff добавляются в него через секцию [tool.ruff]. Это наиболее рекомендуемый подход, так как он консолидирует всю конфигурацию проекта в одном файле.
[build-system]
requires = ["setuptools>=61.0"]
build-backend = "setuptools.build_meta"
[project]
name = "myproject"
version = "0.1.0"
requires-python = ">=3.9"
# --- Настройки Ruff ---
[tool.ruff]
line-length = 88
target-version = "py311"
exclude = ["migrations/", "build/", "*.generated.py"]
include = ["*.py", "*.pyi"]
[tool.ruff.lint]
select = ["E", "F", "I", "N", "UP", "B"]
ignore = ["E501", "D100"]
extend-select = ["SIM"]
[tool.ruff.lint.per-file-ignores]
"__init__.py" = ["F401", "F403"]
"tests/**/*.py" = ["E501", "S101", "D"]
[tool.ruff.format]
quote-style = "double"
indent-style = "space"
magic-trailing-comma = true
Преимущества использования pyproject.toml:
- Единый файл конфигурации для всего проекта
- Поддерживается всеми современными Python-инструментами
- Легко обнаруживается (стандартный путь поиска)
- Меньше файлов в корне проекта
ruff.toml — отдельный файл
Если вы предпочитаете не смешивать конфигурацию разных инструментов, используйте отдельный ruff.toml (или скрытую версию .ruff.toml). Синтаксис такой же, но без префикса [tool.ruff] — настройки идут напрямую:
line-length = 88
target-version = "py311"
exclude = ["migrations/", "build/"]
include = ["*.py", "*.pyi"]
[lint]
select = ["E", "F", "I", "N", "UP", "B"]
ignore = ["E501"]
extend-select = ["SIM"]
[lint.per-file-ignores]
"__init__.py" = ["F401"]
"tests/**/*.py" = ["E501"]
[format]
quote-style = "double"
indent-style = "space"
magic-trailing-comma = true
Преимущества отдельного ruff.toml:
- Не загрязняет pyproject.toml
- Легко найти и редактировать
- Может быть расположен в поддиректории (если нужно)
- Меньше вложенности в TOML (.tool.ruff.lint vs [lint])
Структура секций в pyproject.toml
| Секция в pyproject.toml | Секция в ruff.toml | Описание |
|---|---|---|
[tool.ruff] |
(root) | Общие настройки: line-length, exclude, include, src |
[tool.ruff.lint] |
[lint] |
Настройки линтинга: select, ignore, extend-select |
[tool.ruff.lint.per-file-ignores] |
[lint.per-file-ignores] |
Игнорирование правил для конкретных файлов/папок |
[tool.ruff.format] |
[format] |
Настройки форматтера: quote-style, indent-style |
[tool.ruff.lint.extend-safe-fixes] |
[lint.extend-safe-fixes] |
Расширение списка safe-fixes (продвинутая настройка) |
Полная конфигурация по умолчанию
Вот как выглядит полная конфигурация Ruff со всеми значениями по умолчанию. Это полезно как справочник и отправная точка для настройки:
# ruff.toml — полный default
line-length = 88
indent-width = 4
target-version = "py38" # минимальная версия Python проекта
preview = false
required-version = "0.6.0" # минимальная версия Ruff
# Какие файлы включать/исключать
include = ["*.py", "*.pyi", "*.ipynb"] # с preview
exclude = [
".bzr", ".direnv", ".eggs", ".git", ".git-rewrite",
".hg", ".ipynb_checkpoints", ".mypy_cache", ".nox",
".pants.d", ".pyenv", ".pytest_cache", ".ruff_cache",
".svn", ".tox", ".venv", ".vscode", "__pypackages__",
"_build", "buck-out", "build", "dist", "node_modules",
"site-packages", "venv"
]
src = ["."] # корневые директории для разрешения импортов
# Настройки линтинга
[lint]
select = ["E", "F", "I"] # по умолчанию
ignore = []
extend-select = []
fixable = ["ALL"]
unfixable = []
[lint.per-file-ignores]
[lint.extend-safe-fixes]
[lint.extend-unsafe-fixes]
# Настройки форматтера
[format]
indent-style = "space"
quote-style = "double"
magic-trailing-comma = true
docstring-code-format = false
docstring-code-line-length = "dynamic"
line-ending = "auto"
Поиск конфигурационного файла (дисковери)
Ruff использует иерархический поиск конфигурационного файла. Процесс выглядит так:
- Начинает с директории проверяемого файла
- Ищет
ruff.toml, затем.ruff.toml, затемpyproject.toml - Если не нашёл — поднимается на уровень выше (в родительскую директорию)
- Повторяет до корня файловой системы
- Если ничего не нашёл — использует значения по умолчанию
Если Ruff находит конфигурационный файл, он прекращает поиск и использует найденный. Первый найденный файл побеждает (не объединяет с найденными выше).
Пример иерархического поиска:
# Структура проекта:
/project/
pyproject.toml # <- конфиг для всего проекта
src/
main.py # Ruff ищет: .ruff.toml -> ruff.toml -> pyproject.toml
subpackage/
ruff.toml # <- переопределяет настройки для подпакета
module.py # Ruff ищет: ruff.toml (находит сразу)
tests/
.ruff.toml # <- отдельные настройки для тестов
test_main.py # Ruff ищет: .ruff.toml (находит сразу)
test_subpackage/
test_module.py # наследует .ruff.toml из tests/
ruff check --show-settings . — в начале вывода будет путь к найденному конфигурационному файлу.
Приоритет конфигурации
Ruff ищет конфигурационный файл в следующем порядке (первый найденный побеждает):
ruff.toml(наивысший приоритет).ruff.tomlpyproject.toml(секция[tool.ruff])
А вот полная иерархия приоритетов всех настроек (от наивысшего к низшему):
| Приоритет | Источник | Пример |
|---|---|---|
| 1 (наивысший) | CLI аргументы | ruff check --select ALL --ignore E501 |
| 2 | Локальный ruff.toml (рядом с файлом) | src/subpackage/ruff.toml |
| 3 | Локальный .ruff.toml | src/subpackage/.ruff.toml |
| 4 | Локальный pyproject.toml | src/subpackage/pyproject.toml |
| 5 | Родительский ruff.toml | project/ruff.toml |
| 6 | Родительский .ruff.toml | project/.ruff.toml |
| 7 | Родительский pyproject.toml | project/pyproject.toml |
| 8 (низший) | Default значения | line-length=88, select=E,F,I и т.д. |
Важно: Если в одной директории найдены и ruff.toml, и pyproject.toml — ruff.toml имеет приоритет. pyproject.toml будет проигнорирован (даже если в нём есть настройки Ruff).
extend — наследование конфигурации
Ключ extend позволяет наследовать настройки из другого конфигурационного файла. Это полезно, когда у вас есть базовая конфигурация для всего проекта и специализированные для подпроектов или окружений.
# ruff.toml (корень проекта) — базовый конфиг
line-length = 88
target-version = "py311"
[lint]
select = ["E", "F", "I", "N", "UP", "B"]
ignore = ["E501"]
[format]
quote-style = "double"
# src/api/ruff.toml — переопределяет некоторые настройки
extend = "../../ruff.toml" # наследуем базовый конфиг
[lint]
# добавляем правила для API
select = ["E", "F", "I", "N", "UP", "B", "S"] # S — безопасность
ignore = ["E501", "D"]
# tests/ruff.toml — другие настройки для тестов
extend = "../ruff.toml"
[lint]
select = ["E", "F", "I", "N"]
ignore = ["E501", "D", "S101"] # S101 — assert used (отключаем для тестов)
Правила наследования через extend:
- Наследуются все настройки из указанного файла
- Настройки в текущем файле переопределяют унаследованные
- Путь к файлу может быть относительным или абсолютным
extendне поддерживает цепочки длиннее одного уровня (нельзя A -> B -> C)
extend — отличный способ организовать конфигурацию для монорепозиториев, где разные пакеты требуют разных правил линтинга.
--config — указание конфига через CLI
Флаг --config позволяет указать путь к конфигурационному файлу явно. Это полезно в CI/CD, pre-commit хуках или при использовании временной конфигурации.
# использовать конкретный конфиг
ruff check --config /path/to/ruff.toml .
ruff format --config /path/to/ruff.toml .
# использовать pyproject.toml из другой директории
ruff check --config ../shared/pyproject.toml .
# можно использовать для разных окружений
ruff check --config ruff.prod.toml --select ALL .
ruff check --config ruff.dev.toml --select E,F,I .
# --config переопределяет поиск конфига (используется только указанный файл)
# полезно в CI:
ruff check --config .github/linters/ruff.toml .
Когда вы используете --config, Ruff не выполняет автоматический поиск. Используется только указанный файл. Если в нём нет каких-то настроек — применяются значения по умолчанию.
# Использование --config в GitHub Actions:
- name: Lint with custom config
run: |
ruff check --config .github/ruff-ci.toml --output-format github .
# Использование в pre-commit:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.6.0
hooks:
- id: ruff
args: [--config, pyproject.lint.toml]
--config позволяет держать разные конфиги для каждой ветки без merge conflicts.
Установка Ruff
Ruff можно установить разными способами, в зависимости от вашей платформы и предпочтений:
| Метод | Команда | Примечание |
|---|---|---|
| pip | pip install ruff |
Стандартный способ, pre-built wheels |
| pipx | pipx install ruff |
Изолированная установка |
| conda | conda install ruff -c conda-forge |
Anaconda/Miniconda |
| Homebrew (macOS) | brew install ruff |
macOS |
| Cargo | cargo install ruff |
Из исходников (требуется Rust) |
| GitHub Releases | Скачать бинарник с GitHub | Для CI: curl -LsSf ... | sh |
# установка через pip
pip install ruff
# проверка установки
ruff --version
# установка конкретной версии
pip install ruff==0.6.0
# для разработки (из репозитория)
git clone https://github.com/astral-sh/ruff
cd ruff
cargo build --release
# установка через Astral's install script (для CI)
curl -LsSf https://astral.sh/ruff/install.sh | sh
# GitHub Actions — готовый action
- uses: astral-sh/ruff-action@v2
astral-sh/ruff-action.
Проверка конфигурации
После настройки конфигурации полезно проверить, что Ruff её правильно читает:
# показать активные настройки
ruff check --show-settings .
# показать какие файлы будут проверяться
ruff check --show-files .
# проверить, что конфиг валидный (любая команда с --help)
ruff check --help | grep -A 5 "Config"
# проверить версию Ruff
ruff --version
Если Ruff не находит конфиг или использует не те настройки, проверьте:
- Правильно ли указан путь к конфигу (--config)
- Не переопределяется ли конфиг вложенным ruff.toml
- Правильно ли написаны секции (tool.ruff vs tool.ruff.lint)
- Нет ли синтаксических ошибок в TOML (можно проверить через
python -m toml)
Best Practices
- Используйте pyproject.toml для новых проектов — это современный стандарт
- Зафиксируйте версию Ruff в зависимостях:
ruff = ">=0.6.0,<0.7.0" - Не храните конфиги в нескольких местах — выберите один файл для всего проекта
- Используйте extend для монорепозиториев — базовая конфигурация в корне, переопределения в подпакетах
- Проверяйте конфиг через --show-settings после изменений
- Документируйте неочевидные решения — если отключаете правило, оставьте комментарий почему
- Начинайте с минимального набора — добавляйте правила постепенно
# Пример хорошо документированного конфига:
[tool.ruff]
line-length = 100 # разрешаем 100 из-за длинных имён в Django
[tool.ruff.lint]
select = [
"E", "F", "I", # обязательные: стиль, ошибки, сортировка
"N", # именование
"UP", # современный синтаксис
"B", # баги
"S", # безопасность
]
ignore = [
"E501", # отключаем длину строк — используем ruff format
"D", # документация — пока не готовы
]
[tool.ruff.lint.per-file-ignores]
"__init__.py" = ["F401"] # в __init__ часто реэкспорты
"migrations/**" = ["ALL"] # миграции генерируются, не проверяем
Резюме
| Аспект | Детали |
|---|---|
| Форматы конфигов | pyproject.toml, ruff.toml, .ruff.toml |
| Поиск конфига | Иерархический: от директории файла до корня |
| Приоритет | CLI > локальный ruff.toml > родительский pyproject.toml > default |
| --config | Явное указание конфига, отключает поиск |
| extend | Наследование из другого конфига (1 уровень) |
Валидация конфигурации
Ruff автоматически проверяет конфигурационный файл на корректность при запуске. Если в TOML есть синтаксическая ошибка или неизвестная опция, Ruff сообщит об ошибке и завершится с ненулевым кодом возврата.
Примеры ошибок в конфиге:
# Ошибка: неизвестная опция
[tool.ruff]
line-lenght = 88 # опечатка: должно быть line-length
# Ошибка: неверное значение
[tool.ruff.lint]
select = ["E", "F", "ZZZZ"] # ZZZZ — неизвестное правило
# Ошибка: неверный тип
[tool.ruff]
line-length = "long" # должно быть число
# Ошибка: неверная секция
[tool.ruff.lint]
select = ["E", "F"]
severity = ["E:error", "W:warning"] # неверная опция
Ruff выдаст понятное сообщение об ошибке с указанием строки и проблемы в конфигурационном файле.
Конфигурация для разных окружений
Вы можете иметь разные конфигурации для разработки, CI и продакшена:
# ruff.dev.toml — для локальной разработки (максимум правил)
line-length = 88
[lint]
select = ["ALL"] # все правила
ignore = ["E501", "D"]
[format]
quote-style = "double"
# ruff.ci.toml — для CI (строгие проверки)
line-length = 88
[lint]
select = ["E", "F", "I", "N", "UP", "B", "S"]
ignore = ["E501"]
fixable = [] # в CI не применяем исправления
[format]
quote-style = "double"
# Запуск:
ruff check --config ruff.dev.toml . # локально
ruff check --config ruff.ci.toml . # в CI
Этот подход позволяет иметь разные стандарты для разных окружений без дублирования кода.
Конфигурация для монорепозитория
Монорепозитории часто содержат несколько Python-пакетов с разными требованиями к стилю. Вот как организовать конфигурацию:
# Структура:
# monorepo/
# ruff.toml # базовый конфиг
# packages/
# core/
# ruff.toml # extends ../ruff.toml + свои правила
# src/
# api/
# ruff.toml # extends ../ruff.toml + безопасность
# src/
# scripts/
# ruff.toml # extends ../ruff.toml + более строгие
# monorepo/ruff.toml (базовый):
line-length = 100
[lint]
select = ["E", "F", "I", "N"]
ignore = ["E501"]
[format]
quote-style = "double"
# packages/api/ruff.toml:
extend = "../../ruff.toml"
[lint]
select = ["E", "F", "I", "N", "S", "B"] # добавляем безопасность
ignore = ["E501"]
# packages/scripts/ruff.toml:
extend = "../../ruff.toml"
[lint]
select = ["E", "F"] # минимум для скриптов
ignore = ["E501", "N"]
fixable = ["ALL"]
Теперь при запуске ruff check packages/api/src/ Ruff найдёт packages/api/ruff.toml и использует его с наследованием от корневого конфига.
Советы и хитрости
- required-version — добавьте
required-version = "0.6.0"в конфиг, чтобы предотвратить запуск с неподходящей версией Ruff. Если версия не совпадает, Ruff завершится с ошибкой. - src настройка — если ваш проект использует
src/layout, укажитеsrc = ["src"]. Это поможет Ruff правильно разрешать импорты. - target-version — укажите минимальную версию Python:
target-version = "py311". Ruff будет предлагать только те фичи, которые доступны в этой версии. - exclude кэша — Ruff по умолчанию исключает
.ruff_cache. При использованииruff cleanкэш очищается. - Проверка синтаксиса TOML — используйте
python -m tomlдля проверки синтаксиса конфига.
# pyproject.toml с продвинутыми настройками
[tool.ruff]
line-length = 88
target-version = "py311"
required-version = "0.6.0"
src = ["src"] # src-layout
[tool.ruff.lint]
select = ["E", "F", "I", "N"]
ignore = ["E501"]
[tool.ruff.lint.per-file-ignores]
"__init__.py" = ["F401"]
Устранение проблем
Проблема: Ruff игнорирует мой конфиг
Решение: Проверьте, что файл находится в ожидаемой директории. Используйте ruff check --show-settings . чтобы увидеть, какой конфиг был найден. Проверьте --show-files чтобы убедиться, что файлы включены в проверку.
Проблема: Ruff вылетает с ошибкой парсинга TOML
Решение: Проверьте синтаксис TOML. Обратите внимание на кавычки: строки должны быть в двойных или одинарных кавычках. Массивы — в квадратных скобках. Ключи и значения разделяются знаком =.
Проблема: Ruff не использует правила из моего конфига
Решение: Убедитесь, что select или extend-select указан, а не только ignore. Если указан только ignore, Ruff использует значения по умолчанию для select (E, F, I) и применяет к ним ignore.
Проблема: Ruff не видит файлы .pyi или .ipynb
Решение: Настройте include в конфиге: include = ["*.py", "*.pyi", "*.ipynb"]. По умолчанию Ruff включает только *.py.
Шпаргалка
| Команда | Описание |
|---|---|
ruff check --show-settings . |
Показать активные настройки |
ruff check --show-files . |
Показать проверяемые файлы |
ruff --version |
Версия Ruff |
ruff clean |
Очистить кэш Ruff |
ruff check --config PATH . |
Использовать указанный конфиг |
Обработка ошибок в конфигурации
Ruff сообщает об ошибках в конфигурации понятными сообщениями. Вот типичные ошибки и их решения:
| Ошибка | Причина | Решение |
|---|---|---|
| TOML parse error | Синтаксическая ошибка в TOML | Проверьте кавычки, скобки, запятые |
| Unknown field | Неизвестная опция | Проверьте название опции, возможно опечатка |
| Expected version | Неверная версия в required-version | Обновите версию Ruff |
| Config file not found | Файл из --config не существует | Проверьте путь к файлу |
| Extend cycle detected | Циклическое наследование через extend | Убедитесь, что extend не ведёт к самому себе |
# Пример ошибки:
# Error: Failed to parse "/project/pyproject.toml"
# Caused by:
# TOML parse error at line 3, column 1
# unexpected character
# expected newline, `#`
# Решение: проверьте строку 3 в файле конфигурации
Использование в CI/CD с разными конфигами
В CI/CD можно использовать разные конфиги для разных этапов pipeline:
# Этап 1: Линтинг
ruff check --select E,F,I,N,UP,B .
# Этап 2: Проверка форматирования
ruff format --check .
# Этап 3: Проверка безопасности (с другим конфигом)
ruff check --config ruff.security.toml .
# Этап 4: Проверка документации
ruff check --select D --config ruff.docs.toml .
# GitHub Actions:
name: CI
on: [push, pull_request]
jobs:
quality:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: astral-sh/ruff-action@v2
with:
args: check --select E,F,I,N,UP,B
- uses: astral-sh/ruff-action@v2
with:
args: format --check .
Makefile для локальной разработки:
# Makefile
.PHONY: lint format check
lint:
ruff check --select E,F,I,N,UP,B .
format:
ruff format .
check: lint format-check
format-check:
ruff format --check .
fix:
ruff check --fix .
ruff format .
clean:
ruff clean
Пример полного проекта с конфигурацией
# pyproject.toml — полный файл проекта
[build-system]
requires = ["setuptools>=61.0"]
build-backend = "setuptools.build_meta"
[project]
name = "awesome-project"
version = "1.0.0"
requires-python = ">=3.10"
dependencies = [
"ruff>=0.6.0,<0.7.0",
]
[tool.ruff]
line-length = 88
target-version = "py310"
src = ["src"]
[tool.ruff.lint]
select = [
"E", # pycodestyle errors
"F", # pyflakes
"I", # isort
"N", # pep8-naming
"UP", # pyupgrade
"B", # bugbear
"S", # bandit (security)
"SIM", # flake8-simplify
]
ignore = [
"E501", # line too long — форматтер сам справится
"D100", # missing docstring — пока не готовы
]
[tool.ruff.lint.per-file-ignores]
"__init__.py" = ["F401", "F403"]
"tests/**/*.py" = ["S101", "D", "E501"]
[tool.ruff.format]
quote-style = "double"
indent-style = "space"
magic-trailing-comma = true
docstring-code-format = true
docstring-code-line-length = 72
Урок 4.1: Конфигурационный файл
5 вопросов