Skip to main content

Enforce top-down / newspaper-style function ordering in Python

Project description

flake8-stepdown

Python 3.12+ codecov

A flake8 plugin that enforces top-down (newspaper-style) function ordering in Python modules.

This is inspired by Robert C. Martin's "Clean Code" stepdown rule: High-level logic first, details later. When reading a module, callers should appear before callees, so you can read the code from top to bottom like a newspaper article.

Violation codes

Code Meaning
TDP001 Function is defined in the wrong order (should appear after another function)

Installation

pip install flake8-stepdown

The plugin registers itself with flake8 automatically. Verify it's installed:

flake8 --version

You should see flake8-stepdown in the list of installed plugins.

Usage

As a flake8 plugin

Just run flake8 as usual, the plugin will report TDP001 violations:

flake8 your_module.py

Standalone CLI

The package also provides a stepdown command with three subcommands:

# Report violations
stepdown check your_module.py

# Show a unified diff of the proposed reordering
stepdown diff your_module.py

# Rewrite files in place
stepdown fix your_module.py

Use -v / --verbose to show mutual recursion info on stderr.

Development

Prerequisites

  • UV (Python package manager)

Setup

uv sync

Linting

./lint.sh

Testing

uv run pytest

Tests are organized by pipeline stage (test_parser.py, test_graph.py, test_rewriter.py, etc.). The rewriter uses snapshot testing: tests/fixtures/ contains input Python files exercising various scenarios (bottom-up ordering, mutual recursion, decorators, etc.), and tests/snapshots/ contains the expected output after rewriting. The test suite asserts correctness against snapshots, idempotency, and syntax validity.

Robustness testing

A separate script tests the plugin against real-world Python projects (click, httpx, rich, attrs, typer, pendulum, pydantic-settings) to detect crashes and code corruption:

bash tests/robustness/run_robustness.sh

For each project, the script:

  1. Clones the repo and installs it alongside flake8-stepdown
  2. Runs stepdown check and verifies it doesn't crash
  3. Runs the project's test suite (baseline)
  4. Runs stepdown fix and validates the rewritten code compiles
  5. Re-runs the test suite and checks for regressions

See tests/robustness/projects.json to configure the list of target projects.

Pre-commit hooks

Pre-commit hooks are installed automatically. To run manually:

uv run pre-commit run --all-files

CI

GitHub Actions runs linting, type checking, and tests on every push to main and on pull requests.

Publishing to PyPI

This project uses trusted publishing via GitHub Actions.

To publish a new version:

  1. Bump the version with uv version --bump patch (or minor/major)
  2. Update __version__ in flake8_stepdown/__init__.py to match
  3. Create a GitHub release with a tag matching the version (e.g., v0.1.0)
  4. The publish workflow will automatically build and upload to PyPI

First-time setup: Configure a trusted publisher on PyPI under your project's settings (Publishing tab). Use publish.yml as the workflow name and publish as the environment name.

Contributing

See CONTRIBUTING.md for code style, conventions, and development workflow.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

flake8_stepdown-0.1.2.tar.gz (67.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

flake8_stepdown-0.1.2-py3-none-any.whl (20.2 kB view details)

Uploaded Python 3

File details

Details for the file flake8_stepdown-0.1.2.tar.gz.

File metadata

  • Download URL: flake8_stepdown-0.1.2.tar.gz
  • Upload date:
  • Size: 67.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for flake8_stepdown-0.1.2.tar.gz
Algorithm Hash digest
SHA256 0fe5675c2a091e1d0ba0188d0d6a367fe277551aa55aafa12988991d14f46f81
MD5 8895f0a1c3845e25ef4b4494cb06d414
BLAKE2b-256 19ef88a4750045bd2b67bfadc9e8a4d145919aa5e120fb27b879f74f65b0106a

See more details on using hashes here.

Provenance

The following attestation bundles were made for flake8_stepdown-0.1.2.tar.gz:

Publisher: publish.yml on didmar/flake8-stepdown

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file flake8_stepdown-0.1.2-py3-none-any.whl.

File metadata

File hashes

Hashes for flake8_stepdown-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 f466ecfdd89558e8f2b2a72da8509f0e60026c8c19b7c6952168051aa40eeb3c
MD5 10e727ef91f16c29d066ab2474c538d4
BLAKE2b-256 58f1f93ee584f5516c3b275d968cfdb4d0c81b4ffb51c442980a8bc82e38e638

See more details on using hashes here.

Provenance

The following attestation bundles were made for flake8_stepdown-0.1.2-py3-none-any.whl:

Publisher: publish.yml on didmar/flake8-stepdown

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page