Skip to main content

spacify

CI PyPI

A fast formatter for the vertical rhythm of Python code. ruff format decides how a statement is laid out, but leaves most of the blank lines between statements up to you. spacify fills that gap: it puts air around logical blocks and tightens runs of related statements, and it only touches the blank lines between statements.

Before:

def load(paths):
    seen = set()
    for path in paths:
        if path in seen:
            continue
        seen.add(path)
    total = len(seen)

    count = 0
    log(total)
    return total

After spacify:

def load(paths):
    seen = set()

    for path in paths:
        if path in seen:
            continue

        seen.add(path)

    total = len(seen)
    count = 0
    log(total)

    return total

spacify never fights ruff. Every rule stays inside the blank-line bounds ruff format keeps, and CI runs both tools over CPython's standard library in both orders to check they reach a fixed point. Checking all of CPython's Lib takes under half a second on 8 cores.

Install

uv tool install spacify    # or: pipx install spacify, pip install spacify

Use with prek or pre-commit

Put the hook after ruff-format, so spacify sees ruff's line wrapping:

repos:
  - repo: https://github.com/astral-sh/ruff-pre-commit
    rev: v0.16.9
    hooks:
      - id: ruff-format
  - repo: https://github.com/avanserv/spacify-pre-commit
    rev: v0.1.0
    hooks:
      - id: spacify

The hook installs the prebuilt wheel from PyPI, so you don't need a Rust toolchain.

Command line

spacify                   # format every Python file under the current directory
spacify src/ tests/a.py   # format these paths
spacify --check           # write nothing; exit 1 if any file would change
spacify --diff            # write nothing; print a unified diff
spacify - < a.py          # read stdin, write stdout (--stdin-filename names it)

The exit code is 0 on success, 1 when --check or --diff found changes, and 2 on an error such as a syntax error, in which case the file is left untouched. Directory walks respect .gitignore and skip the directories ruff skips by default. A file you name explicitly is always formatted, unless you also pass --force-exclude, which is what the hook does.

Rules

Each rule can be turned on or off. They all apply to sibling statements in the same block.

Rule Effect
blank-before-block At least one blank line before if, for, while, try, with and match (including the async forms) when another statement comes before them.
blank-after-block At least one blank line after one of those blocks, before the next statement.
blank-before-exit At least one blank line before return, raise, break, continue and a bare yield, in blocks of exit-min-block-statements (default 3) or more statements.
collapse-groups No blank line between two single-line statements of the same kind: assignments, augmented assignments, calls, del, assert, global/nonlocal. Outside every function and class, an assignment whose target names all have an uppercase letter and no lowercase one (MAX = 3, T = TypeVar("T"), A, *REST = items) is a constant, a kind apart from other assignments.

The added blank lines take priority over collapse-groups. A few places are never touched:

  • Gaps next to a def or class, after an import, or after a docstring. Ruff decides these.
  • Blank lines that have a comment in the gap, because a comment marks a paragraph you meant. When a rule does add a blank line, it goes above the comments that belong to the next statement.
  • Regions between # fmt: off and # fmt: on (or # spacify: off and # spacify: on), and any line marked # fmt: skip.

Imports are never collapsed, because ruff's isort rules separate import sections with blank lines. A nested block never gets more than one blank line in a row. At module level the limit is two, or one in a .pyi stub.

Configuration

spacify reads [tool.spacify] from pyproject.toml, or the top level of a spacify.toml or .spacify.toml. It uses the first one it finds walking up from the current directory, or the file you pass with --config.

[tool.spacify]
extend-exclude = ["generated", "migrations/*.py"]  # `exclude = [...]` replaces the defaults

[tool.spacify.rules]
blank-before-block = true
blank-after-block = true
blank-before-exit = true
exit-min-block-statements = 3
collapse-groups = true

An exclude pattern containing a / matches the path relative to the config file. Any other pattern matches a single file or directory name.

Contributing

See CONTRIBUTING.md.

Metadata

Release files for spacify 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for spacify 0.2.0
File Size Uploaded Provenance Actions
spacify-0.2.0.tar.gz 25.1 kB Without provenance Details for spacify-0.2.0.tar.gz

Built distributions (wheels)

Table of built distributions (wheels) for spacify 0.2.0
File Actions
spacify-0.2.0-py3-none-win_amd64.whl Python 3 none Windows x86-64 Details for spacify-0.2.0-py3-none-win_amd64.whl
spacify-0.2.0-py3-none-musllinux_1_2_x86_64.whl Python 3 none Linux musl 1.2+ x86-64 Details for spacify-0.2.0-py3-none-musllinux_1_2_x86_64.whl
spacify-0.2.0-py3-none-musllinux_1_2_aarch64.whl Python 3 none Linux musl 1.2+ ARM64 Details for spacify-0.2.0-py3-none-musllinux_1_2_aarch64.whl
spacify-0.2.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl Python 3 none Linux glibc 2.17+ x86-64 Details for spacify-0.2.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
spacify-0.2.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl Python 3 none Linux glibc 2.17+ ARM64 Details for spacify-0.2.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
spacify-0.2.0-py3-none-macosx_11_0_arm64.whl Python 3 none macOS 11.0+ ARM64 Details for spacify-0.2.0-py3-none-macosx_11_0_arm64.whl
spacify-0.2.0-py3-none-macosx_10_12_x86_64.whl Python 3 none macOS 10.12+ x86-64 Details for spacify-0.2.0-py3-none-macosx_10_12_x86_64.whl

Total release size: 8.6 MB

Release files / spacify-0.2.0.tar.gz

Download URL spacify-0.2.0.tar.gz
Size 25.1 kB
Tags Source
SHA-256 checksum
How to use checksums
5b89f2e73ff9f1de3529f84f60b26400be06eaf07a3fc6a3ad443aa7fab9b67c
BLAKE2b-256 checksum
How to use checksums
92e0a210f6a16aa902eade24fbc6ce9221042a923db9e1565647b56a2172207a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.13.2 {"installer":{"name":"uv","version":"0.13.2","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}

Release files / spacify-0.2.0-py3-none-win_amd64.whl

Download URL spacify-0.2.0-py3-none-win_amd64.whl
Size 1.2 MB
Tags Python 3 Windows x86-64
SHA-256 checksum
How to use checksums
a8878890d86c382c384bc99b4f5feddefa0cc551e67394c58854d257e95e24ea
BLAKE2b-256 checksum
How to use checksums
d5c62eb39ca095025f76cb5a5c68963a054426ca1d50dbe58dbf8a69f059b858
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.13.2 {"installer":{"name":"uv","version":"0.13.2","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}

Release files / spacify-0.2.0-py3-none-musllinux_1_2_x86_64.whl

Download URL spacify-0.2.0-py3-none-musllinux_1_2_x86_64.whl
Size 1.4 MB
Tags Linux musl 1.2+ x86-64 Python 3
SHA-256 checksum
How to use checksums
62c5d62d856be5719cca7922ce3a336a2b7c87d31499d6e692b8fbfba584abf9
BLAKE2b-256 checksum
How to use checksums
d54465145047dbc4bfe0abb19ebb9e4bc4cfd61f2e6c05e6a7a6bb3edf8eae00
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.13.2 {"installer":{"name":"uv","version":"0.13.2","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}

Release files / spacify-0.2.0-py3-none-musllinux_1_2_aarch64.whl

Download URL spacify-0.2.0-py3-none-musllinux_1_2_aarch64.whl
Size 1.2 MB
Tags Linux musl 1.2+ ARM64 Python 3
SHA-256 checksum
How to use checksums
b3415c0aae405268a510a748527a64bd4e79b87e4b6897d28eb08899812fe16e
BLAKE2b-256 checksum
How to use checksums
df91b48ffd6e3a83d0dfac21af4b586828871c4ab3a3e9f88c334d9bbaa7c624
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.13.2 {"installer":{"name":"uv","version":"0.13.2","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}

Release files / spacify-0.2.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL spacify-0.2.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 1.3 MB
Tags Linux glibc 2.17+ x86-64 Python 3
SHA-256 checksum
How to use checksums
343646acf8fbb2dccba41d33d575262df456cbcb8a57e2d034f4bebe4220bd02
BLAKE2b-256 checksum
How to use checksums
ede4615eb25a43eedfe48df8aaefc46ef6e80cce4edc49ed9f5abf9416460ccc
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.13.2 {"installer":{"name":"uv","version":"0.13.2","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}

Release files / spacify-0.2.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl

Download URL spacify-0.2.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Size 1.2 MB
Tags Linux glibc 2.17+ ARM64 Python 3
SHA-256 checksum
How to use checksums
c0aebdfe5a7d3887d7d89ef8310dd49bd865343bd816dbb8c475f4eb9ecc98af
BLAKE2b-256 checksum
How to use checksums
ba42ffb19c222a8d933d719022b87f9dbd196436c4f958e4a48006f08fafaa5c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.13.2 {"installer":{"name":"uv","version":"0.13.2","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}

Release files / spacify-0.2.0-py3-none-macosx_11_0_arm64.whl

Download URL spacify-0.2.0-py3-none-macosx_11_0_arm64.whl
Size 1.1 MB
Tags Python 3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
9a47ea5539053cb1589f264252bf6e843898ccc5f97d8a00b0a47f047a507cc9
BLAKE2b-256 checksum
How to use checksums
c3b9a9a8d6ff4cce6218666d179f3ea490366c1b189406828299d93d19a0e8c1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.13.2 {"installer":{"name":"uv","version":"0.13.2","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}

Release files / spacify-0.2.0-py3-none-macosx_10_12_x86_64.whl

Download URL spacify-0.2.0-py3-none-macosx_10_12_x86_64.whl
Size 1.2 MB
Tags Python 3 macOS 10.12+ x86-64
SHA-256 checksum
How to use checksums
99910246fdf5c5991bbf3ee2ff56ffff996f578bc41458626ca4598668212a97
BLAKE2b-256 checksum
How to use checksums
6cd32c7fa78f9582925bc28aac04aefff2dfc2b8b577e1378e81367a51939258
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.13.2 {"installer":{"name":"uv","version":"0.13.2","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}

Security for spacify 0.2.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page