Installation
Since v0.2.0, cfgdrift is installable and runnable on any Python 3.8+.
The C extension is an optional accelerator — when it is not compiled or the build fails, the package
automatically falls back to the pure-Python parsers.
pip install cfgdrift # general install (pip auto-selects the wheel)
pip install "cfgdrift[web]" # includes the Web dashboard
pip install "cfgdrift[dev]" # includes test dependencies
Dual-wheel release model
| Artifact | Target users | Description |
|---|---|---|
cfgdrift-<ver>-py3-none-any.whl | all Python 3.8+ | pure-Python universal wheel (default primary release) |
cfgdrift-<ver>-cp313-*-*.whl | CPython 3.13 | optional C-accelerated platform wheel (faster JSON/TOML/INI parsing) |
cfgdrift-<ver>.tar.gz (sdist) | needs local compilation | ships C sources; pip install tries to compile and auto-falls back on failure |
pip's tag priority naturally delivers the accelerated wheel to CPython 3.13 users and the universal one to everyone else.
Local build recipes
# pure-Python universal wheel (deterministic, no C compilation)
CFGDRIFT_NO_C=1 python -m build --wheel
# C-accelerated platform wheel (optional; requires a C99 compiler)
python -m build --wheel
# sdist (ships C sources; do not set CFGDRIFT_NO_C)
python -m build --sdist
Environment variables
| Variable | Value | Description |
|---|---|---|
CFGDRIFT_BACKEND | auto (default) / pure / c | parser backend selection; auto uses C when available and silently falls back to pure Python |
CFGDRIFT_DEBUG | 1 | enables logging.DEBUG and prints the current parse backend |
CFGDRIFT_NO_C | 1 / true / yes | skips C extension compilation at build time |
CFGDRIFT_HOME | path | overrides the data directory (default ~/.cfgdrift/) |
GITHUB_TOKEN | token | GitHub token for the corpus star check |
CFGDRIFT_CV_RETENTION_DAYS | integer | retention days for constraint violations (default 90) |
Dual-mode consistency
Valid input produces semantically equivalent trees under both the C and pure-Python backends
(type-sensitive, key order not considered); invalid input raises ValueError in both backends,
with messages starting parse error at line L, column C (text after the colon may differ).
The tests/test_dual_mode.py suite runs consistency regression on both backends using the same corpus.
Known documented differences
See the v0.2.0 section (Appendix A) of docs/system_design.md for the design details:
- Unpaired surrogate pairs in JSON (e.g.
"\ud83d"): pure mode accepts (stdlib behavior), C mode rejects; - fractional seconds of timezone-less TOML datetimes: C outputs the literal (
...00.5), pure mode outputs zero-padded 6-digitisoformat()(...00.500000); - local times with a UTC offset (
07:32:00Z) violate TOML v1.0 syntax: pure mode rejects, C mode accepts as a literal; - INI trailing content after section headers (
[s] junk) and section names with spaces ([ s ]) are normalized differently by the two backends; - INI multi-line continuations: C rejects indented continuations, while pure mode's configparser accepts them as multi-line values (more lenient).
Choose the backend with the CFGDRIFT_BACKEND environment variable (auto / pure / c);
CFGDRIFT_DEBUG=1 logs the active backend (parser backend: c/pure).