sqlnbfmt 0.4.0__tar.gz → 0.4.2__tar.gz
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.
- sqlnbfmt-0.4.2/.github/workflows/ci-and-publish.yml +42 -0
- sqlnbfmt-0.4.2/.gitignore +163 -0
- sqlnbfmt-0.4.2/.pre-commit-config.yaml +41 -0
- sqlnbfmt-0.4.2/.pre-commit-hooks.yaml +35 -0
- sqlnbfmt-0.4.2/.python-version +1 -0
- sqlnbfmt-0.4.2/CHANGELOG.md +143 -0
- {sqlnbfmt-0.4.0/sqlnbfmt.egg-info → sqlnbfmt-0.4.2}/PKG-INFO +25 -9
- {sqlnbfmt-0.4.0 → sqlnbfmt-0.4.2}/README.md +17 -0
- sqlnbfmt-0.4.2/config.yaml +49 -0
- sqlnbfmt-0.4.2/jupyter-config/sqlnbfmt.json +7 -0
- {sqlnbfmt-0.4.0 → sqlnbfmt-0.4.2}/pyproject.toml +6 -6
- sqlnbfmt-0.4.2/sqlnbfmt/__init__.py +15 -0
- {sqlnbfmt-0.4.0 → sqlnbfmt-0.4.2}/sqlnbfmt/formatter.py +89 -92
- sqlnbfmt-0.4.2/sqlnbfmt/jupyterlab_integration.py +74 -0
- sqlnbfmt-0.4.2/tests/eval/README.md +103 -0
- sqlnbfmt-0.4.2/tests/eval/basic_select/expected.ipynb +26 -0
- sqlnbfmt-0.4.2/tests/eval/basic_select/input.ipynb +17 -0
- sqlnbfmt-0.4.2/tests/eval/case_expression/expected.ipynb +22 -0
- sqlnbfmt-0.4.2/tests/eval/case_expression/input.ipynb +17 -0
- sqlnbfmt-0.4.2/tests/eval/comment_preservation/expected.ipynb +27 -0
- sqlnbfmt-0.4.2/tests/eval/comment_preservation/input.ipynb +19 -0
- sqlnbfmt-0.4.2/tests/eval/cte/expected.ipynb +29 -0
- sqlnbfmt-0.4.2/tests/eval/cte/input.ipynb +17 -0
- sqlnbfmt-0.4.2/tests/eval/fstring_variables/expected.ipynb +42 -0
- sqlnbfmt-0.4.2/tests/eval/fstring_variables/input.ipynb +30 -0
- sqlnbfmt-0.4.2/tests/eval/generate_fixtures.py +306 -0
- sqlnbfmt-0.4.2/tests/eval/group_by_having/expected.ipynb +29 -0
- sqlnbfmt-0.4.2/tests/eval/group_by_having/input.ipynb +17 -0
- sqlnbfmt-0.4.2/tests/eval/idempotency/expected.ipynb +24 -0
- sqlnbfmt-0.4.2/tests/eval/idempotency/input.ipynb +24 -0
- sqlnbfmt-0.4.2/tests/eval/in_function_sql/expected.ipynb +44 -0
- sqlnbfmt-0.4.2/tests/eval/in_function_sql/input.ipynb +27 -0
- sqlnbfmt-0.4.2/tests/eval/joins/expected.ipynb +27 -0
- sqlnbfmt-0.4.2/tests/eval/joins/input.ipynb +17 -0
- sqlnbfmt-0.4.2/tests/eval/magic_commands/expected.ipynb +50 -0
- sqlnbfmt-0.4.2/tests/eval/magic_commands/input.ipynb +40 -0
- sqlnbfmt-0.4.2/tests/eval/marimo_basic_sql/expected.py +31 -0
- sqlnbfmt-0.4.2/tests/eval/marimo_basic_sql/input.py +20 -0
- sqlnbfmt-0.4.2/tests/eval/marimo_comment_preservation/expected.py +50 -0
- sqlnbfmt-0.4.2/tests/eval/marimo_comment_preservation/input.py +30 -0
- sqlnbfmt-0.4.2/tests/eval/marimo_complex_sql/expected.py +63 -0
- sqlnbfmt-0.4.2/tests/eval/marimo_complex_sql/input.py +27 -0
- sqlnbfmt-0.4.2/tests/eval/marimo_fstring_interpolation/expected.py +47 -0
- sqlnbfmt-0.4.2/tests/eval/marimo_fstring_interpolation/input.py +28 -0
- sqlnbfmt-0.4.2/tests/eval/marimo_idempotency/expected.py +31 -0
- sqlnbfmt-0.4.2/tests/eval/marimo_idempotency/input.py +31 -0
- sqlnbfmt-0.4.2/tests/eval/marimo_multi_cell_mixed/expected.py +66 -0
- sqlnbfmt-0.4.2/tests/eval/marimo_multi_cell_mixed/input.py +44 -0
- sqlnbfmt-0.4.2/tests/eval/marimo_multi_statement/expected.py +34 -0
- sqlnbfmt-0.4.2/tests/eval/marimo_multi_statement/input.py +20 -0
- sqlnbfmt-0.4.2/tests/eval/marimo_non_sql_unchanged/expected.py +39 -0
- sqlnbfmt-0.4.2/tests/eval/marimo_non_sql_unchanged/input.py +39 -0
- sqlnbfmt-0.4.2/tests/eval/marimo_skip_hint/expected.py +21 -0
- sqlnbfmt-0.4.2/tests/eval/marimo_skip_hint/input.py +21 -0
- sqlnbfmt-0.4.2/tests/eval/multi_cell_mixed/expected.ipynb +76 -0
- sqlnbfmt-0.4.2/tests/eval/multi_cell_mixed/input.ipynb +65 -0
- sqlnbfmt-0.4.2/tests/eval/multi_statement/expected.ipynb +29 -0
- sqlnbfmt-0.4.2/tests/eval/multi_statement/input.ipynb +18 -0
- sqlnbfmt-0.4.2/tests/eval/non_sql_unchanged/expected.ipynb +44 -0
- sqlnbfmt-0.4.2/tests/eval/non_sql_unchanged/input.ipynb +44 -0
- sqlnbfmt-0.4.2/tests/eval/skip_hint/expected.ipynb +35 -0
- sqlnbfmt-0.4.2/tests/eval/skip_hint/input.ipynb +28 -0
- sqlnbfmt-0.4.2/tests/eval/subquery/expected.ipynb +29 -0
- sqlnbfmt-0.4.2/tests/eval/subquery/input.ipynb +17 -0
- sqlnbfmt-0.4.2/tests/eval/union/expected.ipynb +31 -0
- sqlnbfmt-0.4.2/tests/eval/union/input.ipynb +17 -0
- sqlnbfmt-0.4.2/tests/eval/window_function/expected.ipynb +23 -0
- sqlnbfmt-0.4.2/tests/eval/window_function/input.ipynb +17 -0
- {sqlnbfmt-0.4.0 → sqlnbfmt-0.4.2}/tests/test_formatter.py +53 -1
- sqlnbfmt-0.4.2/tests/test_jupyterlab_integration.py +76 -0
- sqlnbfmt-0.4.2/tests/test_notebook.ipynb +358 -0
- sqlnbfmt-0.4.2/tests/test_notebook_copy.ipynb +311 -0
- sqlnbfmt-0.4.2/uv.lock +455 -0
- sqlnbfmt-0.4.0/PKG-INFO +0 -270
- sqlnbfmt-0.4.0/setup.cfg +0 -4
- sqlnbfmt-0.4.0/sqlnbfmt.egg-info/SOURCES.txt +0 -14
- sqlnbfmt-0.4.0/sqlnbfmt.egg-info/dependency_links.txt +0 -1
- sqlnbfmt-0.4.0/sqlnbfmt.egg-info/entry_points.txt +0 -2
- sqlnbfmt-0.4.0/sqlnbfmt.egg-info/requires.txt +0 -3
- sqlnbfmt-0.4.0/sqlnbfmt.egg-info/top_level.txt +0 -1
- {sqlnbfmt-0.4.0 → sqlnbfmt-0.4.2}/LICENSE +0 -0
- {sqlnbfmt-0.4.0/sqlnbfmt → sqlnbfmt-0.4.2/tests}/__init__.py +0 -0
- {sqlnbfmt-0.4.0 → sqlnbfmt-0.4.2}/tests/test_eval.py +0 -0
- {sqlnbfmt-0.4.0 → sqlnbfmt-0.4.2}/tests/test_marimo.py +0 -0
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
name: Python CI and Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
release:
|
|
8
|
+
types: [created]
|
|
9
|
+
workflow_dispatch:
|
|
10
|
+
inputs:
|
|
11
|
+
run_publish:
|
|
12
|
+
description: 'Set to true to run the publish job'
|
|
13
|
+
required: false
|
|
14
|
+
default: 'false'
|
|
15
|
+
|
|
16
|
+
jobs:
|
|
17
|
+
test:
|
|
18
|
+
runs-on: ubuntu-latest
|
|
19
|
+
steps:
|
|
20
|
+
- uses: actions/checkout@v4
|
|
21
|
+
- uses: astral-sh/setup-uv@v3
|
|
22
|
+
with:
|
|
23
|
+
enable-cache: true
|
|
24
|
+
cache-dependency-glob: "pyproject.toml"
|
|
25
|
+
- run: uv python install 3.12
|
|
26
|
+
- run: uv sync --all-extras --dev
|
|
27
|
+
- run: uv run pytest
|
|
28
|
+
|
|
29
|
+
publish:
|
|
30
|
+
needs: test
|
|
31
|
+
if: github.event_name == 'release' || (github.event_name == 'workflow_dispatch' && github.event.inputs.run_publish == 'true')
|
|
32
|
+
runs-on: ubuntu-latest
|
|
33
|
+
permissions:
|
|
34
|
+
id-token: write
|
|
35
|
+
steps:
|
|
36
|
+
- uses: actions/checkout@v4
|
|
37
|
+
- uses: astral-sh/setup-uv@v3
|
|
38
|
+
with:
|
|
39
|
+
enable-cache: true
|
|
40
|
+
- run: uv python install 3.12
|
|
41
|
+
- run: uv build --no-sources
|
|
42
|
+
- uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
# Byte-compiled / optimized / DLL files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
|
|
6
|
+
# C extensions
|
|
7
|
+
*.so
|
|
8
|
+
|
|
9
|
+
# Distribution / packaging
|
|
10
|
+
.Python
|
|
11
|
+
build/
|
|
12
|
+
develop-eggs/
|
|
13
|
+
dist/
|
|
14
|
+
downloads/
|
|
15
|
+
eggs/
|
|
16
|
+
.eggs/
|
|
17
|
+
lib/
|
|
18
|
+
lib64/
|
|
19
|
+
parts/
|
|
20
|
+
sdist/
|
|
21
|
+
var/
|
|
22
|
+
wheels/
|
|
23
|
+
share/python-wheels/
|
|
24
|
+
*.egg-info/
|
|
25
|
+
.installed.cfg
|
|
26
|
+
*.egg
|
|
27
|
+
MANIFEST
|
|
28
|
+
|
|
29
|
+
# PyInstaller
|
|
30
|
+
# Usually these files are written by a python script from a template
|
|
31
|
+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
|
32
|
+
*.manifest
|
|
33
|
+
*.spec
|
|
34
|
+
|
|
35
|
+
# Installer logs
|
|
36
|
+
pip-log.txt
|
|
37
|
+
pip-delete-this-directory.txt
|
|
38
|
+
|
|
39
|
+
# Unit test / coverage reports
|
|
40
|
+
htmlcov/
|
|
41
|
+
.tox/
|
|
42
|
+
.nox/
|
|
43
|
+
.coverage
|
|
44
|
+
.coverage.*
|
|
45
|
+
.cache
|
|
46
|
+
nosetests.xml
|
|
47
|
+
coverage.xml
|
|
48
|
+
*.cover
|
|
49
|
+
*.py,cover
|
|
50
|
+
.hypothesis/
|
|
51
|
+
.pytest_cache/
|
|
52
|
+
cover/
|
|
53
|
+
|
|
54
|
+
# Translations
|
|
55
|
+
*.mo
|
|
56
|
+
*.pot
|
|
57
|
+
|
|
58
|
+
# Django stuff:
|
|
59
|
+
*.log
|
|
60
|
+
local_settings.py
|
|
61
|
+
db.sqlite3
|
|
62
|
+
db.sqlite3-journal
|
|
63
|
+
|
|
64
|
+
# Flask stuff:
|
|
65
|
+
instance/
|
|
66
|
+
.webassets-cache
|
|
67
|
+
|
|
68
|
+
# Scrapy stuff:
|
|
69
|
+
.scrapy
|
|
70
|
+
|
|
71
|
+
# Sphinx documentation
|
|
72
|
+
docs/_build/
|
|
73
|
+
|
|
74
|
+
# PyBuilder
|
|
75
|
+
.pybuilder/
|
|
76
|
+
target/
|
|
77
|
+
|
|
78
|
+
# Jupyter Notebook
|
|
79
|
+
.ipynb_checkpoints
|
|
80
|
+
|
|
81
|
+
# IPython
|
|
82
|
+
profile_default/
|
|
83
|
+
ipython_config.py
|
|
84
|
+
|
|
85
|
+
# pyenv
|
|
86
|
+
# For a library or package, you might want to ignore these files since the code is
|
|
87
|
+
# intended to run in multiple environments; otherwise, check them in:
|
|
88
|
+
# .python-version
|
|
89
|
+
|
|
90
|
+
# pipenv
|
|
91
|
+
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
|
92
|
+
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
|
93
|
+
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
|
94
|
+
# install all needed dependencies.
|
|
95
|
+
#Pipfile.lock
|
|
96
|
+
|
|
97
|
+
# poetry
|
|
98
|
+
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
|
99
|
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
100
|
+
# commonly ignored for libraries.
|
|
101
|
+
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
|
102
|
+
#poetry.lock
|
|
103
|
+
|
|
104
|
+
# pdm
|
|
105
|
+
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
|
106
|
+
#pdm.lock
|
|
107
|
+
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
|
|
108
|
+
# in version control.
|
|
109
|
+
# https://pdm.fming.dev/latest/usage/project/#working-with-version-control
|
|
110
|
+
.pdm.toml
|
|
111
|
+
.pdm-python
|
|
112
|
+
.pdm-build/
|
|
113
|
+
|
|
114
|
+
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
|
115
|
+
__pypackages__/
|
|
116
|
+
|
|
117
|
+
# Celery stuff
|
|
118
|
+
celerybeat-schedule
|
|
119
|
+
celerybeat.pid
|
|
120
|
+
|
|
121
|
+
# SageMath parsed files
|
|
122
|
+
*.sage.py
|
|
123
|
+
|
|
124
|
+
# Environments
|
|
125
|
+
.env
|
|
126
|
+
.venv
|
|
127
|
+
env/
|
|
128
|
+
venv/
|
|
129
|
+
ENV/
|
|
130
|
+
env.bak/
|
|
131
|
+
venv.bak/
|
|
132
|
+
|
|
133
|
+
# Spyder project settings
|
|
134
|
+
.spyderproject
|
|
135
|
+
.spyproject
|
|
136
|
+
|
|
137
|
+
# Rope project settings
|
|
138
|
+
.ropeproject
|
|
139
|
+
|
|
140
|
+
# mkdocs documentation
|
|
141
|
+
/site
|
|
142
|
+
|
|
143
|
+
# mypy
|
|
144
|
+
.mypy_cache/
|
|
145
|
+
.dmypy.json
|
|
146
|
+
dmypy.json
|
|
147
|
+
|
|
148
|
+
# Pyre type checker
|
|
149
|
+
.pyre/
|
|
150
|
+
|
|
151
|
+
# pytype static type analyzer
|
|
152
|
+
.pytype/
|
|
153
|
+
|
|
154
|
+
# Cython debug symbols
|
|
155
|
+
cython_debug/
|
|
156
|
+
|
|
157
|
+
# PyCharm
|
|
158
|
+
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
|
159
|
+
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
|
160
|
+
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
|
161
|
+
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
|
162
|
+
#.idea/
|
|
163
|
+
.DS_STORE
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
repos:
|
|
2
|
+
# Linting + formatting (Astral)
|
|
3
|
+
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
4
|
+
rev: v0.15.6
|
|
5
|
+
hooks:
|
|
6
|
+
- id: ruff
|
|
7
|
+
args: [--fix]
|
|
8
|
+
- id: ruff-format
|
|
9
|
+
|
|
10
|
+
# File quality + security
|
|
11
|
+
- repo: https://github.com/pre-commit/pre-commit-hooks
|
|
12
|
+
rev: v6.0.0
|
|
13
|
+
hooks:
|
|
14
|
+
- id: check-ast
|
|
15
|
+
- id: check-yaml
|
|
16
|
+
- id: check-toml
|
|
17
|
+
- id: check-json
|
|
18
|
+
- id: check-merge-conflict
|
|
19
|
+
- id: check-added-large-files
|
|
20
|
+
- id: debug-statements
|
|
21
|
+
- id: detect-private-key
|
|
22
|
+
- id: trailing-whitespace
|
|
23
|
+
- id: end-of-file-fixer
|
|
24
|
+
|
|
25
|
+
# Validate pyproject.toml against PEP 621
|
|
26
|
+
- repo: https://github.com/abravalheri/validate-pyproject
|
|
27
|
+
rev: v0.25
|
|
28
|
+
hooks:
|
|
29
|
+
- id: validate-pyproject
|
|
30
|
+
|
|
31
|
+
# Local hooks
|
|
32
|
+
- repo: local
|
|
33
|
+
hooks:
|
|
34
|
+
# Fast unit tests
|
|
35
|
+
- id: pytest-fast
|
|
36
|
+
name: pytest (fast)
|
|
37
|
+
entry: uv run pytest tests/ -x -q --timeout=10
|
|
38
|
+
language: system
|
|
39
|
+
types: [python]
|
|
40
|
+
pass_filenames: false
|
|
41
|
+
stages: [pre-push]
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
- id: sqlnbfmt
|
|
2
|
+
name: SQL Notebook Formatter
|
|
3
|
+
description: Format SQL queries in Jupyter notebooks
|
|
4
|
+
entry: sqlnbfmt
|
|
5
|
+
language: python
|
|
6
|
+
types: [jupyter]
|
|
7
|
+
require_serial: true
|
|
8
|
+
minimum_pre_commit_version: '3.0.0'
|
|
9
|
+
|
|
10
|
+
- id: sqlnbfmt-check
|
|
11
|
+
name: SQL Notebook Formatter (check)
|
|
12
|
+
description: Check SQL formatting in Jupyter notebooks without modifying files
|
|
13
|
+
entry: sqlnbfmt --check
|
|
14
|
+
language: python
|
|
15
|
+
types: [jupyter]
|
|
16
|
+
require_serial: true
|
|
17
|
+
minimum_pre_commit_version: '3.0.0'
|
|
18
|
+
|
|
19
|
+
- id: sqlnbfmt-py
|
|
20
|
+
name: SQL Python File Formatter
|
|
21
|
+
description: Format SQL queries in Python files (e.g. Marimo notebooks)
|
|
22
|
+
entry: sqlnbfmt
|
|
23
|
+
language: python
|
|
24
|
+
types: [python]
|
|
25
|
+
require_serial: true
|
|
26
|
+
minimum_pre_commit_version: '3.0.0'
|
|
27
|
+
|
|
28
|
+
- id: sqlnbfmt-py-check
|
|
29
|
+
name: SQL Python File Formatter (check)
|
|
30
|
+
description: Check SQL formatting in Python files without modifying files
|
|
31
|
+
entry: sqlnbfmt --check
|
|
32
|
+
language: python
|
|
33
|
+
types: [python]
|
|
34
|
+
require_serial: true
|
|
35
|
+
minimum_pre_commit_version: '3.0.0'
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.12
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [0.4.2] - Unreleased
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- **Jupyter server extension**: `pip install sqlnbfmt` now auto-registers with jupyterlab-code-formatter — no manual config needed
|
|
13
|
+
|
|
14
|
+
### Changed
|
|
15
|
+
|
|
16
|
+
- Switched build system from setuptools to hatchling
|
|
17
|
+
- Updated JupyterLab docs to use `jupyter_server_config.py` (modern) instead of `jupyter_notebook_config.py` (legacy)
|
|
18
|
+
|
|
19
|
+
## [0.4.0] - 2026-03-24
|
|
20
|
+
|
|
21
|
+
### Added
|
|
22
|
+
|
|
23
|
+
- **Marimo notebook support**: format SQL in Marimo `.py` notebooks via `mo.sql()` calls — same `sqlnbfmt` command, auto-detected by file extension
|
|
24
|
+
- **Python file support**: `sqlnbfmt` now accepts `.py` files alongside `.ipynb` — works on any Python file containing SQL strings
|
|
25
|
+
- **JupyterLab integration**: `sqlnbfmt.jupyterlab_integration.register()` for use with `jupyterlab-code-formatter`
|
|
26
|
+
- `format_cell_source()` public API for formatting a single cell's source code
|
|
27
|
+
- `_format_python_source()`, `process_python_file()`, `diff_python_file()` public API for programmatic use
|
|
28
|
+
- `sql` added to default recognized function names (matches `mo.sql()`, etc.)
|
|
29
|
+
- `sqlnbfmt-py` and `sqlnbfmt-py-check` pre-commit hooks for Python files
|
|
30
|
+
- Marimo eval fixtures: `marimo_basic_sql`, `marimo_fstring_interpolation`, `marimo_complex_sql`, `marimo_multi_cell_mixed`, `marimo_comment_preservation`, `marimo_multi_statement`, `marimo_skip_hint`, `marimo_non_sql_unchanged`, `marimo_idempotency`
|
|
31
|
+
|
|
32
|
+
### Fixed
|
|
33
|
+
|
|
34
|
+
- Idempotency: already-formatted SQL in triple-quoted strings (with leading whitespace/indentation) is no longer re-formatted on every run
|
|
35
|
+
|
|
36
|
+
### Changed
|
|
37
|
+
|
|
38
|
+
- CLI description and help text updated to reflect multi-format support
|
|
39
|
+
- Project description and keywords updated for Marimo discoverability
|
|
40
|
+
|
|
41
|
+
## [0.3.2] - 2026-03-16
|
|
42
|
+
|
|
43
|
+
### Fixed
|
|
44
|
+
|
|
45
|
+
- Multiple SQL statements in a single cell are no longer concatenated on one line — each statement now starts on its own line after the `;` separator ([#3](https://github.com/flyersworder/sqlnbfmt/issues/3))
|
|
46
|
+
|
|
47
|
+
### Changed
|
|
48
|
+
|
|
49
|
+
- SQL parsing switched from `sqlglot.parse_one()` to `sqlglot.parse()` to correctly handle multi-statement inputs
|
|
50
|
+
|
|
51
|
+
### Added
|
|
52
|
+
|
|
53
|
+
- `multi_statement` eval fixture case covering `DROP TABLE` + `CREATE TABLE` sequences
|
|
54
|
+
|
|
55
|
+
## [0.3.1] - 2026-03-15
|
|
56
|
+
|
|
57
|
+
### Fixed
|
|
58
|
+
|
|
59
|
+
- `diff_notebook()` no longer duplicates cell-processing logic — extracted shared `_format_cells()` helper to prevent future divergence
|
|
60
|
+
- `--check --diff` combined mode no longer double-counts notebooks or processes them twice
|
|
61
|
+
- Skip hint (`# sqlnbfmt: skip`) no longer triggers on string literals containing the directive — only dedicated comment lines are recognised
|
|
62
|
+
- `load_config()` with a partial config file (missing keys) now falls back to built-in defaults instead of empty sets
|
|
63
|
+
- `load_config()` with an empty YAML file no longer raises `AttributeError`
|
|
64
|
+
- In-function SQL indentation now respects `indent_width` config instead of hardcoded 4 spaces
|
|
65
|
+
|
|
66
|
+
### Added
|
|
67
|
+
|
|
68
|
+
- `main()` integration tests for `--diff`, `--check`, and `--check --diff` exit code behavior
|
|
69
|
+
- Docstring on `_has_skip_hint()` clarifying that inline trailing comments are intentionally ignored
|
|
70
|
+
|
|
71
|
+
## [0.3.0] - 2026-03-15
|
|
72
|
+
|
|
73
|
+
### Added
|
|
74
|
+
|
|
75
|
+
- **Zero-config defaults**: sqlnbfmt now works out of the box without a `config.yaml` file — built-in defaults for SQL keywords, function names, and decorators
|
|
76
|
+
- **`--check` mode**: verify formatting without modifying files; exits with code 1 if changes are needed (CI-friendly)
|
|
77
|
+
- **`--diff` mode**: print a unified diff of formatting changes without modifying files
|
|
78
|
+
- **Skip hints**: add `# sqlnbfmt: skip` to any cell to skip formatting
|
|
79
|
+
- **`sqlnbfmt-check` pre-commit hook**: a read-only hook variant for CI pipelines
|
|
80
|
+
- Cell index in all warning/debug messages for easier debugging
|
|
81
|
+
- PyPI keywords and project URLs in package metadata
|
|
82
|
+
- `skip_hint` eval fixture case
|
|
83
|
+
|
|
84
|
+
### Changed
|
|
85
|
+
|
|
86
|
+
- `--config` argument is now optional (defaults to built-in settings instead of requiring `config.yaml`)
|
|
87
|
+
- `load_config()` accepts `None` to return defaults; passing a missing path still raises `FileNotFoundError`
|
|
88
|
+
- Version bumped to 0.3.0
|
|
89
|
+
|
|
90
|
+
## [0.2.0] - 2026-03-15
|
|
91
|
+
|
|
92
|
+
### Fixed
|
|
93
|
+
|
|
94
|
+
- Python comments in code cells are no longer stripped during formatting ([#2](https://github.com/flyersworder/sqlnbfmt/issues/2))
|
|
95
|
+
|
|
96
|
+
### Changed
|
|
97
|
+
|
|
98
|
+
- Replaced AST-mutation approach (`ast.NodeTransformer` + `astor` + `black`) with surgical string replacement (`ast.NodeVisitor` + offset-based text splicing), preserving all non-SQL content exactly
|
|
99
|
+
- Removed `astor` and `black` from dependencies — fewer install requirements
|
|
100
|
+
- CI publish now uses PyPI Trusted Publishers (OIDC) instead of API tokens
|
|
101
|
+
- Migrated `tool.uv.dev-dependencies` to `dependency-groups.dev` (PEP 735)
|
|
102
|
+
- Updated `actions/checkout` from v3 to v4
|
|
103
|
+
|
|
104
|
+
### Added
|
|
105
|
+
|
|
106
|
+
- Python 3.13 classifier
|
|
107
|
+
- Comment-preservation test case
|
|
108
|
+
|
|
109
|
+
### Fixed
|
|
110
|
+
|
|
111
|
+
- Typo in config.yaml: `exeucte_query` → `execute_query`
|
|
112
|
+
|
|
113
|
+
## [0.1.9] - 2025-01-01
|
|
114
|
+
|
|
115
|
+
### Changed
|
|
116
|
+
|
|
117
|
+
- Updated dependencies (attrs, black, referencing, sqlglot, typing-extensions)
|
|
118
|
+
|
|
119
|
+
## [0.1.8] - 2024-12-01
|
|
120
|
+
|
|
121
|
+
### Fixed
|
|
122
|
+
|
|
123
|
+
- First-line indentation error for in-function SQL
|
|
124
|
+
- New-line handling issues in formatted output
|
|
125
|
+
- Introduced `black` formatter to resolve in-function SQL formatting edge cases
|
|
126
|
+
|
|
127
|
+
## [0.1.7] - 2024-11-01
|
|
128
|
+
|
|
129
|
+
### Added
|
|
130
|
+
|
|
131
|
+
- Pre-commit hook support
|
|
132
|
+
- F-string SQL formatting (with and without variables)
|
|
133
|
+
- In-function SQL formatting (e.g., `pd.read_sql(...)`)
|
|
134
|
+
|
|
135
|
+
## [0.1.0] - 2024-10-01
|
|
136
|
+
|
|
137
|
+
### Added
|
|
138
|
+
|
|
139
|
+
- Initial release
|
|
140
|
+
- SQL formatting in Jupyter notebook code cells using sqlglot
|
|
141
|
+
- Support for `%sql` / `%%sql` magic commands
|
|
142
|
+
- Configurable SQL keywords, function names, and formatting options
|
|
143
|
+
- GitHub Actions CI pipeline
|
|
@@ -1,31 +1,30 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: sqlnbfmt
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.2
|
|
4
4
|
Summary: A tool to format SQL code in Jupyter notebooks and Marimo notebooks.
|
|
5
|
-
Author-email: Qing <qingye779@gmail.com>
|
|
6
|
-
License: MIT
|
|
7
5
|
Project-URL: Homepage, https://github.com/flyersworder/sqlnbfmt
|
|
8
6
|
Project-URL: Repository, https://github.com/flyersworder/sqlnbfmt
|
|
9
7
|
Project-URL: Changelog, https://github.com/flyersworder/sqlnbfmt/blob/main/CHANGELOG.md
|
|
10
8
|
Project-URL: Issues, https://github.com/flyersworder/sqlnbfmt/issues
|
|
11
|
-
|
|
9
|
+
Author-email: Qing <qingye779@gmail.com>
|
|
10
|
+
License: MIT
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Keywords: formatter,jupyter,marimo,notebook,pre-commit,sql,sqlglot
|
|
12
13
|
Classifier: Development Status :: 4 - Beta
|
|
14
|
+
Classifier: Framework :: Jupyter
|
|
13
15
|
Classifier: Intended Audience :: Developers
|
|
14
16
|
Classifier: Intended Audience :: Science/Research
|
|
15
17
|
Classifier: License :: OSI Approved :: MIT License
|
|
16
18
|
Classifier: Programming Language :: Python :: 3
|
|
17
19
|
Classifier: Programming Language :: Python :: 3.12
|
|
18
20
|
Classifier: Programming Language :: Python :: 3.13
|
|
19
|
-
Classifier: Topic :: Software Development :: Quality Assurance
|
|
20
21
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
21
|
-
Classifier:
|
|
22
|
+
Classifier: Topic :: Software Development :: Quality Assurance
|
|
22
23
|
Requires-Python: >=3.12
|
|
23
|
-
Description-Content-Type: text/markdown
|
|
24
|
-
License-File: LICENSE
|
|
25
24
|
Requires-Dist: nbformat>=5.10.4
|
|
26
25
|
Requires-Dist: pyyaml>=6.0.2
|
|
27
26
|
Requires-Dist: sqlglot>=25.27.0
|
|
28
|
-
|
|
27
|
+
Description-Content-Type: text/markdown
|
|
29
28
|
|
|
30
29
|
# sqlnbfmt
|
|
31
30
|
|
|
@@ -48,6 +47,7 @@ A SQL formatter for Jupyter Notebooks and Marimo notebooks. `sqlnbfmt` automatic
|
|
|
48
47
|
- **CI-Friendly**: `--check` mode exits non-zero when formatting is needed; `--diff` shows what would change
|
|
49
48
|
- **Skip Hints**: Add `# sqlnbfmt: skip` to any cell to exclude it from formatting
|
|
50
49
|
- **Pre-commit Ready**: Seamlessly integrates with pre-commit hooks
|
|
50
|
+
- **JupyterLab Plugin**: Works with `jupyterlab-code-formatter` for interactive format-on-save
|
|
51
51
|
- **Lightweight**: Only three runtime dependencies (sqlglot, nbformat, pyyaml)
|
|
52
52
|
|
|
53
53
|
## Installation
|
|
@@ -94,6 +94,22 @@ Add a `# sqlnbfmt: skip` comment to skip formatting. In Jupyter notebooks this a
|
|
|
94
94
|
query = "select * from my_special_table where id = 1"
|
|
95
95
|
```
|
|
96
96
|
|
|
97
|
+
### JupyterLab Integration
|
|
98
|
+
|
|
99
|
+
Format SQL cells interactively with [jupyterlab-code-formatter](https://github.com/jupyterlab-contrib/jupyterlab_code_formatter):
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
pip install sqlnbfmt jupyterlab-code-formatter
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
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".
|
|
106
|
+
|
|
107
|
+
To customize the dialect, add this to `~/.jupyter/jupyter_server_config.py`:
|
|
108
|
+
```python
|
|
109
|
+
from sqlnbfmt.jupyterlab_integration import register
|
|
110
|
+
register(dialect="postgres")
|
|
111
|
+
```
|
|
112
|
+
|
|
97
113
|
### Pre-commit Integration
|
|
98
114
|
|
|
99
115
|
1. Install pre-commit:
|
|
@@ -19,6 +19,7 @@ A SQL formatter for Jupyter Notebooks and Marimo notebooks. `sqlnbfmt` automatic
|
|
|
19
19
|
- **CI-Friendly**: `--check` mode exits non-zero when formatting is needed; `--diff` shows what would change
|
|
20
20
|
- **Skip Hints**: Add `# sqlnbfmt: skip` to any cell to exclude it from formatting
|
|
21
21
|
- **Pre-commit Ready**: Seamlessly integrates with pre-commit hooks
|
|
22
|
+
- **JupyterLab Plugin**: Works with `jupyterlab-code-formatter` for interactive format-on-save
|
|
22
23
|
- **Lightweight**: Only three runtime dependencies (sqlglot, nbformat, pyyaml)
|
|
23
24
|
|
|
24
25
|
## Installation
|
|
@@ -65,6 +66,22 @@ Add a `# sqlnbfmt: skip` comment to skip formatting. In Jupyter notebooks this a
|
|
|
65
66
|
query = "select * from my_special_table where id = 1"
|
|
66
67
|
```
|
|
67
68
|
|
|
69
|
+
### JupyterLab Integration
|
|
70
|
+
|
|
71
|
+
Format SQL cells interactively with [jupyterlab-code-formatter](https://github.com/jupyterlab-contrib/jupyterlab_code_formatter):
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
pip install sqlnbfmt jupyterlab-code-formatter
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
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".
|
|
78
|
+
|
|
79
|
+
To customize the dialect, add this to `~/.jupyter/jupyter_server_config.py`:
|
|
80
|
+
```python
|
|
81
|
+
from sqlnbfmt.jupyterlab_integration import register
|
|
82
|
+
register(dialect="postgres")
|
|
83
|
+
```
|
|
84
|
+
|
|
68
85
|
### Pre-commit Integration
|
|
69
86
|
|
|
70
87
|
1. Install pre-commit:
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# Optional — sqlnbfmt works without this file using built-in defaults.
|
|
2
|
+
# Use this file only to override specific settings.
|
|
3
|
+
# config.yaml
|
|
4
|
+
|
|
5
|
+
sql_keywords:
|
|
6
|
+
- SELECT
|
|
7
|
+
- FROM
|
|
8
|
+
- WHERE
|
|
9
|
+
- INSERT
|
|
10
|
+
- UPDATE
|
|
11
|
+
- DELETE
|
|
12
|
+
- WITH
|
|
13
|
+
- JOIN
|
|
14
|
+
- CREATE
|
|
15
|
+
- DROP
|
|
16
|
+
- ALTER
|
|
17
|
+
- TRUNCATE
|
|
18
|
+
- UNION
|
|
19
|
+
- EXCEPT
|
|
20
|
+
- INTERSECT
|
|
21
|
+
- GROUP BY
|
|
22
|
+
- ORDER BY
|
|
23
|
+
- HAVING
|
|
24
|
+
- LIMIT
|
|
25
|
+
- OFFSET
|
|
26
|
+
- DISTINCT
|
|
27
|
+
|
|
28
|
+
function_names:
|
|
29
|
+
- read_sql
|
|
30
|
+
- read_sql_query
|
|
31
|
+
- read_sql_table
|
|
32
|
+
- execute
|
|
33
|
+
- executescript
|
|
34
|
+
- fetchall
|
|
35
|
+
- fetchone
|
|
36
|
+
- fetchmany
|
|
37
|
+
- execute_query
|
|
38
|
+
|
|
39
|
+
# Decorator names that contain SQL
|
|
40
|
+
sql_decorators:
|
|
41
|
+
- sql_decorator
|
|
42
|
+
- query
|
|
43
|
+
- sql_query
|
|
44
|
+
- db_query
|
|
45
|
+
|
|
46
|
+
# Formatting options
|
|
47
|
+
formatting_options:
|
|
48
|
+
single_line_threshold: 80 # Maximum length for single-line SQL
|
|
49
|
+
indent_width: 4 # Number of spaces for indentation
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "sqlnbfmt"
|
|
3
|
-
version = "0.4.
|
|
3
|
+
version = "0.4.2"
|
|
4
4
|
description = "A tool to format SQL code in Jupyter notebooks and Marimo notebooks."
|
|
5
5
|
authors = [
|
|
6
6
|
{ name = "Qing", email = "qingye779@gmail.com" }
|
|
@@ -44,16 +44,16 @@ dev = [
|
|
|
44
44
|
]
|
|
45
45
|
|
|
46
46
|
[build-system]
|
|
47
|
-
requires = ["
|
|
48
|
-
build-backend = "
|
|
47
|
+
requires = ["hatchling"]
|
|
48
|
+
build-backend = "hatchling.build"
|
|
49
49
|
|
|
50
50
|
[tool.pytest.ini_options]
|
|
51
51
|
markers = [
|
|
52
52
|
"integration: mark a test as an integration test."
|
|
53
53
|
]
|
|
54
54
|
|
|
55
|
+
[tool.hatch.build.targets.wheel.shared-data]
|
|
56
|
+
"jupyter-config/sqlnbfmt.json" = "etc/jupyter/jupyter_server_config.d/sqlnbfmt.json"
|
|
57
|
+
|
|
55
58
|
[tool.ruff]
|
|
56
59
|
extend-exclude = ["tests/eval/*/"]
|
|
57
|
-
|
|
58
|
-
[tool.setuptools.package-data]
|
|
59
|
-
sqlnbfmt = [".pre-commit-hooks.yaml"]
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
def _jupyter_server_extension_points():
|
|
2
|
+
return [{"module": "sqlnbfmt"}]
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def _load_jupyter_server_extension(server_app):
|
|
6
|
+
try:
|
|
7
|
+
from sqlnbfmt.jupyterlab_integration import register
|
|
8
|
+
|
|
9
|
+
register()
|
|
10
|
+
server_app.log.info(
|
|
11
|
+
"sqlnbfmt: registered SQL formatter with jupyterlab-code-formatter"
|
|
12
|
+
)
|
|
13
|
+
except Exception:
|
|
14
|
+
# jupyterlab-code-formatter not installed — silently skip
|
|
15
|
+
pass
|