Pyrefly Type Checker#
Pyrefly is a fast Python type checker (Meta's successor to Pyre) used in the Dify API backend. It runs in strict mode across the codebase and is integrated into both local development and CI workflows via uv. The tool is declared as a dev dependency at pyrefly>=1.2.0 . Supporting type stubs are also included in dev dependencies: types-pytz>=2026.3.1.20260727, types-bleach>=6.4.0.20260728, and types-croniter>=6.2.4.20260711.
The project uses a graduated adoption strategy: new and migrated code runs under strict mode immediately, while legacy files are tracked in managed exclusion lists until they are brought up to standard. Removing a file from an exclusion list is the explicit signal that it now passes strict checking.
Configuration Files#
There are three distinct pyrefly configurations in the api/ tree, each covering a different code surface:
1. api/pyproject.toml — main source config#
The primary configuration lives under [tool.pyrefly] . Key settings:
| Option | Value |
|---|---|
project-includes | . (entire api/) |
project-excludes | .venv, migrations/ |
python-platform | linux |
python-version | 3.12.0 |
infer-with-first-use | true |
min-severity | warn |
errors.missing-override-decorator | error |
errors.unnecessary-type-conversion | info |
Tests are excluded from this config; they get their own configs below.
2. api/tests/unit_tests/pyrefly.toml — unit test config#
Runs with preset = "strict" and a search-path of ["../.."] to resolve cross-package imports . Additional error escalations beyond the main config :
redundant-cast = trueunannotated-return = trueunnecessary-type-conversion = trueunused-ignore = trueimplicit-any-lambda = "info"missing-attribute = "warn"
A project-excludes list with ~900 entries tracks all unit test files not yet under strict mode . The inline comment reads: "Existing strict-mode debt. Remove a file when bringing it under strict checking."
3. api/tests/test_containers_integration_tests/pyrefly.toml — integration test config#
Identical global settings to the unit test config (preset = "strict", same Python version), with its own project-excludes list covering ~130 integration test files . Error escalations match the unit test config except for:
unnecessary-type-conversion = "info"(vstruein unit tests)
Local VDB/Provider Excludes#
api/pyrefly-local-excludes.txt lists ~55 files from the vector-database provider plugins (providers/vdb/*) that are not yet type-clean . These are loaded dynamically by the local check script (see below) using --project-excludes flags rather than being baked into any .toml.
Running Pyrefly#
The dev/pyrefly-check-local shell script is the canonical entry point for running all three checks in sequence :
- Main source check — runs
pyrefly checkagainstapi/with static--project-excludesfor.venv,migrations/, andtests/, then dynamically adds every line frompyrefly-local-excludes.txtas an additional exclude . - Unit test check — invokes pyrefly with
--config=tests/unit_tests/pyrefly.toml. - Integration test check — invokes pyrefly with
--config=tests/test_containers_integration_tests/pyrefly.toml.
All three checks run independently; status accumulates any nonzero exit codes and the script exits with it at the end .
Output formatting: the script pipes pyrefly output through api/libs/pyrefly_diagnostics.py , which strips noisy code-excerpt lines and keeps only ERROR/WARN/WARNING headline lines — producing a clean diff-friendly output for CI. Setting PYREFLY_OUTPUT_FORMAT=github switches pyrefly itself to GitHub Actions annotation format .
How to Migrate a File to Strict Mode#
- Fix all type errors in the target file until
pyrefly checkreports zero issues. - Remove its entry from the relevant
project-excludeslist:- Unit test files →
api/tests/unit_tests/pyrefly.tomlproject-excludes - Integration test files →
api/tests/test_containers_integration_tests/pyrefly.tomlproject-excludes - VDB provider files →
api/pyrefly-local-excludes.txt
- Unit test files →
- Run
dev/pyrefly-check-localto confirm the full suite is still green.
The services/test_app_dsl_service.py migration is a documented example: it was removed from the unit test exclusion list after being migrated to real SQLite sessions.