ddlglot 26.3.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.
Files changed (47) hide show
  1. ddlglot-26.3.0/.github/pull_request_template.md +25 -0
  2. ddlglot-26.3.0/.github/workflows/ci.yml +86 -0
  3. ddlglot-26.3.0/.github/workflows/release.yml +71 -0
  4. ddlglot-26.3.0/.gitignore +5 -0
  5. ddlglot-26.3.0/.pre-commit-config.yaml +16 -0
  6. ddlglot-26.3.0/.python-version +1 -0
  7. ddlglot-26.3.0/AGENTS.md +248 -0
  8. ddlglot-26.3.0/CHANGELOG.md +32 -0
  9. ddlglot-26.3.0/PKG-INFO +137 -0
  10. ddlglot-26.3.0/PLAN.md +356 -0
  11. ddlglot-26.3.0/README.md +123 -0
  12. ddlglot-26.3.0/commitlint.config.js +27 -0
  13. ddlglot-26.3.0/docs/api_reference.rst +121 -0
  14. ddlglot-26.3.0/docs/conf.py +25 -0
  15. ddlglot-26.3.0/docs/core_builder.rst +153 -0
  16. ddlglot-26.3.0/docs/index.rst +51 -0
  17. ddlglot-26.3.0/docs/quickstart.rst +162 -0
  18. ddlglot-26.3.0/docs/variants/bigquery.rst +52 -0
  19. ddlglot-26.3.0/docs/variants/duckdb.rst +35 -0
  20. ddlglot-26.3.0/docs/variants/hive.rst +62 -0
  21. ddlglot-26.3.0/docs/variants/index.rst +34 -0
  22. ddlglot-26.3.0/docs/variants/postgres.rst +26 -0
  23. ddlglot-26.3.0/docs/variants/spark_delta.rst +79 -0
  24. ddlglot-26.3.0/init.md +544 -0
  25. ddlglot-26.3.0/prd.md +297 -0
  26. ddlglot-26.3.0/pyproject.toml +45 -0
  27. ddlglot-26.3.0/src/ddlglot/__init__.py +69 -0
  28. ddlglot-26.3.0/src/ddlglot/builder.py +216 -0
  29. ddlglot-26.3.0/src/ddlglot/exceptions.py +78 -0
  30. ddlglot-26.3.0/src/ddlglot/properties.py +78 -0
  31. ddlglot-26.3.0/src/ddlglot/registry.py +94 -0
  32. ddlglot-26.3.0/src/ddlglot/variants/__init__.py +22 -0
  33. ddlglot-26.3.0/src/ddlglot/variants/bigquery.py +111 -0
  34. ddlglot-26.3.0/src/ddlglot/variants/duckdb.py +122 -0
  35. ddlglot-26.3.0/src/ddlglot/variants/hive.py +182 -0
  36. ddlglot-26.3.0/src/ddlglot/variants/postgres.py +85 -0
  37. ddlglot-26.3.0/src/ddlglot/variants/spark_delta.py +169 -0
  38. ddlglot-26.3.0/tests/conftest.py +3 -0
  39. ddlglot-26.3.0/tests/test_bigquery.py +63 -0
  40. ddlglot-26.3.0/tests/test_core.py +253 -0
  41. ddlglot-26.3.0/tests/test_duckdb.py +52 -0
  42. ddlglot-26.3.0/tests/test_hive.py +107 -0
  43. ddlglot-26.3.0/tests/test_postgres.py +87 -0
  44. ddlglot-26.3.0/tests/test_registry.py +156 -0
  45. ddlglot-26.3.0/tests/test_spark_delta.py +135 -0
  46. ddlglot-26.3.0/tests/test_validation.py +130 -0
  47. ddlglot-26.3.0/uv.lock +308 -0
@@ -0,0 +1,25 @@
1
+ ## Description
2
+
3
+ <!-- Describe your changes -->
4
+
5
+ ## Type of Change
6
+
7
+ - [ ] Bug fix
8
+ - [ ] New feature
9
+ - [ ] Breaking change
10
+ - [ ] Documentation update
11
+ - [ ] Refactoring
12
+
13
+ ## Checklist
14
+
15
+ - [ ] My code follows the style guidelines
16
+ - [ ] I have performed a self-review
17
+ - [ ] I have commented my code where necessary
18
+ - [ ] I have updated the documentation
19
+ - [ ] My changes generate no new warnings
20
+ - [ ] I have added tests that prove my fix is effective
21
+ - [ ] New and existing tests pass locally
22
+
23
+ ## Related Issue
24
+
25
+ <!-- Link to related issue (e.g., "Closes #123") -->
@@ -0,0 +1,86 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ jobs:
10
+ test:
11
+ name: Test
12
+ runs-on: ubuntu-latest
13
+
14
+ steps:
15
+ - uses: actions/checkout@v4
16
+
17
+ - name: Set up Python
18
+ uses: actions/setup-python@v5
19
+ with:
20
+ python-version: "3.13"
21
+
22
+ - name: Install uv
23
+ uses: astral-sh/setup-uv@v4
24
+ with:
25
+ enable-cache: true
26
+
27
+ - name: Install dependencies
28
+ run: uv sync --all-extras
29
+
30
+ - name: Lint
31
+ run: uv run ruff check src tests
32
+
33
+ - name: Format check
34
+ run: uv run ruff format --check src tests
35
+
36
+ - name: Type check
37
+ run: uv run mypy src
38
+
39
+ - name: Run tests
40
+ run: uv run pytest tests --cov=ddlglot --cov-report=term-missing --cov-report=xml
41
+
42
+ - name: Upload coverage
43
+ uses: actions/upload-artifact@v4
44
+ with:
45
+ name: coverage
46
+ path: coverage.xml
47
+ retention-days: 1
48
+
49
+ - name: Upload to Codecov
50
+ uses: codecov/codecov-action@v4
51
+ with:
52
+ files: coverage.xml
53
+ continue-on-error: true
54
+
55
+ build:
56
+ name: Build
57
+ needs: test
58
+ runs-on: ubuntu-latest
59
+ steps:
60
+ - uses: actions/checkout@v4
61
+
62
+ - name: Set up Python
63
+ uses: actions/setup-python@v5
64
+ with:
65
+ python-version: "3.13"
66
+
67
+ - name: Install uv
68
+ uses: astral-sh/setup-uv@v4
69
+
70
+ - name: Install build
71
+ run: uv pip install --system build hatch
72
+
73
+ - name: Build package
74
+ run: python -m build
75
+
76
+ - name: Verify build
77
+ run: |
78
+ pip install dist/*.whl --force-reinstall
79
+ python -c "import ddlglot; print('ddlglot imported successfully')"
80
+
81
+ - name: Upload artifacts
82
+ uses: actions/upload-artifact@v4
83
+ with:
84
+ name: dist
85
+ path: dist/
86
+ retention-days: 5
@@ -0,0 +1,71 @@
1
+ name: Release
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v*"
7
+
8
+ jobs:
9
+ test:
10
+ name: Test before release
11
+ runs-on: ubuntu-latest
12
+ steps:
13
+ - uses: actions/checkout@v4
14
+
15
+ - name: Set up Python
16
+ uses: actions/setup-python@v5
17
+ with:
18
+ python-version: "3.13"
19
+
20
+ - name: Install uv
21
+ uses: astral-sh/setup-uv@v4
22
+
23
+ - name: Install dependencies
24
+ run: uv sync --all-extras
25
+
26
+ - name: Lint
27
+ run: uv run ruff check src tests
28
+
29
+ - name: Type check
30
+ run: uv run mypy src
31
+
32
+ - name: Run tests
33
+ run: uv run pytest tests --cov=ddlglot
34
+
35
+ release:
36
+ name: Publish to PyPI
37
+ needs: test
38
+ runs-on: ubuntu-latest
39
+ environment:
40
+ name: pypi
41
+ url: https://pypi.org/project/ddlglot/
42
+ permissions:
43
+ id-token: write
44
+
45
+ steps:
46
+ - uses: actions/checkout@v4
47
+
48
+ - name: Set up Python
49
+ uses: actions/setup-python@v5
50
+ with:
51
+ python-version: "3.13"
52
+
53
+ - name: Install uv
54
+ uses: astral-sh/setup-uv@v4
55
+
56
+ - name: Install build
57
+ run: uv pip install --system build hatch
58
+
59
+ - name: Build package
60
+ run: python -m build
61
+
62
+ - name: Publish to PyPI
63
+ uses: pypa/gh-action-pypi-publish@release/v1
64
+
65
+ - name: Create GitHub Release
66
+ uses: softprops/action-gh-release@v2
67
+ with:
68
+ files: dist/*
69
+ generate_release_notes: true
70
+ env:
71
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -0,0 +1,5 @@
1
+ .venv/
2
+ __pycache__/
3
+ *.pyc
4
+ .git/
5
+
@@ -0,0 +1,16 @@
1
+ repos:
2
+ - repo: https://github.com/pre-commit/pre-commit-hooks
3
+ rev: v4.5.0
4
+ hooks:
5
+ - id: trailing-whitespace
6
+ - id: end-of-file-fixer
7
+ - id: check-yaml
8
+ - id: check-added-large-files
9
+ - id: check-toml
10
+
11
+ - repo: https://github.com/astral-sh/ruff-pre-commit
12
+ rev: v0.1.8
13
+ hooks:
14
+ - id: ruff
15
+ args: [--fix]
16
+ - id: ruff-format
@@ -0,0 +1 @@
1
+ 3.13
@@ -0,0 +1,248 @@
1
+ # AGENTS.md - Developer Guide for ddlglot
2
+
3
+ ## Overview
4
+
5
+ `ddlglot` is a Python library that provides a fluent builder API for generating DDL (Data Definition Language) statements using SQLGlot's AST. It supports multiple SQL dialects (PostgreSQL, SQLite, DuckDB, Spark/Delta Lake, etc.).
6
+
7
+ ---
8
+
9
+ ## 1. Commands
10
+
11
+ ### Build & Install
12
+
13
+ ```bash
14
+ # Install the package in editable mode
15
+ pip install -e .
16
+
17
+ # Build the package
18
+ hatch build
19
+ ```
20
+
21
+ ### Testing
22
+
23
+ ```bash
24
+ # Run all tests
25
+ pytest
26
+
27
+ # Run a single test file
28
+ pytest tests/test_core.py
29
+
30
+ # Run a single test function
31
+ pytest tests/test_core.py::test_create_table_basic
32
+
33
+ # Run tests with verbose output
34
+ pytest -v
35
+
36
+ # Run tests with coverage
37
+ pytest --cov=ddlglot --cov-report=term-missing
38
+ ```
39
+
40
+ ### Linting & Type Checking
41
+
42
+ ```bash
43
+ # Run ruff (linter + formatter)
44
+ ruff check .
45
+ ruff format .
46
+
47
+ # Run mypy (type checking)
48
+ mypy src/ddlglot
49
+ ```
50
+
51
+ ---
52
+
53
+ ## 2. Code Style Guidelines
54
+
55
+ ### General
56
+
57
+ - **Language**: English for all code, comments, and documentation
58
+ - **Python version**: 3.13+
59
+ - **Build system**: hatchling (via `pyproject.toml`)
60
+
61
+ ### Imports
62
+
63
+ ```python
64
+ # Standard library first
65
+ from __future__ import annotations
66
+ from typing import Any, Dict, List, Optional, Tuple, Union
67
+
68
+ # Third-party packages
69
+ from sqlglot import expressions as exp
70
+
71
+ # Local modules
72
+ from ddlglot.builder import CreateBuilder, create
73
+ from ddlglot.variants.spark_delta import create_spark_delta
74
+ ```
75
+
76
+ - Use `from __future__ import annotations` for forward references
77
+ - Always use explicit relative imports for package modules (`from ..builder import ...`)
78
+ - Alphabetize imports within each group
79
+
80
+ ### Formatting
81
+
82
+ - **Line length**: 100 characters max
83
+ - **Indentation**: 4 spaces (no tabs)
84
+ - **Quotes**: Double quotes for strings, except when string contains double quotes
85
+ - **Trailing commas**: Use in multi-line expressions
86
+
87
+ ```python
88
+ # Good
89
+ def example(
90
+ arg1: str,
91
+ arg2: int,
92
+ ) -> Dict[str, Any]:
93
+ return {"arg1": arg1, "arg2": arg2}
94
+
95
+ # Bad
96
+ def example(arg1: str, arg2: int) -> Dict[str, Any]:
97
+ return {"arg1": arg1, "arg2": arg2}
98
+ ```
99
+
100
+ ### Types
101
+
102
+ - Use explicit type hints for all function parameters and return types
103
+ - Use `Optional[X]` instead of `X | None` for Python < 3.10 compatibility
104
+ - Prefer type aliases for complex types:
105
+
106
+ ```python
107
+ Lit = Union[str, int, float, bool]
108
+ ```
109
+
110
+ ### Naming Conventions
111
+
112
+ | Element | Convention | Example |
113
+ |---------|------------|---------|
114
+ | Modules | snake_case | `spark_delta.py` |
115
+ | Classes | PascalCase | `CreateBuilder` |
116
+ | Functions | snake_case | `create()`, `to_ast()` |
117
+ | Variables | snake_case | `self._table` |
118
+ | Constants | UPPER_SNAKE_CASE | `DELTA_FORMAT` |
119
+ | Private members | `_leading_underscore` | `self._columns` |
120
+
121
+ ### Classes & Methods
122
+
123
+ - Use fluent builder pattern: methods return `self` for chaining
124
+ - Use `__init__` for object construction
125
+ - Use `@staticmethod` for pure utility functions
126
+
127
+ ```python
128
+ class CreateBuilder:
129
+ def name(self, table: str) -> "CreateBuilder":
130
+ self._table = table
131
+ return self
132
+ ```
133
+
134
+ ### Error Handling
135
+
136
+ - Use explicit exceptions with descriptive messages
137
+ - Raise `ValueError` for invalid arguments
138
+
139
+ ```python
140
+ def to_ast(self) -> exp.Create:
141
+ if not self._table:
142
+ raise ValueError("Falta .name(<tabla>)")
143
+ ```
144
+
145
+ ### Docstrings
146
+
147
+ - Use Google-style docstrings for public APIs:
148
+
149
+ ```python
150
+ def sql(self, dialect: Optional[str] = None, pretty: bool = False) -> str:
151
+ """Generate SQL DDL string.
152
+
153
+ Args:
154
+ dialect: SQL dialect (e.g., "postgres", "spark").
155
+ pretty: Enable pretty formatting.
156
+
157
+ Returns:
158
+ The generated SQL string.
159
+ """
160
+ return self.to_ast().sql(dialect=dialect, pretty=pretty)
161
+ ```
162
+
163
+ - **Do not add comments** unless explicitly requested
164
+
165
+ ### Testing
166
+
167
+ - Place tests in `tests/` directory
168
+ - Use `pytest` as test runner
169
+ - Follow naming: `test_<module>.py`
170
+ - One test class per module, test functions prefixed with `test_`
171
+
172
+ ```python
173
+ # tests/test_core.py
174
+ import pytest
175
+ from ddlglot import create
176
+
177
+ def test_create_table_basic():
178
+ sql = (
179
+ create("table")
180
+ .name("public.users")
181
+ .column("id", "INT", not_null=True)
182
+ .sql(dialect="postgres")
183
+ )
184
+ assert "CREATE TABLE" in sql
185
+ ```
186
+
187
+ ---
188
+
189
+ ## 3. Project Structure
190
+
191
+ ```
192
+ ddlglot/
193
+ ├── pyproject.toml
194
+ ├── src/ddlglot/
195
+ │ ├── __init__.py
196
+ │ ├── builder.py # Core fluent builder
197
+ │ ├── properties.py # Property helpers
198
+ │ └── variants/
199
+ │ ├── __init__.py
200
+ │ └── spark_delta.py # Spark + Delta preset
201
+ └── tests/
202
+ ├── test_core.py
203
+ └── test_spark_delta.py
204
+ ```
205
+
206
+ ---
207
+
208
+ ## 4. Key Libraries
209
+
210
+ - **sqlglot**: AST and SQL generation (installed as dependency)
211
+ - **pytest**: Testing framework
212
+ - **ruff**: Linting and formatting
213
+ - **mypy**: Static type checking
214
+
215
+ ---
216
+
217
+ ## 5. Dialect-Specific Notes
218
+
219
+ - The builder is **dialect-agnostic** at the AST level
220
+ - Dialect-specific generation happens at `.sql(dialect=...)` call
221
+ - Supported dialects: `postgres`, `sqlite`, `duckdb`, `spark`, `databricks`, etc.
222
+ - SQLGlot's `Generator` handles dialect-specific syntax (e.g., `PARTITIONED BY` placement)
223
+
224
+ ---
225
+
226
+ ## 6. Common Tasks
227
+
228
+ ### Adding a New Dialect Preset
229
+
230
+ 1. Create `src/ddlglot/variants/<dialect>.py`
231
+ 2. Extend `CreateBuilder` following the pattern in `spark_delta.py`
232
+ 3. Export factory function `<dialect>_builder()`
233
+ 4. Add tests in `tests/test_<dialect>.py`
234
+
235
+ ### Adding New DDL Properties
236
+
237
+ 1. Add method to `CreateBuilder` (e.g., `.tblproperties()`)
238
+ 2. Implement property building in `_build_properties()`
239
+ 3. Use appropriate SQLGlot expression type (e.g., `exp.Properties`, `exp.Property`)
240
+ 4. Add tests covering the new property
241
+
242
+ ---
243
+
244
+ ## 7. Git Workflow
245
+
246
+ - Use Conventional Commits: `feat(scope): description`, `fix(scope): description`
247
+ - Run `pytest` and `ruff check .` before committing
248
+ - Never commit directly to `main`; use feature branches
@@ -0,0 +1,32 @@
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.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [26.3.0] - 2026-03-20
9
+
10
+ ### Added
11
+
12
+ - Core builder with fluent API for DDL generation
13
+ - Support for multiple SQL dialects:
14
+ - Spark+Delta Lake with CDF support
15
+ - Apache Hive with SERDE/ROW FORMAT
16
+ - PostgreSQL
17
+ - DuckDB
18
+ - BigQuery
19
+ - Plugin registry system for custom variants
20
+ - Dialect-specific validation
21
+ - Comprehensive test suite (92 tests)
22
+ - GitHub Actions CI/CD
23
+ - Sphinx documentation
24
+ - Pre-commit hooks
25
+
26
+ ### Features
27
+
28
+ - `create()` factory function for generic DDL
29
+ - `create_spark_delta()`, `create_hive()`, etc. for dialect-specific DDL
30
+ - Fluent method chaining for all DDL operations
31
+ - Type hints and validation
32
+ - SQLGlot-powered AST generation
@@ -0,0 +1,137 @@
1
+ Metadata-Version: 2.4
2
+ Name: ddlglot
3
+ Version: 26.3.0
4
+ Summary: Fluent DDL builder using SQLGlot AST
5
+ Author-email: alexsyntonize <249129647+alexsyntonize@users.noreply.github.com>
6
+ Requires-Python: >=3.13
7
+ Requires-Dist: sqlglot>=25.0.0
8
+ Provides-Extra: dev
9
+ Requires-Dist: mypy>=1.8; extra == 'dev'
10
+ Requires-Dist: pytest-cov>=4.0; extra == 'dev'
11
+ Requires-Dist: pytest>=8.0; extra == 'dev'
12
+ Requires-Dist: ruff>=0.4.0; extra == 'dev'
13
+ Description-Content-Type: text/markdown
14
+
15
+ # ddlglot
16
+
17
+ **Fluent DDL builder API using SQLGlot's AST**
18
+
19
+ [![CI](https://github.com/alexmarco/ddlglot/actions/workflows/ci.yml/badge.svg)](https://github.com/alexmarco/ddlglot/actions/workflows/ci.yml)
20
+ [![PyPI version](https://img.shields.io/pypi/v/ddlglot.svg)](https://pypi.org/project/ddlglot/)
21
+ [![Python versions](https://img.shields.io/pypi/pyversions/ddlglot.svg)](https://pypi.org/project/ddlglot/)
22
+
23
+ ## Features
24
+
25
+ - **Fluent API**: Chain method calls to build DDL statements
26
+ - **Multiple Dialects**: Support for Spark, Delta Lake, Hive, PostgreSQL, DuckDB, BigQuery
27
+ - **Type Safe**: Full type hints and validation
28
+ - **SQLGlot Powered**: Leverage SQLGlot's AST for SQL generation
29
+
30
+ ## Installation
31
+
32
+ ```bash
33
+ pip install ddlglot
34
+ ```
35
+
36
+ Or with uv:
37
+
38
+ ```bash
39
+ uv add ddlglot
40
+ ```
41
+
42
+ ## Quick Start
43
+
44
+ ```python
45
+ from ddlglot import create
46
+
47
+ # Create a table
48
+ sql = (
49
+ create("table")
50
+ .name("public.users")
51
+ .column("id", "INT", not_null=True)
52
+ .column("name", "VARCHAR(100)")
53
+ .sql(dialect="postgres")
54
+ )
55
+ # CREATE TABLE public.users (id INT NOT NULL, name VARCHAR(100))
56
+ ```
57
+
58
+ ## Dialect Variants
59
+
60
+ ### Spark+Delta
61
+
62
+ ```python
63
+ from ddlglot import create_spark_delta
64
+
65
+ sql = (
66
+ create_spark_delta()
67
+ .name("default.events")
68
+ .column("id", "INT")
69
+ .partitioned_by("event_date")
70
+ .enable_cdf(True)
71
+ .sql()
72
+ )
73
+ ```
74
+
75
+ ### Hive
76
+
77
+ ```python
78
+ from ddlglot import create_hive
79
+
80
+ sql = (
81
+ create_hive()
82
+ .name("default.events")
83
+ .column("id", "INT")
84
+ .stored_as("PARQUET")
85
+ .sql()
86
+ )
87
+ ```
88
+
89
+ ### BigQuery
90
+
91
+ ```python
92
+ from ddlglot import create_bigquery
93
+
94
+ sql = (
95
+ create_bigquery()
96
+ .name("project.dataset.events")
97
+ .column("id", "INT64")
98
+ .partitioned_by("event_date")
99
+ .cluster_by("user_id")
100
+ .sql()
101
+ )
102
+ ```
103
+
104
+ ## Validation
105
+
106
+ The library validates dialect-specific constraints:
107
+
108
+ ```python
109
+ from ddlglot import create_duckdb
110
+ from ddlglot.exceptions import UnsupportedFeatureError
111
+
112
+ # DuckDB doesn't support partitioning
113
+ try:
114
+ create_duckdb().name("test").partitioned_by("date").sql()
115
+ except UnsupportedFeatureError as e:
116
+ print(f"Error: {e}")
117
+ ```
118
+
119
+ ## Development
120
+
121
+ ```bash
122
+ # Install dependencies
123
+ pip install -e ".[dev]"
124
+
125
+ # Run tests
126
+ pytest tests/
127
+
128
+ # Lint
129
+ ruff check src tests
130
+
131
+ # Type check
132
+ mypy src
133
+ ```
134
+
135
+ ## License
136
+
137
+ MIT License