Migrating from v1 to v2¶
Wily v2 is a major rewrite. The analysis backend has been replaced with a Rust native extension, the storage format has changed from JSON to Parquet, and several operators have been renamed or replaced. This guide covers everything you need to know to upgrade.
Requirements¶
Python 3.10+ is required. Wily v1 supported Python 3.6+.
Rust toolchain is only needed if building from source. Pre-built wheels are available for Linux, macOS, and Windows (x86_64 and aarch64).
Rebuilding the cache¶
The v1 cache (JSON files under ~/.wily/) is not compatible with v2. You must rebuild:
$ wily clean -y
$ wily build src/
This will delete the old cache and create a new one using the Parquet storage format. The new cache is significantly faster for large codebases thanks to columnar storage and parallel analysis.
Note
If you use --cache to specify a custom cache path, make sure to clean and rebuild that location as well.
Operator and metric changes¶
Removed: mccabe¶
The mccabe operator from v1 (which used the mccabe Python package) has been removed. Its functionality is replaced by the cyclomatic operator, which now uses Ruff’s AST parser implemented in Rust.
If you referenced mccabe in your configuration or scripts, change it to cyclomatic:
# v1
$ wily build src/ -o raw,mccabe,maintainability
# v2
$ wily build src/ -o raw,cyclomatic,maintainability
The metric name remains complexity (accessed as cyclomatic.complexity), so wily report and wily graph commands using that metric name will continue to work.
New: cognitive¶
v2 adds a new cognitive operator that measures cognitive complexity — how hard code is to understand, as opposed to cyclomatic complexity which measures structural/branching complexity. Based on the SonarSource “Cognitive Complexity” paper by G. Ann Campbell (2017).
$ wily build src/ -o raw,cyclomatic,cognitive,maintainability
$ wily report src/module.py cognitive.cognitive_complexity
Default operators¶
In v2, the default operator set is: cyclomatic, maintainability, raw, halstead, and cognitive. In v1, the defaults were: raw, maintainability, cyclomatic, and halstead.
The main difference is that cognitive is now included by default.
Metric name reference¶
All metrics from v1 are still available in v2 under the same names. Here is the complete list:
Metric key |
Description |
Operator |
|---|---|---|
|
Lines of Code |
raw |
|
Logical Lines of Code |
raw |
|
Source Lines of Code |
raw |
|
Multi-line comments |
raw |
|
Multi lines |
raw |
|
Blank lines |
raw |
|
Single comment lines |
raw |
|
Cyclomatic Complexity |
cyclomatic |
|
Unique Operators |
halstead |
|
Unique Operands |
halstead |
|
Number of Operators |
halstead |
|
Number of Operands |
halstead |
|
Unique vocabulary (h1 + h2) |
halstead |
|
Length of application |
halstead |
|
Code volume |
halstead |
|
Difficulty |
halstead |
|
Effort |
halstead |
|
Maintainability Index |
maintainability |
|
Maintainability Ranking (A/B/C) |
maintainability |
|
Cognitive Complexity (new in v2) |
cognitive |
CLI changes¶
The CLI commands are largely the same between v1 and v2. The main differences are:
New options on existing commands¶
Several commands gained new formatting options in v2:
--wrap/--no-wrap: Control whether output wraps to terminal width (available onindex,rank,report,diff,list-metrics)--table-style: Choose a Rich table border style such asROUNDED,ASCII,SIMPLE,MINIMAL, orMARKDOWN(available on the same commands)--json/--no-json: Outputdiffresults in JSON format
Output formatting¶
v1 used
tabulatefor console tables. v2 uses Rich, which provides better terminal rendering with color support and configurable table styles.HTML reports continue to work with the
-f HTMLoption onwily report.
Removed dependencies¶
v2 removes several Python dependencies that were used in v1 for metric computation:
v1 (Python) |
v2 (Rust backend) |
|---|---|
|
Built-in Rust implementation using |
|
Removed (replaced by |
|
Replaced by |
The remaining Python dependencies in v2 are: gitpython, click, nbformat, plotly, and rich.
Storage format¶
v1 |
v2 |
|
|---|---|---|
Format |
JSON files (one per revision per operator) |
Single Parquet file per archiver |
Location |
|
|
Schema |
Nested JSON (operator → path → metrics) |
Flat columnar (one row per file per revision) |
Performance |
Slower on large codebases |
Significantly faster (columnar reads + parallel writes) |
The Parquet schema stores metadata columns (revision, date, author, message, path, path_type) alongside all metric values as top-level columns.
Row types by path_type:
"file"— metrics for an individual Python file"directory"— aggregated metrics for a directory"root"— aggregated metrics for the entire project (path is"")"function"/"class"— detailed object-level metrics (path format:"file.py:object_name")
Configuration¶
Wily v2 continues to read configuration from wily.cfg files. The configuration format is unchanged.
The --path, --cache, --debug, and --config global options work the same as in v1.
Pre-commit hook¶
The pre-commit hook configuration is unchanged:
repos:
- repo: local
hooks:
- id: wily
name: wily
entry: wily diff
verbose: true
language: python
additional_dependencies: [wily]
CI/CD usage¶
If you use wily in CI/CD pipelines:
Update your Python version to 3.10+ if not already.
Remove ``mccabe`` references from any operator lists.
Rebuild your cache — if you cache the
~/.wily/directory between CI runs, delete it and rebuild. The v1 JSON cache is not compatible.Update any metric parsing scripts — if you parse wily’s output programmatically, note that the console output now uses Rich formatting. Use
wily diff --jsonfor machine-readable output.
Performance improvements¶
v2 brings significant performance improvements:
Parallel file analysis: Files are analyzed in parallel using Rayon (Rust). Build times are substantially faster on multi-core machines.
Rust-native parsing: Python AST parsing uses
ruff_python_parser(from the Ruff project), which is much faster than the Python-basedradonandmccabepackages.Columnar storage: Parquet format enables faster reads for report and graph operations, especially on large indexes.
Reduced Python overhead: The hot path (parsing, metric computation, storage I/O) runs entirely in Rust.
Quick migration checklist¶
✅ Ensure Python 3.10+ is installed
✅ Install wily v2:
pip install wily✅ Delete old cache:
wily clean -y✅ Replace
mccabewithcyclomaticin any config or scripts✅ Rebuild the index:
wily build src/✅ Verify with
wily reportorwily index✅ Optionally try the new
cognitiveoperator