Quick start:
pip install sqlnbfmt && sqlnbfmt notebook.ipynb
A SQL formatter designed specifically for Jupyter Notebooks. sqlnbfmt automatically formats SQL queries embedded in code cells, including both Python strings and SQL magic cells (%%sql), helping you maintain clean and consistent code.
- Zero-config: Works out of the box with sensible defaults — no config file needed
- Smart SQL Detection: Automatically identifies and formats SQL queries in code cells and magic SQL cells
- AST-Powered: Uses Abstract Syntax Tree parsing for accurate SQL string identification
- Safe Formatting: Preserves Python comments, query parameters (e.g.,
%s,?), and SQL comments - CI-Friendly:
--checkmode exits non-zero when formatting is needed;--diffshows what would change - Skip Hints: Add
# sqlnbfmt: skipto any cell to exclude it from formatting - Pre-commit Ready: Seamlessly integrates with pre-commit hooks
- Lightweight: Only three runtime dependencies (sqlglot, nbformat, pyyaml)
pip install sqlnbfmtFormat a single notebook:
sqlnbfmt path/to/your_notebook.ipynbCheck formatting without modifying files (useful in CI):
sqlnbfmt --check path/to/your_notebook.ipynbShow a diff of what would change:
sqlnbfmt --diff path/to/your_notebook.ipynbAdd a # sqlnbfmt: skip comment anywhere in a cell to skip formatting:
# sqlnbfmt: skip
query = "select * from my_special_table where id = 1"- Install pre-commit:
pip install pre-commit- Add to
.pre-commit-config.yaml:
repos:
- repo: https://github.com/flyersworder/sqlnbfmt
rev: v0.3.0
hooks:
- id: sqlnbfmt
types: [jupyter]All arguments are optional. To specify a dialect or custom config:
args: [--dialect, postgres, --config, config.yaml]- Install the hook:
pre-commit install- (Optional) Run on all files:
pre-commit run --all-filesUse --check in GitHub Actions to enforce formatting:
- name: Check SQL notebook formatting
run: |
pip install sqlnbfmt
sqlnbfmt --check **/*.ipynbsqlnbfmt works without any configuration file. A config.yaml is only needed to override defaults.
Create a config.yaml file to customize formatting behavior. Here is a template.
| Option | Description | Default |
|---|---|---|
sql_keywords |
SQL keywords to recognize and format | Common SQL keywords |
function_names |
Python functions containing SQL code | read_sql, execute, etc. |
sql_decorators |
Decorators indicating SQL code | query, sql_query, etc. |
single_line_threshold |
Maximum length before splitting SQL | 80 |
indent_width |
Number of spaces for indentation | 4 |
Before formatting:
execute_sql("""SELECT a.col1, b.col2 FROM table_a a JOIN table_b b ON a.id = b.a_id WHERE a.status = 'active' ORDER BY a.created_at DESC""")After formatting:
execute_sql("""
SELECT
a.col1,
b.col2
FROM
table_a AS a
JOIN
table_b AS b
ON a.id = b.a_id
WHERE
a.status = 'active'
ORDER BY
a.created_at DESC
""")SQL not being formatted?
- Ensure the string contains at least 2 SQL keywords or a recognizable pattern like
SELECT...FROM - Check that the function name is in the recognized list (use
--configto add custom ones)
Comments being modified?
- Python comments (
#) are preserved. SQL comments (--) inside strings are converted to/* */block comments by sqlglot.
Pre-commit hook fails?
- Make sure the
revmatches the installed version - Run
pre-commit autoupdateto get the latest version
We welcome contributions! Here's how to get started:
- Clone the repository:
git clone https://github.com/flyersworder/sqlnbfmt.git
cd sqlnbfmt- Use
uvto sync the environment:
uv sync
source .venv/bin/activate # On Windows: .venv\Scripts\activate- Run tests:
pytest-
Add eval cases: see
tests/eval/generate_fixtures.pyfor examples. Runpython tests/eval/generate_fixtures.pyto regenerate fixtures. -
Install dev pre-commit hooks:
pre-commit installThis project is licensed under the MIT License - see the LICENSE file for details.
- sqlglot - SQL parsing and formatting engine
- All contributors and early adopters who helped shape this tool
Made with