Custom Python linting through AST expressions

Overview

bellybutton

Build Status PyPI version PyPI - Python Version

bellybutton is a customizable, easy-to-configure linting engine for Python.

What is this good for?

Tools like pylint and flake8 provide, out-of-the-box, a wide variety of rules for enforcing Python best practices, ensuring PEP-8 compliance, and avoiding frequent sources of bugs. However, many projects have project-specific candidates for static analysis, such as internal style guides, areas of deprecated functionality, or common sources of error. This is especially true of those projects with many contributors or with large or legacy codebases.

bellybutton allows custom linting rules to be specified on a per-project basis and detected as part of your normal build, test and deployment process and, further, makes specifying these rules highly accessible, greatly lowering the cost of adoption.

Give bellybutton a try if:

  • You find yourself making the same PR comments over and over again
  • You need a means of gradually deprecating legacy functionality
  • You're looking to build a self-enforcing style guide
  • Your project needs to onboard new or junior developers more quickly and effectively
  • You have Python nitpicks that go beyond what standard linting tools enforce

Installation & getting started

bellybutton can be installed via:

pip install bellybutton

Once installed, running

bellybutton init

in your project's root directory will create a .bellybutton.yml configuration file with an example rule for you to begin adapting. bellybutton will also try to provide additional rule settings based on the directory structure of your project.

Once you have configured bellybutton for your project, running

bellybutton lint

will lint the project against the rules specified in your .bellybutton.yml. Additionally, running

bellybutton lint --modified-only

will, if using git, only lint those files that differ from origin/master.

For adding bellybutton to your CI pipeline, take a look at this repository's tox configuration and .travis.yml as an example.

Concepts

Rules

Rules in bellybutton supply patterns that should be caught and cause linting to fail. Rules as specified in your .bellybutton.yml configuration must consist of:

  • A description description, expressing the meaning of the rule
  • An expression expr, specifying the pattern to be caught - either as an astpath expression or as a regular expression (!regex ...).

Additionally, the key used for the rule within the rules mapping serves as its name.

Rules may also consist of:

  • Settings settings that specify on which files the rule is to be enforced, as well as whether it can be ignored via a # bb: ignore comment
  • An example example of Python code that would be matched by the rule
  • A counter-example instead of an alternative piece of code, for guiding the developer in fixing their linting error.

These example and instead clauses are checked at run-time to ensure that they respectively are and are not matched by the rule's expr.

As an example, a rule to lint for a deprecated function call using an astpath expression might look like:

DeprecatedFnCall:
  description: `deprecated_fn` will be deprecated in v9.1.2. Please use `new_fn` instead.
  expr: //Call[func/Name/@id='deprecated_fn']
  example: "deprecated_fn(*values)"
  instead: "new_fn(values)"

Settings

!settings nodes specify:

  • included paths on which rules are to be run, using glob notation
  • excluded paths on which rules are not to be run (even when matching the included paths)
  • A boolean allow_ignore which determines whether rules can be ignored, providing the line matching the rule has a # bb: ignore comment.

Additionally, at the root level of .bellybutton.yml, a default_settings setting may be specified which will be used by rules without explicit settings. Each rule must either have a settings parameter or be able to fall back on the default_settings.

As an example, a !settings node to lint only a specific module might look like:

my_module_settings: !settings
  included:
    - ~+/my_package/my_module.py
  excluded: []
  allow_ignore: no

Example usage

Check out this repository's .bellybutton.yml as an example bellybutton configuration file, and astpath's README for examples of the types of patterns you can lint for using bellybutton.

Development status

bellybutton is in an alpha release and, as such, is missing some key features, documentation, and full test coverage. Further, bellybutton is not optimized for performance on extremely large codebases and may contain breaking bugs. Please report any bugs encountered.

Known issues:

  • The !chain and !verbal expression nodes are not yet implemented

Contacts

Owner
H. Chase Stevens
Metaprogramming, natural language processing, and global optimization technique enthusiast.
H. Chase Stevens
Silence mypy by adding or removing code comments

mypy-silent Automatically add or remove # type: ignore commends to silence mypy. Inspired by pylint-silent Why? Imagine you want to add type check for

Wu Haotian 8 Nov 30, 2022
Flake8 plugin for managing type-checking imports & forward references

flake8-type-checking Lets you know which imports to put in type-checking blocks. For the imports you've already defined inside type-checking blocks, i

snok 67 Dec 16, 2022
🦆 Better duck-typing with mypy-compatible extensions to Protocol

🦆 Quacks If it walks like a duck and it quacks like a duck, then it must be a duck Thanks to PEP544, Python now has protocols: a way to define duck t

Arie Bovenberg 9 Nov 14, 2022
Flashcards - A flash card application with 2 optional command line arguments

Flashcards A flash card application with 2 optional command line arguments impor

Özgür Yildirim 2 Jul 15, 2022
docstring style checker

pydocstyle - docstring style checker pydocstyle is a static analysis tool for checking compliance with Python docstring conventions. pydocstyle suppor

Python Code Quality Authority 982 Jan 03, 2023
:sparkles: Surface lint errors during code review

✨ Linty Fresh ✨ Keep your codebase sparkly clean with the power of LINT! Linty Fresh parses lint errors and report them back to GitHub as comments on

Lyft 183 Dec 18, 2022
Code audit tool for python.

Pylama Code audit tool for Python and JavaScript. Pylama wraps these tools: pycodestyle (formerly pep8) © 2012-2013, Florent Xicluna; pydocstyle (form

Kirill Klenov 967 Jan 07, 2023
Design by contract for Python. Write bug-free code. Add a few decorators, get static analysis and tests for free.

A Python library for design by contract (DbC) and checking values, exceptions, and side-effects. In a nutshell, deal empowers you to write bug-free co

Life4 473 Dec 28, 2022
Naming Convention checker for Python

PEP 8 Naming Conventions Check your code against PEP 8 naming conventions. This module provides a plugin for flake8, the Python code checker. (It repl

Python Code Quality Authority 411 Dec 23, 2022
Optional static typing for Python 3 and 2 (PEP 484)

Mypy: Optional Static Typing for Python Got a question? Join us on Gitter! We don't have a mailing list; but we are always happy to answer questions o

Python 14.4k Jan 08, 2023
Flake8 wrapper to make it nice, legacy-friendly, configurable.

THE PROJECT IS ARCHIVED Forks: https://github.com/orsinium/forks It's a Flake8 wrapper to make it cool. Lint md, rst, ipynb, and more. Shareable and r

Life4 232 Dec 16, 2022
Type annotations builder for boto3 compatible with VSCode, PyCharm, Emacs, Sublime Text, pyright and mypy.

mypy_boto3_builder Type annotations builder for boto3-stubs project. Compatible with VSCode, PyCharm, Emacs, Sublime Text, mypy, pyright and other too

Vlad Emelianov 2 Dec 05, 2022
Flake8 plugin for managing type-checking imports & forward references

flake8-type-checking Lets you know which imports to put in type-checking blocks. For the imports you've already defined inside type-checking blocks, i

snok 67 Dec 16, 2022
Pylint plugin for improving code analysis for when using Django

pylint-django About pylint-django is a Pylint plugin for improving code analysis when analysing code using Django. It is also used by the Prospector t

Python Code Quality Authority 544 Jan 06, 2023
mypy plugin to type check Kubernetes resources

kubernetes-typed mypy plugin to dynamically define types for Kubernetes objects. Features Type checking for Custom Resources Type checking forkubernet

Artem Yarmoliuk 16 Oct 10, 2022
Unbearably fast O(1) runtime type-checking in pure Python.

Look for the bare necessities, the simple bare necessities. Forget about your worries and your strife. — The Jungle Book.

beartype 1.4k Jan 01, 2023
Tool for automatically reordering python imports. Similar to isort but uses static analysis more.

reorder_python_imports Tool for automatically reordering python imports. Similar to isort but uses static analysis more. Installation pip install reor

Anthony Sottile 589 Dec 26, 2022
Rust like Option and Result types in Python

Option Rust-like Option and Result types in Python, slotted and fully typed. An Option type represents an optional value, every Option is either Some

45 Dec 13, 2022
A simple plugin that allows running mypy from PyCharm and navigate between errors

mypy-PyCharm-plugin The plugin provides a simple terminal to run fast mypy daemon from PyCharm with a single click or hotkey and easily navigate throu

Dropbox 301 Dec 09, 2022
Collection of awesome Python types, stubs, plugins, and tools to work with them.

Awesome Python Typing Collection of awesome Python types, stubs, plugins, and tools to work with them. Contents Static type checkers Dynamic type chec

TypedDjango 1.2k Jan 04, 2023