sqlnbfmt 0.4.1__tar.gz → 0.5.0__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.5.0/.github/dependabot.yml +23 -0
- sqlnbfmt-0.5.0/.github/workflows/ci-and-publish.yml +55 -0
- sqlnbfmt-0.5.0/.gitignore +163 -0
- sqlnbfmt-0.5.0/.pre-commit-config.yaml +41 -0
- sqlnbfmt-0.5.0/.pre-commit-hooks.yaml +35 -0
- sqlnbfmt-0.5.0/.python-version +1 -0
- sqlnbfmt-0.5.0/CHANGELOG.md +165 -0
- {sqlnbfmt-0.4.1/sqlnbfmt.egg-info → sqlnbfmt-0.5.0}/PKG-INFO +65 -48
- sqlnbfmt-0.4.1/PKG-INFO → sqlnbfmt-0.5.0/README.md +56 -67
- sqlnbfmt-0.5.0/SECURITY.md +13 -0
- sqlnbfmt-0.5.0/config.yaml +53 -0
- sqlnbfmt-0.5.0/jupyter-config/sqlnbfmt.json +7 -0
- {sqlnbfmt-0.4.1 → sqlnbfmt-0.5.0}/pyproject.toml +11 -6
- sqlnbfmt-0.5.0/sqlnbfmt/__init__.py +29 -0
- {sqlnbfmt-0.4.1 → sqlnbfmt-0.5.0}/sqlnbfmt/formatter.py +276 -93
- {sqlnbfmt-0.4.1 → sqlnbfmt-0.5.0}/sqlnbfmt/jupyterlab_integration.py +31 -14
- sqlnbfmt-0.5.0/tests/eval/README.md +103 -0
- sqlnbfmt-0.5.0/tests/eval/basic_select/expected.ipynb +26 -0
- sqlnbfmt-0.5.0/tests/eval/basic_select/input.ipynb +17 -0
- sqlnbfmt-0.5.0/tests/eval/case_expression/expected.ipynb +22 -0
- sqlnbfmt-0.5.0/tests/eval/case_expression/input.ipynb +17 -0
- sqlnbfmt-0.5.0/tests/eval/comment_preservation/expected.ipynb +27 -0
- sqlnbfmt-0.5.0/tests/eval/comment_preservation/input.ipynb +19 -0
- sqlnbfmt-0.5.0/tests/eval/cte/expected.ipynb +29 -0
- sqlnbfmt-0.5.0/tests/eval/cte/input.ipynb +17 -0
- sqlnbfmt-0.5.0/tests/eval/fstring_variables/expected.ipynb +42 -0
- sqlnbfmt-0.5.0/tests/eval/fstring_variables/input.ipynb +30 -0
- sqlnbfmt-0.5.0/tests/eval/generate_fixtures.py +306 -0
- sqlnbfmt-0.5.0/tests/eval/group_by_having/expected.ipynb +29 -0
- sqlnbfmt-0.5.0/tests/eval/group_by_having/input.ipynb +17 -0
- sqlnbfmt-0.5.0/tests/eval/idempotency/expected.ipynb +24 -0
- sqlnbfmt-0.5.0/tests/eval/idempotency/input.ipynb +24 -0
- sqlnbfmt-0.5.0/tests/eval/in_function_sql/expected.ipynb +43 -0
- sqlnbfmt-0.5.0/tests/eval/in_function_sql/input.ipynb +27 -0
- sqlnbfmt-0.5.0/tests/eval/joins/expected.ipynb +27 -0
- sqlnbfmt-0.5.0/tests/eval/joins/input.ipynb +17 -0
- sqlnbfmt-0.5.0/tests/eval/magic_commands/expected.ipynb +50 -0
- sqlnbfmt-0.5.0/tests/eval/magic_commands/input.ipynb +40 -0
- sqlnbfmt-0.5.0/tests/eval/marimo_basic_sql/expected.py +31 -0
- sqlnbfmt-0.5.0/tests/eval/marimo_basic_sql/input.py +20 -0
- sqlnbfmt-0.5.0/tests/eval/marimo_comment_preservation/expected.py +50 -0
- sqlnbfmt-0.5.0/tests/eval/marimo_comment_preservation/input.py +30 -0
- sqlnbfmt-0.5.0/tests/eval/marimo_complex_sql/expected.py +63 -0
- sqlnbfmt-0.5.0/tests/eval/marimo_complex_sql/input.py +27 -0
- sqlnbfmt-0.5.0/tests/eval/marimo_fstring_interpolation/expected.py +47 -0
- sqlnbfmt-0.5.0/tests/eval/marimo_fstring_interpolation/input.py +28 -0
- sqlnbfmt-0.5.0/tests/eval/marimo_idempotency/expected.py +31 -0
- sqlnbfmt-0.5.0/tests/eval/marimo_idempotency/input.py +31 -0
- sqlnbfmt-0.5.0/tests/eval/marimo_multi_cell_mixed/expected.py +66 -0
- sqlnbfmt-0.5.0/tests/eval/marimo_multi_cell_mixed/input.py +44 -0
- sqlnbfmt-0.5.0/tests/eval/marimo_multi_statement/expected.py +34 -0
- sqlnbfmt-0.5.0/tests/eval/marimo_multi_statement/input.py +20 -0
- sqlnbfmt-0.5.0/tests/eval/marimo_non_sql_unchanged/expected.py +39 -0
- sqlnbfmt-0.5.0/tests/eval/marimo_non_sql_unchanged/input.py +39 -0
- sqlnbfmt-0.5.0/tests/eval/marimo_skip_hint/expected.py +21 -0
- sqlnbfmt-0.5.0/tests/eval/marimo_skip_hint/input.py +21 -0
- sqlnbfmt-0.5.0/tests/eval/multi_cell_mixed/expected.ipynb +76 -0
- sqlnbfmt-0.5.0/tests/eval/multi_cell_mixed/input.ipynb +65 -0
- sqlnbfmt-0.5.0/tests/eval/multi_statement/expected.ipynb +29 -0
- sqlnbfmt-0.5.0/tests/eval/multi_statement/input.ipynb +18 -0
- sqlnbfmt-0.5.0/tests/eval/non_sql_unchanged/expected.ipynb +44 -0
- sqlnbfmt-0.5.0/tests/eval/non_sql_unchanged/input.ipynb +44 -0
- sqlnbfmt-0.5.0/tests/eval/skip_hint/expected.ipynb +35 -0
- sqlnbfmt-0.5.0/tests/eval/skip_hint/input.ipynb +28 -0
- sqlnbfmt-0.5.0/tests/eval/subquery/expected.ipynb +29 -0
- sqlnbfmt-0.5.0/tests/eval/subquery/input.ipynb +17 -0
- sqlnbfmt-0.5.0/tests/eval/union/expected.ipynb +31 -0
- sqlnbfmt-0.5.0/tests/eval/union/input.ipynb +17 -0
- sqlnbfmt-0.5.0/tests/eval/window_function/expected.ipynb +23 -0
- sqlnbfmt-0.5.0/tests/eval/window_function/input.ipynb +17 -0
- sqlnbfmt-0.5.0/tests/test_call_layout.py +151 -0
- {sqlnbfmt-0.4.1 → sqlnbfmt-0.5.0}/tests/test_formatter.py +22 -4
- sqlnbfmt-0.5.0/tests/test_jupyterlab_integration.py +208 -0
- {sqlnbfmt-0.4.1 → sqlnbfmt-0.5.0}/tests/test_marimo.py +6 -2
- sqlnbfmt-0.5.0/tests/test_notebook.ipynb +358 -0
- sqlnbfmt-0.5.0/tests/test_notebook_copy.ipynb +311 -0
- sqlnbfmt-0.5.0/tests/test_pyproject_config.py +244 -0
- sqlnbfmt-0.5.0/uv.lock +497 -0
- sqlnbfmt-0.4.1/README.md +0 -259
- sqlnbfmt-0.4.1/setup.cfg +0 -4
- sqlnbfmt-0.4.1/sqlnbfmt.egg-info/SOURCES.txt +0 -16
- sqlnbfmt-0.4.1/sqlnbfmt.egg-info/dependency_links.txt +0 -1
- sqlnbfmt-0.4.1/sqlnbfmt.egg-info/entry_points.txt +0 -2
- sqlnbfmt-0.4.1/sqlnbfmt.egg-info/requires.txt +0 -3
- sqlnbfmt-0.4.1/sqlnbfmt.egg-info/top_level.txt +0 -1
- sqlnbfmt-0.4.1/tests/test_jupyterlab_integration.py +0 -76
- {sqlnbfmt-0.4.1 → sqlnbfmt-0.5.0}/LICENSE +0 -0
- {sqlnbfmt-0.4.1/sqlnbfmt → sqlnbfmt-0.5.0/tests}/__init__.py +0 -0
- {sqlnbfmt-0.4.1 → sqlnbfmt-0.5.0}/tests/test_eval.py +0 -0
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
version: 2
|
|
2
|
+
updates:
|
|
3
|
+
- package-ecosystem: "github-actions"
|
|
4
|
+
directory: "/"
|
|
5
|
+
schedule:
|
|
6
|
+
interval: "weekly"
|
|
7
|
+
day: "monday"
|
|
8
|
+
labels:
|
|
9
|
+
- "dependencies"
|
|
10
|
+
|
|
11
|
+
- package-ecosystem: "pip"
|
|
12
|
+
directory: "/"
|
|
13
|
+
schedule:
|
|
14
|
+
interval: "weekly"
|
|
15
|
+
day: "monday"
|
|
16
|
+
open-pull-requests-limit: 10
|
|
17
|
+
labels:
|
|
18
|
+
- "dependencies"
|
|
19
|
+
groups:
|
|
20
|
+
minor-and-patch:
|
|
21
|
+
update-types:
|
|
22
|
+
- "minor"
|
|
23
|
+
- "patch"
|
|
@@ -0,0 +1,55 @@
|
|
|
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
|
+
permissions: {}
|
|
17
|
+
|
|
18
|
+
jobs:
|
|
19
|
+
test:
|
|
20
|
+
runs-on: ubuntu-latest
|
|
21
|
+
permissions:
|
|
22
|
+
contents: read
|
|
23
|
+
steps:
|
|
24
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
25
|
+
- uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0
|
|
26
|
+
with:
|
|
27
|
+
enable-cache: true
|
|
28
|
+
cache-dependency-glob: "pyproject.toml"
|
|
29
|
+
- run: uv python install 3.12
|
|
30
|
+
- run: uv sync --all-extras --dev --frozen
|
|
31
|
+
- run: uv run pytest
|
|
32
|
+
|
|
33
|
+
security:
|
|
34
|
+
runs-on: ubuntu-latest
|
|
35
|
+
permissions:
|
|
36
|
+
contents: read
|
|
37
|
+
steps:
|
|
38
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
39
|
+
- uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0
|
|
40
|
+
- run: uvx uv-secure uv.lock
|
|
41
|
+
|
|
42
|
+
publish:
|
|
43
|
+
needs: [test, security]
|
|
44
|
+
if: github.event_name == 'release' || (github.event_name == 'workflow_dispatch' && github.event.inputs.run_publish == 'true')
|
|
45
|
+
runs-on: ubuntu-latest
|
|
46
|
+
permissions:
|
|
47
|
+
id-token: write
|
|
48
|
+
steps:
|
|
49
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
50
|
+
- uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0
|
|
51
|
+
with:
|
|
52
|
+
enable-cache: true
|
|
53
|
+
- run: uv python install 3.12
|
|
54
|
+
- run: uv build --no-sources
|
|
55
|
+
- uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # v1.14.2
|
|
@@ -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.17.1
|
|
5
|
+
hooks:
|
|
6
|
+
- id: ruff-check
|
|
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: '0.26'
|
|
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,165 @@
|
|
|
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.5.0] - 2026-10-15
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- **`pyproject.toml` configuration**: set options in a `[tool.sqlnbfmt]` table instead of a separate YAML file. Without `--config`, sqlnbfmt uses the nearest `pyproject.toml` that has the table, searching up to the repository root. The JupyterLab integration uses the same discovery ([#22](https://github.com/flyersworder/sqlnbfmt/issues/22))
|
|
13
|
+
- `--config` accepts a `.toml` path as well as YAML
|
|
14
|
+
- `dialect` config option (in `[tool.sqlnbfmt]` or YAML), so the dialect no longer has to be passed as `--dialect` on every run; `--dialect` still overrides it
|
|
15
|
+
|
|
16
|
+
### Changed
|
|
17
|
+
|
|
18
|
+
- Config values are now type-checked: a wrong type (e.g. a string where a list is expected) is reported as an error naming the file. Previously such values were silently mis-parsed or crashed with a traceback
|
|
19
|
+
- Unknown config options now produce a warning instead of being silently ignored
|
|
20
|
+
|
|
21
|
+
### Fixed
|
|
22
|
+
|
|
23
|
+
- SQL passed to a function call is now indented relative to the line the call is on, and a closing `)` or remaining arguments no longer land at column 0. This was most visible in Marimo cells, where every `mo.sql(...)` sits inside a function. It had regressed in 0.3.0, when the `black` post-processing pass was removed. Code already formatted by an earlier version keeps its layout until its SQL changes
|
|
24
|
+
- The Jupyter server extension no longer overrides a formatter registered in `jupyter_server_config.py` (e.g. `register(dialect="postgres")`), and it now logs configuration errors instead of silently not registering
|
|
25
|
+
- An unknown dialect (e.g. `--dialect postgress`) is now rejected with a suggestion. Previously every SQL string silently failed to parse, so `--check` reported all files as properly formatted
|
|
26
|
+
- The `config.yaml` template was missing the `sql` function name (default since 0.4.0). Because config lists replace the defaults, copying the template silently disabled Marimo `mo.sql()` formatting. The README now states the replace semantics explicitly
|
|
27
|
+
- Upgraded locked dependencies, including sqlglot 29 → 30 (formatting output unchanged across the eval suite)
|
|
28
|
+
- A skipped Jupyter extension registration is now logged at debug level instead of being silently swallowed
|
|
29
|
+
|
|
30
|
+
## [0.4.2] - 2026-03-24
|
|
31
|
+
|
|
32
|
+
### Added
|
|
33
|
+
|
|
34
|
+
- **Jupyter server extension**: `pip install sqlnbfmt` now auto-registers with jupyterlab-code-formatter — no manual config needed
|
|
35
|
+
|
|
36
|
+
### Changed
|
|
37
|
+
|
|
38
|
+
- Switched build system from setuptools to hatchling
|
|
39
|
+
- Updated JupyterLab docs to use `jupyter_server_config.py` (modern) instead of `jupyter_notebook_config.py` (legacy)
|
|
40
|
+
|
|
41
|
+
## [0.4.0] - 2026-03-24
|
|
42
|
+
|
|
43
|
+
### Added
|
|
44
|
+
|
|
45
|
+
- **Marimo notebook support**: format SQL in Marimo `.py` notebooks via `mo.sql()` calls — same `sqlnbfmt` command, auto-detected by file extension
|
|
46
|
+
- **Python file support**: `sqlnbfmt` now accepts `.py` files alongside `.ipynb` — works on any Python file containing SQL strings
|
|
47
|
+
- **JupyterLab integration**: `sqlnbfmt.jupyterlab_integration.register()` for use with `jupyterlab-code-formatter`
|
|
48
|
+
- `format_cell_source()` public API for formatting a single cell's source code
|
|
49
|
+
- `_format_python_source()`, `process_python_file()`, `diff_python_file()` public API for programmatic use
|
|
50
|
+
- `sql` added to default recognized function names (matches `mo.sql()`, etc.)
|
|
51
|
+
- `sqlnbfmt-py` and `sqlnbfmt-py-check` pre-commit hooks for Python files
|
|
52
|
+
- 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`
|
|
53
|
+
|
|
54
|
+
### Fixed
|
|
55
|
+
|
|
56
|
+
- Idempotency: already-formatted SQL in triple-quoted strings (with leading whitespace/indentation) is no longer re-formatted on every run
|
|
57
|
+
|
|
58
|
+
### Changed
|
|
59
|
+
|
|
60
|
+
- CLI description and help text updated to reflect multi-format support
|
|
61
|
+
- Project description and keywords updated for Marimo discoverability
|
|
62
|
+
|
|
63
|
+
## [0.3.2] - 2026-03-16
|
|
64
|
+
|
|
65
|
+
### Fixed
|
|
66
|
+
|
|
67
|
+
- 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))
|
|
68
|
+
|
|
69
|
+
### Changed
|
|
70
|
+
|
|
71
|
+
- SQL parsing switched from `sqlglot.parse_one()` to `sqlglot.parse()` to correctly handle multi-statement inputs
|
|
72
|
+
|
|
73
|
+
### Added
|
|
74
|
+
|
|
75
|
+
- `multi_statement` eval fixture case covering `DROP TABLE` + `CREATE TABLE` sequences
|
|
76
|
+
|
|
77
|
+
## [0.3.1] - 2026-03-15
|
|
78
|
+
|
|
79
|
+
### Fixed
|
|
80
|
+
|
|
81
|
+
- `diff_notebook()` no longer duplicates cell-processing logic — extracted shared `_format_cells()` helper to prevent future divergence
|
|
82
|
+
- `--check --diff` combined mode no longer double-counts notebooks or processes them twice
|
|
83
|
+
- Skip hint (`# sqlnbfmt: skip`) no longer triggers on string literals containing the directive — only dedicated comment lines are recognised
|
|
84
|
+
- `load_config()` with a partial config file (missing keys) now falls back to built-in defaults instead of empty sets
|
|
85
|
+
- `load_config()` with an empty YAML file no longer raises `AttributeError`
|
|
86
|
+
- In-function SQL indentation now respects `indent_width` config instead of hardcoded 4 spaces
|
|
87
|
+
|
|
88
|
+
### Added
|
|
89
|
+
|
|
90
|
+
- `main()` integration tests for `--diff`, `--check`, and `--check --diff` exit code behavior
|
|
91
|
+
- Docstring on `_has_skip_hint()` clarifying that inline trailing comments are intentionally ignored
|
|
92
|
+
|
|
93
|
+
## [0.3.0] - 2026-03-15
|
|
94
|
+
|
|
95
|
+
### Added
|
|
96
|
+
|
|
97
|
+
- **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
|
|
98
|
+
- **`--check` mode**: verify formatting without modifying files; exits with code 1 if changes are needed (CI-friendly)
|
|
99
|
+
- **`--diff` mode**: print a unified diff of formatting changes without modifying files
|
|
100
|
+
- **Skip hints**: add `# sqlnbfmt: skip` to any cell to skip formatting
|
|
101
|
+
- **`sqlnbfmt-check` pre-commit hook**: a read-only hook variant for CI pipelines
|
|
102
|
+
- Cell index in all warning/debug messages for easier debugging
|
|
103
|
+
- PyPI keywords and project URLs in package metadata
|
|
104
|
+
- `skip_hint` eval fixture case
|
|
105
|
+
|
|
106
|
+
### Changed
|
|
107
|
+
|
|
108
|
+
- `--config` argument is now optional (defaults to built-in settings instead of requiring `config.yaml`)
|
|
109
|
+
- `load_config()` accepts `None` to return defaults; passing a missing path still raises `FileNotFoundError`
|
|
110
|
+
- Version bumped to 0.3.0
|
|
111
|
+
|
|
112
|
+
## [0.2.0] - 2026-03-15
|
|
113
|
+
|
|
114
|
+
### Fixed
|
|
115
|
+
|
|
116
|
+
- Python comments in code cells are no longer stripped during formatting ([#2](https://github.com/flyersworder/sqlnbfmt/issues/2))
|
|
117
|
+
|
|
118
|
+
### Changed
|
|
119
|
+
|
|
120
|
+
- Replaced AST-mutation approach (`ast.NodeTransformer` + `astor` + `black`) with surgical string replacement (`ast.NodeVisitor` + offset-based text splicing), preserving all non-SQL content exactly
|
|
121
|
+
- Removed `astor` and `black` from dependencies — fewer install requirements
|
|
122
|
+
- CI publish now uses PyPI Trusted Publishers (OIDC) instead of API tokens
|
|
123
|
+
- Migrated `tool.uv.dev-dependencies` to `dependency-groups.dev` (PEP 735)
|
|
124
|
+
- Updated `actions/checkout` from v3 to v4
|
|
125
|
+
|
|
126
|
+
### Added
|
|
127
|
+
|
|
128
|
+
- Python 3.13 classifier
|
|
129
|
+
- Comment-preservation test case
|
|
130
|
+
|
|
131
|
+
### Fixed
|
|
132
|
+
|
|
133
|
+
- Typo in config.yaml: `exeucte_query` → `execute_query`
|
|
134
|
+
|
|
135
|
+
## [0.1.9] - 2025-01-01
|
|
136
|
+
|
|
137
|
+
### Changed
|
|
138
|
+
|
|
139
|
+
- Updated dependencies (attrs, black, referencing, sqlglot, typing-extensions)
|
|
140
|
+
|
|
141
|
+
## [0.1.8] - 2024-12-01
|
|
142
|
+
|
|
143
|
+
### Fixed
|
|
144
|
+
|
|
145
|
+
- First-line indentation error for in-function SQL
|
|
146
|
+
- New-line handling issues in formatted output
|
|
147
|
+
- Introduced `black` formatter to resolve in-function SQL formatting edge cases
|
|
148
|
+
|
|
149
|
+
## [0.1.7] - 2024-11-01
|
|
150
|
+
|
|
151
|
+
### Added
|
|
152
|
+
|
|
153
|
+
- Pre-commit hook support
|
|
154
|
+
- F-string SQL formatting (with and without variables)
|
|
155
|
+
- In-function SQL formatting (e.g., `pd.read_sql(...)`)
|
|
156
|
+
|
|
157
|
+
## [0.1.0] - 2024-10-01
|
|
158
|
+
|
|
159
|
+
### Added
|
|
160
|
+
|
|
161
|
+
- Initial release
|
|
162
|
+
- SQL formatting in Jupyter notebook code cells using sqlglot
|
|
163
|
+
- Support for `%sql` / `%%sql` magic commands
|
|
164
|
+
- Configurable SQL keywords, function names, and formatting options
|
|
165
|
+
- GitHub Actions CI pipeline
|
|
@@ -1,31 +1,30 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
2
|
Name: sqlnbfmt
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.5.0
|
|
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
|
|
|
@@ -99,19 +98,18 @@ query = "select * from my_special_table where id = 1"
|
|
|
99
98
|
|
|
100
99
|
Format SQL cells interactively with [jupyterlab-code-formatter](https://github.com/jupyterlab-contrib/jupyterlab_code_formatter):
|
|
101
100
|
|
|
102
|
-
1. Install both packages:
|
|
103
101
|
```bash
|
|
104
102
|
pip install sqlnbfmt jupyterlab-code-formatter
|
|
105
103
|
```
|
|
106
104
|
|
|
107
|
-
|
|
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
|
+
The extension uses `[tool.sqlnbfmt]` (including `dialect`) from the nearest `pyproject.toml` of the directory you start Jupyter in. To set the dialect explicitly instead, add this to `~/.jupyter/jupyter_server_config.py`:
|
|
108
108
|
```python
|
|
109
109
|
from sqlnbfmt.jupyterlab_integration import register
|
|
110
|
-
register(
|
|
110
|
+
register(dialect="postgres")
|
|
111
111
|
```
|
|
112
112
|
|
|
113
|
-
3. In JupyterLab, use **Edit > Format Cell** or configure format-on-save in Settings > Code Formatter.
|
|
114
|
-
|
|
115
113
|
### Pre-commit Integration
|
|
116
114
|
|
|
117
115
|
1. Install pre-commit:
|
|
@@ -123,7 +121,7 @@ pip install pre-commit
|
|
|
123
121
|
```yaml
|
|
124
122
|
repos:
|
|
125
123
|
- repo: https://github.com/flyersworder/sqlnbfmt
|
|
126
|
-
rev: v0.
|
|
124
|
+
rev: v0.5.0
|
|
127
125
|
hooks:
|
|
128
126
|
- id: sqlnbfmt
|
|
129
127
|
types: [jupyter]
|
|
@@ -135,7 +133,7 @@ To also format Marimo notebooks (Python files), add the Python hook:
|
|
|
135
133
|
files: '\.py$' # optionally narrow with: files: 'marimo_.*\.py$'
|
|
136
134
|
```
|
|
137
135
|
|
|
138
|
-
All arguments are optional.
|
|
136
|
+
All arguments are optional. Settings in `[tool.sqlnbfmt]` in your `pyproject.toml` are picked up automatically (see [Configuration](#configuration)); alternatively pass them as arguments:
|
|
139
137
|
```yaml
|
|
140
138
|
args: [--dialect, postgres, --config, config.yaml]
|
|
141
139
|
```
|
|
@@ -164,19 +162,38 @@ Use `--check` in GitHub Actions to enforce formatting:
|
|
|
164
162
|
|
|
165
163
|
## Configuration
|
|
166
164
|
|
|
167
|
-
`sqlnbfmt` works without any configuration
|
|
165
|
+
`sqlnbfmt` works without any configuration. To override defaults, use a `[tool.sqlnbfmt]` table in `pyproject.toml` or a separate YAML file.
|
|
166
|
+
|
|
167
|
+
### pyproject.toml
|
|
168
168
|
|
|
169
|
-
|
|
169
|
+
```toml
|
|
170
|
+
[tool.sqlnbfmt]
|
|
171
|
+
dialect = "postgres"
|
|
172
|
+
|
|
173
|
+
[tool.sqlnbfmt.formatting_options]
|
|
174
|
+
indent_width = 2
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
`sqlnbfmt` searches the current directory and its parents for the nearest `pyproject.toml` with a `[tool.sqlnbfmt]` table, stopping at the repository root (the directory containing `.git`). A `pyproject.toml` without that table is skipped, so a sub-package's file doesn't hide the repository-level configuration. The JupyterLab integration does the same, starting from the Jupyter server's working directory.
|
|
178
|
+
|
|
179
|
+
### YAML file
|
|
180
|
+
|
|
181
|
+
Pass a YAML file with `--config config.yaml`. [Here](https://github.com/flyersworder/sqlnbfmt/blob/main/config.yaml) is a template. `--config` also accepts a `.toml` path, which is read from its `[tool.sqlnbfmt]` table.
|
|
182
|
+
|
|
183
|
+
When `--config` is given, `pyproject.toml` discovery is skipped. Options you don't set keep their defaults, and unknown option names produce a warning.
|
|
170
184
|
|
|
171
185
|
### Configuration Options
|
|
172
186
|
|
|
173
187
|
| Option | Description | Default |
|
|
174
188
|
|--------|-------------|---------|
|
|
189
|
+
| `dialect` | SQL dialect passed to sqlglot (e.g. `postgres`, `mysql`, `bigquery`); `--dialect` overrides it | none (generic SQL) |
|
|
175
190
|
| `sql_keywords` | SQL keywords to recognize and format | Common SQL keywords |
|
|
176
|
-
| `function_names` | Python functions containing SQL code | `read_sql`, `execute`, etc. |
|
|
191
|
+
| `function_names` | Python functions containing SQL code | `read_sql`, `execute`, `sql` (Marimo's `mo.sql`), etc. |
|
|
177
192
|
| `sql_decorators` | Decorators indicating SQL code | `query`, `sql_query`, etc. |
|
|
178
|
-
| `single_line_threshold` | Maximum length before splitting SQL | 80 |
|
|
179
|
-
| `indent_width` | Number of spaces for indentation | 4 |
|
|
193
|
+
| `formatting_options.single_line_threshold` | Maximum length before splitting SQL | 80 |
|
|
194
|
+
| `formatting_options.indent_width` | Number of spaces for indentation | 4 |
|
|
195
|
+
|
|
196
|
+
`sql_keywords`, `function_names` and `sql_decorators` **replace** the built-in lists rather than extending them. Copy the defaults you still rely on from the [template](https://github.com/flyersworder/sqlnbfmt/blob/main/config.yaml); for example, keep `sql` in `function_names` or Marimo's `mo.sql()` calls stop being formatted.
|
|
180
197
|
|
|
181
198
|
## Examples
|
|
182
199
|
|
|
@@ -189,20 +206,20 @@ execute_sql("""SELECT a.col1, b.col2 FROM table_a a JOIN table_b b ON a.id = b.a
|
|
|
189
206
|
|
|
190
207
|
After formatting:
|
|
191
208
|
```python
|
|
192
|
-
execute_sql(
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
JOIN
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
209
|
+
execute_sql(
|
|
210
|
+
"""
|
|
211
|
+
SELECT
|
|
212
|
+
a.col1,
|
|
213
|
+
b.col2
|
|
214
|
+
FROM table_a AS a
|
|
215
|
+
JOIN table_b AS b
|
|
216
|
+
ON a.id = b.a_id
|
|
217
|
+
WHERE
|
|
218
|
+
a.status = 'active'
|
|
219
|
+
ORDER BY
|
|
220
|
+
a.created_at DESC
|
|
221
|
+
"""
|
|
222
|
+
)
|
|
206
223
|
```
|
|
207
224
|
|
|
208
225
|
### Marimo Notebook
|
|
@@ -220,17 +237,17 @@ After formatting:
|
|
|
220
237
|
@app.cell
|
|
221
238
|
def _(mo):
|
|
222
239
|
_df = mo.sql(
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
)
|
|
240
|
+
f"""
|
|
241
|
+
SELECT
|
|
242
|
+
id,
|
|
243
|
+
name
|
|
244
|
+
FROM users
|
|
245
|
+
WHERE
|
|
246
|
+
active = 1
|
|
247
|
+
ORDER BY
|
|
248
|
+
name
|
|
249
|
+
"""
|
|
250
|
+
)
|
|
234
251
|
return
|
|
235
252
|
```
|
|
236
253
|
|
|
@@ -238,7 +255,7 @@ def _(mo):
|
|
|
238
255
|
|
|
239
256
|
**SQL not being formatted?**
|
|
240
257
|
- Ensure the string contains at least 2 SQL keywords or a recognizable pattern like `SELECT...FROM`
|
|
241
|
-
- Check that the function name is in the recognized list (
|
|
258
|
+
- Check that the function name is in the recognized list (add custom ones via `function_names` in `[tool.sqlnbfmt]` or `--config`)
|
|
242
259
|
|
|
243
260
|
**Comments being modified?**
|
|
244
261
|
- Python comments (`#`) are preserved. SQL comments (`--`) inside strings are converted to `/* */` block comments by sqlglot.
|