Skip to content

Linting

Henry Wright edited this page Jul 11, 2025 · 12 revisions

Lint (software) - Wikipedia

The following applies to all SciTools repositories except Cartopy, which has its own independent team of awesome developers.

Which linters

We mainly use the Scientific Python Library Development Guide to dictate which linting tools check our repositories. Our 'compliance' is maintained by using the automated sp-repo-review tool, as a pre-commit hook.

We sometimes also choose linting tools that are not covered by Scientific Python. To ensure a consistent developer experience across repositories, we record our standard list of linting tools in a template .pre-commit-config.yaml, which all repos are expected to align with as closely as possible.

Which rules

The following linting tools categorise their rules, which allows use to easily choose which types of rules we want to opt-in or opt-out:

We try to apply as many of the rules as possible - both the default one and optional extra ones - then opt-out of any specific rules that cannot be applied. Opt-out reasons that are shared across all our repositories are recorded in the pyproject.toml template.

Despite the template, opting-out of specific rules, is still handled on a repo by repo basis, achieved via each repository's pyproject.toml file, which includes sections to configure each of the above tools. We expect that some repositories will need to ignore rules that other repositories can be fully compliant with. This content should not be included in the template.

Temporary opt-out rules

Should be separated from the permanent opt-outs with a # TODO: comment. E.g.

[tool.ruff.lint]
ignore = [
    "AAA111",
    "BBB222",

    # TODO: exceptions that still need investigating are below. Might be fixable, or might become permanent (above):
    "YYY999",
    "ZZZ000",
    ]

Targeted opt-outs

If you consider a rule to not apply for a specific file, or a specific line in a file, you can usually ignore that rule on a more granular basis rather than opting out completely; this will ensure that any new code added will still have the linting rule applied to it.

This can be done on a per file basis, for example in Ruff:

[tool.ruff.lint.per-file-ignores]
"cf_units/tests/*.py" = [
     "N999",  # Invalid module name

With Ruff, this can also be done for specific lines in a file, e.g.:

@property
def file_element(self):
    # noqa D102   # <-- allow undocumented public method
    return self._file_element

Comments

Please use comments to give as much info as possible to your fellow developers. E.g.

[tool.ruff.lint]
ignore = [
    # flake8-commas (COM)
    # https://docs.astral.sh/ruff/rules/#flake8-commas-com
    "COM812",  # Trailing comma missing.
    "COM819",  # Trailing comma prohibited.

    # flake8-implicit-str-concat (ISC)
    # https://docs.astral.sh/ruff/rules/single-line-implicit-string-concatenation/
    # NOTE: This rule may cause conflicts when used with "ruff format".
    "ISC001",  # Implicitly concatenate string literals on one line.
    ]


Clone this wiki locally