A Python code formatter with custom formatting rules that complement Ruff. Pyhone focuses on stylistic rules that go beyond what typical formatters handle.
- Multiline Spacing Rule: Automatically ensures multi-line statements (3+ lines by default) have blank lines before and after them for better readability
- Format Mode: Automatically fix formatting issues
- Check Mode: Report violations without modifying files (useful for CI/CD)
- GitHub Actions Integration: Output violations in GitHub Actions annotation format
- Configurable: Customize rules via
pyhone.toml - Fast: Built in Rust for maximum performance
cargo build --releaseThe binary will be available at target/release/pyhone.
Apply fixes to Python files:
pyhone file.pyReport violations without fixing:
pyhone --check file.pypyhone file1.py file2.py file3.pyHuman-readable (default):
pyhone --format human --check file.pyGitHub Actions:
pyhone --format github --check file.pySpecify a custom config file:
pyhone --config my-config.toml file.pyCreate a pyhone.toml file in your project root:
[rules.multiline-spacing]
# Enable/disable the multiline-spacing rule
enabled = true
# Minimum number of lines for a statement to be considered "multi-line"
# Default: 2
min_lines = 2Ensures multi-line statements have blank lines before and after them for improved readability.
Example:
Before:
x = 1
def foo():
a = 1
b = 2
c = 3
d = 4
y = 2After:
x = 1
def foo():
a = 1
b = 2
c = 3
d = 4
y = 2Use Pyhone in your GitHub Actions workflow:
name: Code Quality
on: [push, pull_request]
jobs:
formatting:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Install Rust
uses: actions-rs/toolchain@v1
with:
toolchain: stable
- name: Build Pyhone
run: cargo build --release
- name: Check Python formatting
run: |
find . -name "*.py" -exec ./target/release/pyhone --check --format github {} +This will automatically annotate your PRs with formatting issues.
Pyhone is designed to complement Ruff, not replace it. Use Ruff for:
- Import sorting
- Code linting
- Standard formatting rules
Use Pyhone for:
- Custom spacing rules
- Project-specific style enforcement
Example workflow:
# Run Ruff first
ruff check --fix .
ruff format .
# Then run Pyhone
pyhone **/*.pycargo testpyhone/
├── src/
│ ├── main.rs # CLI with clap
│ ├── parser.rs # Python AST parsing
│ ├── config.rs # TOML config loading
│ ├── formatter.rs # Orchestrate rules on source code
│ ├── output.rs # Output formatters (human, github)
│ └── rules/
│ ├── mod.rs # Rule trait + registry
│ └── multiline_spacing.rs
└── pyhone.toml # Example config file
- Create a new file in
src/rules/(e.g.,my_rule.rs) - Implement the
FormattingRuletrait:
use crate::rules::{FormattingRule, Violation};
use anyhow::Result;
use rustpython_parser::ast::Mod;
pub struct MyRule;
impl FormattingRule for MyRule {
fn name(&self) -> &str {
"my-rule"
}
fn description(&self) -> &str {
"Description of my rule"
}
fn apply(&self, source: &str, ast: &Mod) -> Result<Vec<Violation>> {
// Your rule logic here
Ok(Vec::new())
}
}- Register the rule in
src/rules/mod.rs - Add configuration in
src/config.rs - Update the formatter in
src/formatter.rsto use your rule
MIT
Contributions are welcome! Please feel free to submit a Pull Request.