dc это высокопроизводительная утилита на Rust для статического анализа
проектов на Python и Django. Главная цель инструмента это точное обнаружение
неиспользуемого кода с минимумом ложных срабатываний: анализатор учитывает
специфику фреймворка Django и динамическую природу Python.
Если rust и cargo не установлены:
curl https://sh.rustup.rs -sSf | shУстановка самого инструмента:
cargo install --git https://github.com/ak4code/deadcodedc # запуск в корне анализируемого проекта
dc --target-path /path/to/project --verbose
dc --format json > report.json
dc --kind function,method # только функции и методыПараметры командной строки:
| Параметр | По умолчанию | Назначение |
|---|---|---|
-t, --target-path |
. |
Корневая директория проекта |
-c, --config-path |
автопоиск | Путь к файлу конфигурации |
-f, --format |
text |
Формат отчета: text или json |
-k, --kind |
все виды | Фильтр находок: function, class, method, variable; повторение или перечисление через запятую |
-v, --verbose |
выкл. | Вывод статистики анализа |
Коды завершения (для интеграции с CI):
| Код | Значение |
|---|---|
0 |
Мертвый код не найден |
1 |
Найден мертвый код |
2 |
Ошибка конфигурации или запуска |
Предупреждения о пропущенных файлах (ошибки чтения или парсинга) выводятся в поток ошибок и не прерывают анализ.
Источники конфигурации в порядке приоритета: явный --config-path,
файл .dc.toml в корне проекта, секция [tool.dc] в pyproject.toml.
Незнакомые ключи считаются ошибкой — опечатка не отключит настройку молча.
По умолчанию из анализа полностью исключаются .venv (включая окружения
uv), migrations и скрытые директории; правила .gitignore учитываются
автоматически. Тестовые файлы (пакет tests, а также test_*.py,
*_test.py, tests.py, conftest.py) не исключаются, а
анализируются только как источник ссылок: код, используемый исключительно
в тестах, не считается мертвым, но сами тесты в отчет не попадают. Чтобы
исключить тесты полностью, добавьте tests в exclude_directories.
# .dc.toml (или те же ключи в [tool.dc] файла pyproject.toml)
# Директории, исключаемые из анализа.
exclude_directories = [".venv", "migrations", "tests", "node_modules"]
# Дополнительные декораторы точек входа: полное имя или последний сегмент.
extra_entry_point_decorators = ["broker.subscribe", "periodic_task"]
# Имена, всегда считающиеся используемыми (подавление ложных срабатываний).
extra_dynamic_names = ["called_from_template"]
# Дополнительные маркеры базовых классов под управлением фреймворка:
# методы наследников таких баз не считаются мертвым кодом.
extra_framework_base_markers = ["Repository", "Actor"]- Сбор файлов — обход дерева каталогов (
ignore) с фильтрацией.py. - Парсинг — параллельная обработка файлов (
rayon+tree-sitter); парсер создается один раз на рабочий поток. - Извлечение сущностей — функции, классы, методы, переменные модулей.
- Построение графа — ориентированный граф зависимостей (
petgraph) по ссылкам на имена. - Достижимость — обход графа от точек входа; недостижимые узлы попадают в отчет как мертвый код.
- Строковые ссылки — строки из
getattr,setattr,hasattr,delattrиimportlib.import_moduleобразуют пул динамических ссылок; совпадающие по имени сущности считаются используемыми. - Точечные строковые пути — любая строка вида
app.views.handler(не менее двух сегментов, каждый — корректный идентификатор Python) считается ссылкой на код и добавляется в пул динамических ссылок. Это покрывает повсеместные для Django строковые ссылки:handler404, значения настроек DRF (EXCEPTION_HANDLER,DEFAULT_SCHEMA_CLASS), строковые константы динамических импортов. Версии (1.2.3), пути файлов и человекочитаемый текст ссылками не считаются. - Тесты как источник ссылок — тестовые файлы анализируются ради ссылок на код проекта, поэтому функции, вызываемые только из тестов, не считаются мертвыми; сущности самих тестов в отчет не попадают.
- Маршрутизация — представления из вызовов
path,re_path,url(включая строковые ссылкиmyapp.views.my_view) помечаются точками входа. - Админка — строковые значения
list_display,list_filter,actions,readonly_fieldsклассовadmin.ModelAdminдобавляются в пул ссылок; классы под@admin.registerсчитаются точками входа. - Сигналы и задачи — декораторы
receiver,shared_task,taskпомечают функции точками входа;signal.connectсоздает связь в графе. - Management команды и теги — классы
Commandвmanagement/commandsи функции сregister.simple_tag/register.filterэто точки входа. - Pytest —
pytest.fixtureпомечает фикстуры точками входа, строки изpytest.mark.usefixturesдобавляются в пул динамических ссылок. - Соглашения Django —
urlpatterns, модулиsettings, классыMetaиAppConfig, неявно вызываемые методы (handle,save,validateи другие) и dunder-методы не считаются мертвым кодом. - Хуки фреймворков — методы с префиксами
validate_,clean_,get_,perform_,has_,test_вызываются Django, DRF и Pytest по соглашению и не считаются мертвым кодом. - Свойства — методы под
@property,@cached_propertyи аксессорами@имя.setter/@имя.getter/@имя.deleterчитаются как атрибуты (в том числе из шаблонов Django) и не считаются мертвым кодом. - Классы под управлением фреймворка — методы классов, унаследованных
от баз
Serializer,ViewSet,View,Permission,Form,Admin,Middleware,TestCase,BaseModel(pydantic),Document(elasticsearch-dsl) и подобных, вызываются фреймворком по контракту; признак распространяется по иерархии наследования внутри проекта, поэтому переопределения методов в наследниках не считаются мертвым кодом. Список маркеров расширяется черезextra_framework_base_markers. Функцииtest_*это точки входа Pytest. - Вложенные классы соглашений —
Meta,Media(Django),Config(pydantic),Index,Django(django-elasticsearch-dsl) читаются фреймворками и не считаются мертвым кодом; методыprepare_*документов вызываются при индексации, классы под@registry.register_documentэто точки входа.
Кодовая база разделена на четыре слоя с минимальной публичной поверхностью:
src/
├── main.rs # CLI-оболочка: аргументы, коды завершения
├── lib.rs # публичный API библиотеки
├── model.rs # доменные типы: сущности, ссылки, отчеты
├── config.rs # загрузка и валидация конфигурации
├── error.rs # типы ошибок
├── heuristics.rs # эвристики Python / Django / Pytest
├── render.rs # текстовый и JSON отчеты
└── pipeline/ # конвейер анализа (приватный модуль)
├── mod.rs # оркестрация run_analysis
├── collect.rs # этап 1: сбор файлов
├── extract.rs # этапы 2–3: парсинг и извлечение
└── reachability.rs # этапы 4–5: граф и достижимость
Принципы:
- ошибки конфигурации фатальны и явно сообщаются; ошибки отдельных файлов накапливаются и не прерывают анализ;
- результат детерминирован: файлы и находки отсортированы;
- в коде запрещен
unsafe, публичный API полностью документирован (missing_docsвключен как warning уровня crate).
cargo test # модульные и интеграционные тесты
cargo clippy --all-targets -- -D warnings # статический анализ
cargo fmt --all --check # проверка форматированияИнтеграционные тесты используют демонстрационный Django проект
в tests/fixtures/demo_project и проверяют CLI через собранный
бинарный файл, включая коды завершения и JSON-вывод.