spacify 0.1.0__py3-none-win_amd64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
Binary file
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: spacify
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Classifier: Development Status :: 3 - Alpha
|
|
5
|
+
Classifier: Environment :: Console
|
|
6
|
+
Classifier: Intended Audience :: Developers
|
|
7
|
+
Classifier: Programming Language :: Python
|
|
8
|
+
Classifier: Programming Language :: Rust
|
|
9
|
+
Classifier: Topic :: Software Development :: Quality Assurance
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Summary: A fast formatter for the vertical rhythm of Python code, complementary to ruff
|
|
12
|
+
Keywords: python,formatter,blank-lines,ruff,pre-commit
|
|
13
|
+
License-Expression: MIT
|
|
14
|
+
Requires-Python: >=3.9
|
|
15
|
+
Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
|
|
16
|
+
Project-URL: Changelog, https://github.com/avanserv/spacify/blob/main/CHANGELOG.md
|
|
17
|
+
Project-URL: Repository, https://github.com/avanserv/spacify
|
|
18
|
+
|
|
19
|
+
# spacify
|
|
20
|
+
|
|
21
|
+
[](https://github.com/avanserv/spacify/actions/workflows/ci.yml)
|
|
22
|
+
[](https://pypi.org/project/spacify/)
|
|
23
|
+
|
|
24
|
+
A fast formatter for the vertical rhythm of Python code. `ruff format` decides how a statement is
|
|
25
|
+
laid out, but leaves most of the blank lines between statements up to you. spacify fills that gap:
|
|
26
|
+
it puts air around logical blocks and tightens runs of related statements, and it only touches the
|
|
27
|
+
blank lines between statements.
|
|
28
|
+
|
|
29
|
+
Before:
|
|
30
|
+
|
|
31
|
+
```python
|
|
32
|
+
def load(paths):
|
|
33
|
+
seen = set()
|
|
34
|
+
for path in paths:
|
|
35
|
+
if path in seen:
|
|
36
|
+
continue
|
|
37
|
+
seen.add(path)
|
|
38
|
+
total = len(seen)
|
|
39
|
+
|
|
40
|
+
count = 0
|
|
41
|
+
log(total)
|
|
42
|
+
return total
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
After `spacify`:
|
|
46
|
+
|
|
47
|
+
```python
|
|
48
|
+
def load(paths):
|
|
49
|
+
seen = set()
|
|
50
|
+
|
|
51
|
+
for path in paths:
|
|
52
|
+
if path in seen:
|
|
53
|
+
continue
|
|
54
|
+
|
|
55
|
+
seen.add(path)
|
|
56
|
+
|
|
57
|
+
total = len(seen)
|
|
58
|
+
count = 0
|
|
59
|
+
log(total)
|
|
60
|
+
|
|
61
|
+
return total
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
spacify never fights ruff. Every rule stays inside the blank-line bounds `ruff format` keeps, and
|
|
65
|
+
CI runs both tools over CPython's standard library in both orders to check they reach a fixed point.
|
|
66
|
+
Checking all of CPython's `Lib` takes under half a second on 8 cores.
|
|
67
|
+
|
|
68
|
+
## Install
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
uv tool install spacify # or: pipx install spacify, pip install spacify
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Use with prek or pre-commit
|
|
75
|
+
|
|
76
|
+
Put the hook after `ruff-format`, so spacify sees ruff's line wrapping:
|
|
77
|
+
|
|
78
|
+
```yaml
|
|
79
|
+
repos:
|
|
80
|
+
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
81
|
+
rev: v0.16.9
|
|
82
|
+
hooks:
|
|
83
|
+
- id: ruff-format
|
|
84
|
+
- repo: https://github.com/avanserv/spacify-pre-commit
|
|
85
|
+
rev: v0.1.0
|
|
86
|
+
hooks:
|
|
87
|
+
- id: spacify
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
The hook installs the prebuilt wheel from PyPI, so you don't need a Rust toolchain.
|
|
91
|
+
|
|
92
|
+
## Command line
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
spacify # format every Python file under the current directory
|
|
96
|
+
spacify src/ tests/a.py # format these paths
|
|
97
|
+
spacify --check # write nothing; exit 1 if any file would change
|
|
98
|
+
spacify --diff # write nothing; print a unified diff
|
|
99
|
+
spacify - < a.py # read stdin, write stdout (--stdin-filename names it)
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
The exit code is 0 on success, 1 when `--check` or `--diff` found changes, and 2 on an error such as
|
|
103
|
+
a syntax error, in which case the file is left untouched. Directory walks respect `.gitignore` and
|
|
104
|
+
skip the directories ruff skips by default. A file you name explicitly is always formatted, unless
|
|
105
|
+
you also pass `--force-exclude`, which is what the hook does.
|
|
106
|
+
|
|
107
|
+
## Rules
|
|
108
|
+
|
|
109
|
+
Each rule can be turned on or off. They all apply to sibling statements in the same block.
|
|
110
|
+
|
|
111
|
+
| Rule | Effect |
|
|
112
|
+
| --- | --- |
|
|
113
|
+
| `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. |
|
|
114
|
+
| `blank-after-block` | At least one blank line after one of those blocks, before the next statement. |
|
|
115
|
+
| `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. |
|
|
116
|
+
| `collapse-groups` | No blank line between two single-line statements of the same kind: assignments, augmented assignments, calls, `del`, `assert`, `global`/`nonlocal`. |
|
|
117
|
+
|
|
118
|
+
The added blank lines take priority over `collapse-groups`. A few places are never touched:
|
|
119
|
+
|
|
120
|
+
- Gaps next to a `def` or `class`, after an `import`, or after a docstring. Ruff decides these.
|
|
121
|
+
- Blank lines that have a comment in the gap, because a comment marks a paragraph you meant. When a
|
|
122
|
+
rule does add a blank line, it goes above the comments that belong to the next statement.
|
|
123
|
+
- Regions between `# fmt: off` and `# fmt: on` (or `# spacify: off` and `# spacify: on`), and any
|
|
124
|
+
line marked `# fmt: skip`.
|
|
125
|
+
|
|
126
|
+
Imports are never collapsed, because ruff's isort rules separate import sections with blank lines.
|
|
127
|
+
A nested block never gets more than one blank line in a row. At module level the limit is two, or one
|
|
128
|
+
in a `.pyi` stub.
|
|
129
|
+
|
|
130
|
+
## Configuration
|
|
131
|
+
|
|
132
|
+
spacify reads `[tool.spacify]` from `pyproject.toml`, or the top level of a `spacify.toml` or
|
|
133
|
+
`.spacify.toml`. It uses the first one it finds walking up from the current directory, or the file
|
|
134
|
+
you pass with `--config`.
|
|
135
|
+
|
|
136
|
+
```toml
|
|
137
|
+
[tool.spacify]
|
|
138
|
+
extend-exclude = ["generated", "migrations/*.py"] # `exclude = [...]` replaces the defaults
|
|
139
|
+
|
|
140
|
+
[tool.spacify.rules]
|
|
141
|
+
blank-before-block = true
|
|
142
|
+
blank-after-block = true
|
|
143
|
+
blank-before-exit = true
|
|
144
|
+
exit-min-block-statements = 3
|
|
145
|
+
collapse-groups = true
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
An exclude pattern containing a `/` matches the path relative to the config file. Any other pattern
|
|
149
|
+
matches a single file or directory name.
|
|
150
|
+
|
|
151
|
+
## Contributing
|
|
152
|
+
|
|
153
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md).
|
|
154
|
+
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
spacify-0.1.0.data/scripts/spacify.exe,sha256=sFuRUly_z340OOXhSkkyUGQhvSlICNNOd8ih3GFSggA,2858496
|
|
2
|
+
spacify-0.1.0.dist-info/METADATA,sha256=lB_GlWg6cgUW4b3CeT68FbGIIf5q_Tl-n1qS-Gahqbw,5646
|
|
3
|
+
spacify-0.1.0.dist-info/WHEEL,sha256=8Aej0W0a6Cz6apA3IzJrTnxLRVLAt-w0Oh8SA3Con_c,94
|
|
4
|
+
spacify-0.1.0.dist-info/licenses/LICENSE,sha256=huA5Cm2O3t3c2YDNjTrXfcwIbbF7s1VlVR_YGtNsuO4,1086
|
|
5
|
+
spacify-0.1.0.dist-info/sboms/spacify.cyclonedx.json,sha256=RdtJRysZTJO47quYeYZp4de8EF5AdzhJCA1X9voNT68,73270
|
|
6
|
+
spacify-0.1.0.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Avanserv
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|