Skip to main content

Well, actually — an opinionated Python linter and formatter: bans else and elif, allows only flat ternaries, and enforces blank lines around return

Project description

actually

Well, actually, your code should read like this.

actually is a highly opinionated Python linter and formatter built on ast-grep. It enforces a guard-clause style through rules with ruff-style stable codes, grouped by language construct (ADR 1). Every rule is checkable; the auto-fix column marks what format can rewrite. Each rule links to its documentation page with rationale and a banned/wanted example pair — generated from rules.toml and validated by the linter itself (ADR 2):

Code Rule Status Auto-fix What it enforces
ACTC001 no-else stable partial else on if, and the completion clauses on for, while, try
ACTC002 no-elif stable no elif — use guard clauses or a dispatch table
ACTC003 ternary-not-nested stable no a ternary inside another ternary's arm (elif in expression form)
ACTC004 ternary-not-empty unstable no a degenerate ternary arm (None, "", empty container) — conditional inclusion in disguise
ACTR001 blank-before-return stable yes a return stacked directly under other statements in its block
ACTR002 blank-after-return stable yes code directly under a return line

Usage

uvx well-actually@latest check .
uvx well-actually@latest format .

The @latest matters: a bare uvx well-actually reuses a cached tool environment and can silently run an outdated version; @latest re-resolves against the index every time.

Installed (uv tool install well-actually), the short command is available too:

actually check .
actually format .

check reports violations and exits non-zero when it finds any. Both commands lint .py files only; directory scans skip environment, cache, and VCS directories (.venv, venv, .git, __pycache__, node_modules, and friends) and respect .gitignore files — nested ones and negations included, matched via pathspec (black's approach), so no git installation is required. When a .git directory is found above the scanned path, .gitignore files up to that repo root apply as well. Global excludes (core.excludesFile, .git/info/exclude) are not consulted. A .py file passed explicitly is always linted.

format rewrites files in place, then reports what it could not fix:

  • inserts the missing blank lines around return
  • dedents a try/except/else completion clause into straight-line code when every except body already exits (return, raise, continue, break) — when one falls through, the rewrite would change behaviour, so it is reported for human refactoring instead

Example

def describe_config(path):
    try:
        config = parse_json_file(path)
    except ParseError:
        return "invalid config"
    else:
        return describe(config)

actually format rewrites this to:

def describe_config(path):
    try:
        config = parse_json_file(path)
    except ParseError:
        return "invalid config"

    return describe(config)

Development

uv sync
mise install
hk install
uv run pytest

README.md and rules/*.md are generated from README.template.md and rules.toml by scripts/generate_docs.py; an hk pre-commit hook regenerates and stages them. Edit the sources, never the outputs.

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

well_actually-0.3.0.tar.gz (8.4 kB view details)

Uploaded Source

Built Distribution

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

well_actually-0.3.0-py3-none-any.whl (11.8 kB view details)

Uploaded Python 3

File details

Details for the file well_actually-0.3.0.tar.gz.

File metadata

  • Download URL: well_actually-0.3.0.tar.gz
  • Upload date:
  • Size: 8.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.28 {"installer":{"name":"uv","version":"0.11.28","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for well_actually-0.3.0.tar.gz
Algorithm Hash digest
SHA256 6c673c189869046159e1bd56afe96d1348e224a3d7326034de61bdaaeafbc827
MD5 f61f4b8545c60eb8d7272005891d2af7
BLAKE2b-256 bab01e927c2479e67df3367a1def912f11846ed8ee5aa6c7a445673ace7be35c

See more details on using hashes here.

File details

Details for the file well_actually-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: well_actually-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 11.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.28 {"installer":{"name":"uv","version":"0.11.28","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for well_actually-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 e5bab3c1886f3beca72fc7da4ff86bbd415252ec74cb79a2b6125144fff30910
MD5 728a045d04fe88e9cccda72ffe5a52d6
BLAKE2b-256 b5521d636f762245ab79feaacad9108a556e3e55e6142841687f62f26ca7f833

See more details on using hashes here.

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