The Zen of Python [1] emphasises complexity reduction in many ways:

Simple is better than complex.

Complex is better than complicated.

Flat is better than nested.

Wily is a command line tool for checking the complexity of Python code in tests and applications. For this purpose, Wily uses the following metrics:

Cyclomatic complexity

measures the complexity of code by the number of linearly independent paths in the control flow graph.

The Software Engineering Institute at Carnegie Mellon University distinguishes the following four levels of risk [2]:

Cyclomatic complexity

Risk assessment


Simple programme without much risk


moderate risk


complex, high-risk programme

> 50

untestable programme with very high risk

Halstead complexity measures

Statically analysing procedure that calculates the difficulty of the programme, the effort and the implementation time from the number of operators and operands.

Maintainability Index

is based on the cyclomatic complexity, the Halstead complexity measures and the number of lines of code [3]:








in need of improvement


Superhero code


Wily can be easily installed with

$ pipenv install wily

You can then check the installation with

$ pipenv run wily --help
Usage: wily [OPTIONS] COMMAND [ARGS]...
  Version: 1.19.0
  🦊 Inspect and search through the complexity of your source code. To get
  started, run setup:
    $ wily setup 


A wily.cfg file can be created in the project directory with the list of available operators:

# list of operators, choose from cyclomatic, maintainability, mccabe and raw
operators = cyclomatic,raw
# archiver to use, defaults to git
archiver = git
# path to analyse, defaults to .
path = /path/to/target
# max revisions to archive, defaults to 50
max_revisions = 20

Python code in .ipynb files is also usually recognised automatically. However, you may be able to disable this for a Jupyter notebook with

ipynb_support = false

or for individual cells with

ipynb_cells = false


… as a command line tool

  1. Building a cache with the statistics of the project


    Wily assumes that your project folder is a Git repository. However, Wily does not create a cache if the working directory is dirty.

    $ pipenv run wily build
  2. Show metric

    $ pipenv run wily report

    This outputs both the metric and the delta to the previous revision.

  3. Show ranking

    $ pipenv run wily rank

    This shows the ranking of all files in a directory or a single file based on the specified metric, if present in .wily/.

  4. Show graph

    $ pipenv run wily graph

    This displays a graph in the default browser.

  5. Show build directory information

    $ pipenv run wily index
  6. List the metrics available in the Wily operators

    $ pipenv run wily list-metrics

… as pre-commit hook

You can also use Wily as a pre-commit framework. To do this, you would have to add the following to the pre-commit-config.yaml configuration file, for example:

-   repo: local
    -   id: wily
        name: wily
        entry: wily diff
        verbose: true
        language: python
        additional_dependencies: [wily]

… in a CI/CD pipeline

Usually Wily compares the complexity with the previous revision. However, you can also specify other references, for example HEAD^1 with

$ pipenv run wily build src/
$ pipenv run wily diff src/ -r HEAD^1