bellybutton is a customizable, easy-to-configure linting engine for Python.
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
bellybutton can be installed via:
pip install bellybuttonOnce installed, running
bellybutton initin 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 lintwill lint the project against the rules specified in your .bellybutton.yml. Additionally, running
bellybutton lint --modified-onlywill, 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.
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
settingsthat specify on which files the rule is to be enforced, as well as whether it can be ignored via a# bb: ignorecomment - An example
exampleof Python code that would be matched by the rule - A counter-example
insteadof 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 nodes specify:
includedpaths on which rules are to be run, using glob notationexcludedpaths on which rules are not to be run (even when matching theincludedpaths)- A boolean
allow_ignorewhich determines whether rules can be ignored, providing the line matching the rule has a# bb: ignorecomment.
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: noCheck 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.
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.
- The
!chainand!verbalexpression nodes are not yet implemented
- Name: H. Chase Stevens
- Twitter: @hchasestevens
