Flake8 Documentation

repository·main·Indexed 26 days ago

https://github.com/pycqa/flake8

Flake8 is a Python linting tool that wraps PyFlakes, pycodestyle, and McCabe to provide a unified interface for checking code quality and complexity. It supports plugins for adding new checks and formatters, utilizes a system of error codes and classes (F, E, W, C), and provides a command-line interface for analyzing files and directories. The documentation covers installation, configuration precedence, internal components like FileChecker and Manager, and guidelines for plugin development.

Tokens
14.9K
Snippets
48
Records
124
Agent score
82%

What's inside Flake8

  1. Overview of Flake8

    main
    Flake8 is a tool that wraps PyFlakes, pycodestyle, and Ned Batchelder's McCabe script. It runs these tools via a single flake8 command and provides a merged, per-file output of warnings.
  2. Understand the Flake8 execution lifecycle

    main

    When running the standard flake8.main.application.Application.run workflow, the following sequence occurs:

    1. Initialization (initialize): Loads plugins, registers plugin options, parses command-line arguments, configures the formatter, creates the StyleGuide, and initializes the Manager (file checker manager).
    2. Running Checks (run_checks): Aggregates files matching patterns (excluding those explicitly excluded), creates a flake8.checker.FileChecker for each file, and executes checks (potentially using subprocesses via --jobs).
    3. Reporting Violations (report_errors): Passes violations from the manager through the StyleGuide. The DecisionEngine determines if an error code should be reported or ignored based on user configuration.
    4. Reporting Benchmarks (report_benchmarks): If --benchmark is enabled, performance data is printed.
    5. Exiting (exit): Determines the exit code based on the error count and the presence of the --exit-zero flag.
  3. Understand Flake8 core concepts: plugins, checks, and formatters

    main

    To extend or use Flake8, it is important to understand its core components:

    • plugin: A package (typically installed from PyPI) that augments Flake8 by adding new checks or formatters.
    • check: The specific logic that corresponds to an error code. This can be a style check (e.g., line length) or a lint check (e.g., unused imports).
    • formatter: A plugin that augments the output when used with the --format option.
  4. Getting started with Flake8 plugin development

    main

    To develop a Flake8 plugin, you must first decide on the type of plugin you want to build: a Formatter or a Check. All plugins must be registered via Python entry points so that Flake8 can discover them.

    Prerequisites for development include:

    • A defined plugin idea
    • An available package name on PyPI
    • Python installed
    • A text editor or IDE
  5. Develop a custom formatting plugin for Flake8

    main

    To create a custom formatter plugin, inherit from flake8.formatting.base.BaseFormatter. You must implement the format(self, error) method, which receives an error object and should return a string representation of that error.

    Flake8 interacts with your formatter in two ways:

    1. It instantiates the formatter and provides it with options parsed from configuration files and command-line arguments.
    2. It calls the handle method with the error object.

    By default, BaseFormatter.handle calls format and then write. If you need to perform additional logic (such as aggregating results into XML or JSON), you should override the handle method.

    from flake8.formatting import base
    
    
    class Example(base.BaseFormatter):
        """Flake8's example formatter."""
    
        def format(self, error):
            return 'Example formatter: {0!r}'.format(error)
  6. Organize imports using Google style

    main

    Flake8 follows Google's Python Style Guide for imports. Imports must be:

    1. Only importing modules (avoid importing specific objects into a namespace).
    2. Grouped into three distinct sections:
      • Standard library imports
      • Third-party dependency imports
      • Local application imports
    3. Ordered alphabetically within each group.

    Do not add comments to label which group an import belongs to.

    import configparser
    import logging
    from os import path
    
    import requests
    
    from flake8 import exceptions
    from flake8.formatting import base
  7. Ignore entire files

    main

    There are two ways to prevent Flake8 from checking an entire file:

    1. Using --exclude (Recommended): Add the file path to the excluded paths list via the --exclude flag or in your configuration file. This keeps the exclusion logic centralized.
    2. Using # flake8: noqa: Add this comment to the top of the file. This is useful if you want the file to be checked again easily if you run Flake8 with --disable-noqa.
  8. Exclude files from Flake8 in pre-commit

    main

    When using Flake8 via pre-commit, the --exclude option in Flake8 is ignored because checked-in files are passed as positional arguments. To exclude specific files or directories, use the exclude regex setting within your .pre-commit-config.yaml configuration.

    -   id: flake8
        exclude: ^testing/(data|examples)/
  9. Register a Flake8 plugin using entry points

    main

    Flake8 discovers plugins via Python entry points defined in your package metadata (e.g., setup.py using setuptools). To register a plugin, you must define an entry point in one of two specific groups:

    1. flake8.extension: Use this if your plugin adds new linting checks.
    2. flake8.report: Use this if your plugin performs report handling, such as custom formatting or filtering.

    Important Naming Rules:

    • Each entry point must be unique in the user's environment. Duplicate names can cause plugins to be silently deactivated.
    • The entry point name acts as a prefix for the error codes your plugin reports.
    • Prefix Length: Avoid single-letter prefixes (e.g., X). It is recommended to use a 2 or 3 character prefix (e.g., ABC).
    • Maximum Length: The longest allowed entry point name is a 3-letter prefix followed by 3 numbers (e.g., ABC123).
    import setuptools
    
    setuptools.setup(
        name="flake8_example",
        # ... other metadata ...
        entry_points={
            'flake8.extension': [
                'X101 = flake8_example:ExamplePlugin',
            ],
        },
    )