Skip to main content

A tool to format SQL code in Jupyter notebooks and Marimo notebooks.

Project description

sqlnbfmt

PyPI Tests License Python Versions

Quick start: pip install sqlnbfmt && sqlnbfmt notebook.ipynb

A SQL formatter for Jupyter Notebooks and Marimo notebooks. sqlnbfmt automatically formats SQL queries embedded in notebook cells — Python strings, SQL magic cells (%%sql), and Marimo mo.sql() calls — helping you maintain clean and consistent code.

Features

  • Zero-config: Works out of the box with sensible defaults — no config file needed
  • Jupyter + Marimo: Formats SQL in .ipynb notebooks and Marimo .py notebooks
  • Smart SQL Detection: Automatically identifies and formats SQL queries in code cells, magic SQL cells, and mo.sql() calls
  • AST-Powered: Uses Abstract Syntax Tree parsing for accurate SQL string identification
  • Safe Formatting: Preserves Python comments, query parameters (e.g., %s, ?), f-string placeholders, and SQL comments
  • CI-Friendly: --check mode exits non-zero when formatting is needed; --diff shows what would change
  • Skip Hints: Add # sqlnbfmt: skip to any cell to exclude it from formatting
  • Pre-commit Ready: Seamlessly integrates with pre-commit hooks
  • JupyterLab Plugin: Works with jupyterlab-code-formatter for interactive format-on-save
  • Lightweight: Only three runtime dependencies (sqlglot, nbformat, pyyaml)

Installation

pip install sqlnbfmt

Usage

Command Line

Format Jupyter notebooks:

sqlnbfmt path/to/your_notebook.ipynb

Format Marimo notebooks (or any Python file with SQL strings):

sqlnbfmt path/to/your_notebook.py

Mix both in a single invocation:

sqlnbfmt *.ipynb marimo_app.py

Check formatting without modifying files (useful in CI):

sqlnbfmt --check path/to/your_notebook.ipynb path/to/marimo_app.py

Show a diff of what would change:

sqlnbfmt --diff path/to/your_notebook.ipynb

Skipping Cells

Add a # sqlnbfmt: skip comment to skip formatting. In Jupyter notebooks this applies per-cell; in Python files it applies to the entire file.

# sqlnbfmt: skip
query = "select * from my_special_table where id = 1"

JupyterLab Integration

Format SQL cells interactively with jupyterlab-code-formatter:

pip install sqlnbfmt jupyterlab-code-formatter

That's it — sqlnbfmt auto-registers as a Jupyter server extension. In JupyterLab, use Edit > Format Cell or configure format-on-save in Settings > Code Formatter, and select "Apply SQL Notebook Formatter".

To customize the dialect, add this to ~/.jupyter/jupyter_server_config.py:

from sqlnbfmt.jupyterlab_integration import register
register(dialect="postgres")

Pre-commit Integration

  1. Install pre-commit:
pip install pre-commit
  1. Add to .pre-commit-config.yaml:
repos:
  - repo: https://github.com/flyersworder/sqlnbfmt
    rev: v0.4.0
    hooks:
      - id: sqlnbfmt
        types: [jupyter]

To also format Marimo notebooks (Python files), add the Python hook:

      - id: sqlnbfmt-py
        files: '\.py$'  # optionally narrow with: files: 'marimo_.*\.py$'

All arguments are optional. To specify a dialect or custom config:

        args: [--dialect, postgres, --config, config.yaml]
  1. Install the hook:
pre-commit install
  1. (Optional) Run on all files:
pre-commit run --all-files

CI Usage

Use --check in GitHub Actions to enforce formatting:

- name: Check SQL notebook formatting
  run: |
    pip install sqlnbfmt
    sqlnbfmt --check **/*.ipynb
    sqlnbfmt --check marimo_*.py  # if using Marimo

Configuration

sqlnbfmt 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.

Configuration Options

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

Examples

Jupyter Notebook

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
""")

Marimo Notebook

Before formatting:

@app.cell
def _(mo):
    _df = mo.sql(f"select id, name from users where active = 1 order by name")
    return

After formatting:

@app.cell
def _(mo):
    _df = mo.sql(
    f"""
    SELECT
      id,
      name
    FROM users
    WHERE
      active = 1
    ORDER BY
      name
    """
)
    return

Troubleshooting

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 --config to 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 rev matches the installed version
  • Run pre-commit autoupdate to get the latest version

Contributing

We welcome contributions! Here's how to get started:

  1. Clone the repository:
git clone https://github.com/flyersworder/sqlnbfmt.git
cd sqlnbfmt
  1. Use uv to sync the environment:
uv sync
source .venv/bin/activate  # On Windows: .venv\Scripts\activate
  1. Run tests:
pytest
  1. Add eval cases: see tests/eval/generate_fixtures.py for examples. Run python tests/eval/generate_fixtures.py to regenerate fixtures.

  2. Install dev pre-commit hooks:

pre-commit install

License

This project is licensed under the MIT License - see the LICENSE file for details.

Acknowledgments

  • sqlglot - SQL parsing and formatting engine
  • All contributors and early adopters who helped shape this tool

Made with ♥️ by the sqlnbfmt team

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

sqlnbfmt-0.4.2.tar.gz (56.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

sqlnbfmt-0.4.2-py3-none-any.whl (13.8 kB view details)

Uploaded Python 3

File details

Details for the file sqlnbfmt-0.4.2.tar.gz.

File metadata

  • Download URL: sqlnbfmt-0.4.2.tar.gz
  • Upload date:
  • Size: 56.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for sqlnbfmt-0.4.2.tar.gz
Algorithm Hash digest
SHA256 3c1ed37941f120c569778272660fefdc1908b58e33fadf79bffa20450a6d980c
MD5 f3ed2dfbbeb1e1310b3eda7ab9e07ab5
BLAKE2b-256 06adb32e3ba40adc00250d3611a70bed4f3135bd18d3d47dde8048e5a907da97

See more details on using hashes here.

Provenance

The following attestation bundles were made for sqlnbfmt-0.4.2.tar.gz:

Publisher: ci-and-publish.yml on flyersworder/sqlnbfmt

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file sqlnbfmt-0.4.2-py3-none-any.whl.

File metadata

  • Download URL: sqlnbfmt-0.4.2-py3-none-any.whl
  • Upload date:
  • Size: 13.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for sqlnbfmt-0.4.2-py3-none-any.whl
Algorithm Hash digest
SHA256 b98402c2bed9c66e54877c349afe612ef5470e33998d92615520d373e6b75430
MD5 03cdfafd98c0e64ccd92360331e30259
BLAKE2b-256 1bb3786ff8b621b7d86662f16bfd67741538102a21fe46ca3da21351316afc4f

See more details on using hashes here.

Provenance

The following attestation bundles were made for sqlnbfmt-0.4.2-py3-none-any.whl:

Publisher: ci-and-publish.yml on flyersworder/sqlnbfmt

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page