# blank-line-after-blocks
A Python formatter to automatically add blank lines after if/for/while/with/try
blocks to improve code readability.
## Installation
```bash
pip install blank-line-after-blocks
```
## Usage
### Command Line
```bash
# Format Python files
blank-line-after-blocks file1.py file2.py
# Format with exclude patterns (regex - use | for multiple patterns)
blank-line-after-blocks --exclude "tests/|_generated\.py$" src/
# Format Jupyter notebooks
blank-line-after-blocks-jupyter notebook1.ipynb notebook2.ipynb
# Format notebooks with exclude patterns (regex)
blank-line-after-blocks-jupyter --exclude "notebooks/generated/" notebooks/
```
### Pre-commit Hook
Add this to your `.pre-commit-config.yaml`:
```yaml
repos:
- repo: https://github.com/jsh9/blank-line-after-blocks
rev: <LATEST_TAG>
hooks:
- id: blank-line-after-blocks
- id: blank-line-after-blocks-jupyter
```
#### Pre-commit with exclude patterns
```yaml
repos:
- repo: https://github.com/jsh9/blank-line-after-blocks
rev: <LATEST_TAG>
hooks:
- id: blank-line-after-blocks
args: ["--exclude", "tests/|_generated\.py$"]
- id: blank-line-after-blocks-jupyter
args: ["--exclude", "notebooks/generated/"]
```
### Configuration File
You can also configure exclude patterns in `pyproject.toml`:
```toml
[tool.blank-line-after-blocks]
exclude = [
"tests/", # Exclude all files in tests directory
"_generated\.py$", # Exclude files ending with _generated.py
"vendor/", # Exclude all files in vendor directory
"build/", # Exclude build directory
]
```
**Note**: CLI `--exclude` options take precedence over configuration file
settings.
## What it does
This tool automatically adds one blank line after the end of:
- `if` statements
- `for` loops
- `while` loops
- `with` statements
- `try`/`except`/`finally` blocks
This improves code readability by providing visual separation between blocks
and subsequent code.
## Examples
### Basic if and for blocks
```diff
if condition:
do_something()
+
next_statement()
for item in items:
process(item)
+
final_step()
if a > 3:
print('a > 3')
# Already a comment; no new line added
a += 2
```
### Try/except blocks with context managers
```diff
def process_files(filenames):
results = []
for filename in filenames:
try:
with open(filename) as f:
data = json.load(f)
+
results.append(data)
except FileNotFoundError:
print(f'File {filename} not found')
except json.JSONDecodeError:
print(f'Invalid JSON in {filename}')
+
return results
```
### Nested blocks in class methods
```diff
class TestClass:
def method(self):
try:
if self.condition():
with self.get_context():
self.do_work()
+
self.cleanup()
+
except Exception as e:
self.handle_error(e)
+
print('method complete')
```
### Compound blocks stay tight (no blank line before else/elif/except/finally)
If a block ends right before the second part of compound blocks (if/else,
try/except, etc.), no blank line is added:
```python
for item in items:
if found(item):
break
else:
not_found()
```
Raw data
{
"_id": null,
"home_page": null,
"name": "blank-line-after-blocks",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.10",
"maintainer_email": "Your Name <your.email@example.com>",
"keywords": "formatter, code-style, blank-lines, python",
"author": null,
"author_email": "Your Name <your.email@example.com>",
"download_url": "https://files.pythonhosted.org/packages/1c/11/188cc43fff820b6292db86bbd796fd9079dd4caca6af86ac11f508858985/blank_line_after_blocks-0.1.4.tar.gz",
"platform": null,
"description": "# blank-line-after-blocks\n\nA Python formatter to automatically add blank lines after if/for/while/with/try\nblocks to improve code readability.\n\n## Installation\n\n```bash\npip install blank-line-after-blocks\n```\n\n## Usage\n\n### Command Line\n\n```bash\n# Format Python files\nblank-line-after-blocks file1.py file2.py\n\n# Format with exclude patterns (regex - use | for multiple patterns)\nblank-line-after-blocks --exclude \"tests/|_generated\\.py$\" src/\n\n# Format Jupyter notebooks\nblank-line-after-blocks-jupyter notebook1.ipynb notebook2.ipynb\n\n# Format notebooks with exclude patterns (regex)\nblank-line-after-blocks-jupyter --exclude \"notebooks/generated/\" notebooks/\n```\n\n### Pre-commit Hook\n\nAdd this to your `.pre-commit-config.yaml`:\n\n```yaml\nrepos:\n - repo: https://github.com/jsh9/blank-line-after-blocks\n rev: <LATEST_TAG>\n hooks:\n - id: blank-line-after-blocks\n - id: blank-line-after-blocks-jupyter\n```\n\n#### Pre-commit with exclude patterns\n\n```yaml\nrepos:\n - repo: https://github.com/jsh9/blank-line-after-blocks\n rev: <LATEST_TAG>\n hooks:\n - id: blank-line-after-blocks\n args: [\"--exclude\", \"tests/|_generated\\.py$\"]\n - id: blank-line-after-blocks-jupyter\n args: [\"--exclude\", \"notebooks/generated/\"]\n```\n\n### Configuration File\n\nYou can also configure exclude patterns in `pyproject.toml`:\n\n```toml\n[tool.blank-line-after-blocks]\nexclude = [\n \"tests/\", # Exclude all files in tests directory\n \"_generated\\.py$\", # Exclude files ending with _generated.py\n \"vendor/\", # Exclude all files in vendor directory\n \"build/\", # Exclude build directory\n]\n```\n\n**Note**: CLI `--exclude` options take precedence over configuration file\nsettings.\n\n## What it does\n\nThis tool automatically adds one blank line after the end of:\n\n- `if` statements\n- `for` loops\n- `while` loops\n- `with` statements\n- `try`/`except`/`finally` blocks\n\nThis improves code readability by providing visual separation between blocks\nand subsequent code.\n\n## Examples\n\n### Basic if and for blocks\n\n```diff\n if condition:\n do_something()\n+\n next_statement()\n\n for item in items:\n process(item)\n+\n final_step()\n\n if a > 3:\n print('a > 3')\n # Already a comment; no new line added\n a += 2\n```\n\n### Try/except blocks with context managers\n\n```diff\n def process_files(filenames):\n results = []\n for filename in filenames:\n try:\n with open(filename) as f:\n data = json.load(f)\n+\n results.append(data)\n except FileNotFoundError:\n print(f'File {filename} not found')\n except json.JSONDecodeError:\n print(f'Invalid JSON in {filename}')\n+\n return results\n```\n\n### Nested blocks in class methods\n\n```diff\n class TestClass:\n def method(self):\n try:\n if self.condition():\n with self.get_context():\n self.do_work()\n+\n self.cleanup()\n+\n except Exception as e:\n self.handle_error(e)\n+\n print('method complete')\n```\n\n### Compound blocks stay tight (no blank line before else/elif/except/finally)\n\nIf a block ends right before the second part of compound blocks (if/else,\ntry/except, etc.), no blank line is added:\n\n```python\nfor item in items:\n if found(item):\n break\nelse:\n not_found()\n```\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "A Python formatter to automatically add blank lines after if/for/while/with/try blocks",
"version": "0.1.4",
"project_urls": {
"Changelog": "https://github.com/jsh9/blank-line-after-blocks/blob/main/CHANGELOG.md",
"Homepage": "https://github.com/jsh9/blank-line-after-blocks",
"Issues": "https://github.com/jsh9/blank-line-after-blocks/issues",
"Repository": "https://github.com/jsh9/blank-line-after-blocks.git"
},
"split_keywords": [
"formatter",
" code-style",
" blank-lines",
" python"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "79deb25edbae61a06e28440f39194541430dcd5d7ab194e13844f305a2425284",
"md5": "309ef19c0c9cd67ac662033f9e81df0b",
"sha256": "a920744aefb0969155074a5bff6db183fa76271f385a2245ed21ab362761f615"
},
"downloads": -1,
"filename": "blank_line_after_blocks-0.1.4-py3-none-any.whl",
"has_sig": false,
"md5_digest": "309ef19c0c9cd67ac662033f9e81df0b",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.10",
"size": 9449,
"upload_time": "2025-09-04T04:07:23",
"upload_time_iso_8601": "2025-09-04T04:07:23.501897Z",
"url": "https://files.pythonhosted.org/packages/79/de/b25edbae61a06e28440f39194541430dcd5d7ab194e13844f305a2425284/blank_line_after_blocks-0.1.4-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "1c11188cc43fff820b6292db86bbd796fd9079dd4caca6af86ac11f508858985",
"md5": "3679bd231e4a15e9ecf3ca4d4f869e69",
"sha256": "3b7b9ef3a3c298c52d718c87f99eada30a75d1792150d8bacf924436c5ffe884"
},
"downloads": -1,
"filename": "blank_line_after_blocks-0.1.4.tar.gz",
"has_sig": false,
"md5_digest": "3679bd231e4a15e9ecf3ca4d4f869e69",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.10",
"size": 32016,
"upload_time": "2025-09-04T04:07:24",
"upload_time_iso_8601": "2025-09-04T04:07:24.646353Z",
"url": "https://files.pythonhosted.org/packages/1c/11/188cc43fff820b6292db86bbd796fd9079dd4caca6af86ac11f508858985/blank_line_after_blocks-0.1.4.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-09-04 04:07:24",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "jsh9",
"github_project": "blank-line-after-blocks",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"tox": true,
"lcname": "blank-line-after-blocks"
}