Code style tools#

There are many tools for checking code style. This section presents some of the most popular ones in the Python ecosystem. A minimum configuration is provided for each one so that you can easily include them in your PyAnsys project.

Most of the tools presented can be configured using The pyproject.toml file. Avoiding dotfiles leads to a much cleaner root project directory.

Black#

Black is the most popular code formatter in the Python community because it is maintained by the Python Software Foundation. It allows for a minimum configuration to ensure that the Python code format looks almost the same across projects.

While PEP 8 imposes a default line length of 79 characters, black has a default line length of 88 characters.

The minimum black configuration for a PyAnsys project should look like this:

[tool.black]
line-length = "<length>"

Isort#

The goal of isort is to properly format import statements by making sure that they follow the standard order:

  1. library

  2. third-party libraries

  3. custom libraries

When using isort with black, it is important to properly configure both tools so that no conflicts arise. To accomplish this, use the --profile black flag in isort.

[tool.isort]
profile = "black"
force_sort_within_sections = true
line_length = "<length>"
default_section = "THIRDPARTY"
src_paths = ["doc", "src", "tests"]

Flake8#

The goal of flake8 is to act as a PEP 8 compliance checker. Again, if this tool is being used with black, it is important to make sure that no conflicts arise.

The following configuration is the minimum one to set up flake8 together with black.

The configuration for flake8 must be specified in a .flake8 file.

[flake8]
max-line-length = 88
extend-ignore = 'E203'

Flake8 has many options that can be set within the configuration file. For more information, see this Flake8 documentation topic.

The example configuration defines these options:

  • exclude

    Subdirectories and files to exclude when checking.

  • select

    Sequence of error codes that Flake8 is to report errors for. The set in the preceding configuration is a basic set of errors for checking and is not an exhaustive list.

    For a full list of error codes and their descriptions, see this Flake8 documentation topic.

  • count

    Total number of errors to print when checking ends.

  • max-complexity
    Maximum allowed McCabe complexity value for a block of code.

    The value of 10 was chosen because it is a common default.

  • statistics

    Number of occurrences of each error or warning code to print as a report when checking ends.

Code coverage#

Code coverage indicates the percentage of the codebase tested by the test suite. Code coverage should be as high as possible to guarantee that every piece of code has been tested.

For PyAnsys libraries, code coverage is done using pytest-cov, a pytest plugin that triggers code coverage analysis once your test suite has executed.

Considering the layout presented in Required files, the following configuration for code coverage is the minimum one required for a PyAnsys project:

[tool.coverage.run]
source = ["ansys.<product>"]

[tool.coverage.report]
show_missing = true

Pre-commit#

To ensure that every commit you make is compliant with the code style guidelines for PyAnsys, you can take advantage of pre-commit in your project. Every time you stage some changes and try to commit them, pre-commit only allows them to be committed if all defined hooks succeed.

The configuration for pre-commit must be defined in a .pre-commit-config.yaml file. The following lines present a minimum pre-commit configuration that includes both code and documentation formatting tools.

repos:

- repo: https://github.com/psf/black
  rev: X.Y.Z
  hooks:
  - id: black

- repo: https://github.com/pycqa/isort
  rev: X.Y.Z
  hooks:
  - id: isort

- repo: https://github.com/PyCQA/flake8
  rev: X.Y.Z
  hooks:
  - id: flake8

- repo: https://github.com/codespell-project/codespell
  rev: vX.Y.Z
  hooks:
  - id: codespell

- repo: https://github.com/pycqa/pydocstyle
  rev: X.Y.Z
  hooks:
  - id: pydocstyle
    additional_dependencies: [toml]
    exclude: "tests/"

Installing pre-commit#

You can install pre-commit by running:

python -m pip install pre-commit

Then, ensure that you install it as a Git hook by running:

pre-commit install

Using pre-commit#

One installed as described, pre-commit automatically triggers every time that you try to commit a change. If any hook defined in .pre-commit-config.yaml fails, you must fix the failing files, stage the new changes, and try to commit them again.

If you want to manually run pre-commit, you can run:

pre-commit run --all-files --show-diff-on-failure

This command shows the current and expected style of the code if any of the hooks fail.

Tox#

You might consider using tox in your project. While this automation tool is similar to Make, it supports testing of your package in a temporary virtual environment. Being able to test your package in isolation rather than in “local” mode guarantees reproducible builds.

Configuration for tox is stored in a tox.ini file. The minimum configuration for a PyAnsys py<product>-<library> project should be:

[tox]
description = Default tox environments list
envlist =
    style,{py37,py38,py39,py310}{,-coverage},doc
skip_missing_interpreters = true
isolated_build = true
isolated_build_env = build

[testenv]
description = Checks for project unit tests and coverage (if desired)
basepython =
    py37: python3.7
    py38: python3.8
    py39: python3.9
    py310: python3.10
    py: python3
    {style,reformat,doc,build}: python3
setenv =
    PYTHONUNBUFFERED = yes
    coverage: PYTEST_EXTRA_ARGS = --cov=ansys.product --cov-report=term --cov-report=xml --cov-report=html
deps =
    -r{toxinidir}/requirements/requirements_tests.txt
commands =
    pytest {env:PYTEST_MARKERS:} {env:PYTEST_EXTRA_ARGS:} {posargs:-vv}

[testenv:style]
description = Checks project code style
skip_install = true
deps =
    pre-commit
commands =
    pre-commit install
    pre-commit run --all-files --show-diff-on-failure

[testenv:doc]
description = Check if documentation generates properly
deps =
    -r{toxinidir}/requirements/requirements_doc.txt
commands =
    sphinx-build -d "{toxworkdir}/doc_doctree" doc/source "{toxworkdir}/doc_out" --color -vW -bhtml
[tox]
description = Default tox environments list
envlist =
    style,{py37,py38,py39,py310}{,-coverage},doc
skip_missing_interpreters = true
isolated_build = true

[testenv]
description = Checks for project unit tests and coverage (if desired)
basepython =
    py37: python3.7
    py38: python3.8
    py39: python3.9
    py310: python3.10
    py: python3
    {style,reformat,doc,build}: python3
skip_install = true
whitelist_externals =
    poetry
setenv =
    PYTHONUNBUFFERED = yes
    coverage: PYTEST_EXTRA_ARGS = --cov=ansys.product --cov-report=term --cov-report=xml --cov-report=html
deps =
    -r{toxinidir}/requirements/requirements_tests.txt
commands =
    poetry install
    poetry run pytest {env:PYTEST_MARKERS:} {env:PYTEST_EXTRA_ARGS:} {posargs:-vv}

[testenv:style]
description = Checks project code style
skip_install = true
deps =
    pre-commit
commands =
    pre-commit install
    pre-commit run --all-files --show-diff-on-failure

[testenv:doc]
description = Check if documentation generates properly
deps =
    -r{toxinidir}/requirements/requirements_doc.txt
commands =
    poetry run sphinx-build -d "{toxworkdir}/doc_doctree" doc/source "{toxworkdir}/doc_out" --color -vW -bhtml

This minimum configuration assumes that you have a requirements/ directory that contains requirements_tests.txt and requirements_doc.txt. In addition, the style environment must execute pre-commit, which guarantees the usage of this tool in your project.

Installing tox#

You can install tox like any other Python package:

python -m pip install tox

Using tox#

tox uses environments, which are similar to Makefile rules, to make it highly customizable. Descriptions follow of some of the most widely used environments:

  • tox -e style checks the code style of your project.

  • tox -e py runs your test suite.

  • tox -e doc builds the documentation of your project.

It is possible to run multiple environments by separating them with commas tox -e <env-name0>,<env-name1>,...`. To run all available environments, simply run tox.