sqlmodel-export
Export SQLAlchemy or SQLModel metadata as creation SQL for PostgreSQL, SQLite, or MySQL. Requires Python 3.10+ and SQLAlchemy 2.0 or 2.1; generation works offline without database credentials, database drivers, or Alembic.
Install and run
Install this checkout in your application's Python environment:
uv pip install /path/to/sqlmodel-export
uv pip install -e /path/to/your/application
Activate that environment before running the console command. For a uv-managed
application, you can instead add the local package with
uv add /path/to/sqlmodel-export and invoke the command with uv run.
Applications using SQLModel supply their own SQLModel installation.
sqlmodel-export myapp.models:Base.metadata --dialect postgresql --output schema.sql
sqlmodel-export myapp.models:SQLModel.metadata --dialect sqlite
sqlmodel-export myapp.models:metadata --dialect mysql
Omit --output to print SQL to stdout. --help shows the available arguments.
Targets use module.path:attribute.path, with Python identifiers in each dotted
segment. The resolved value must be a nonempty sqlalchemy.MetaData instance.
Register every model
Make the target module import every model whose table should be exported.
For example, myapp/models/__init__.py for a SQLModel application can contain:
from sqlmodel import SQLModel
from .user import User
from .order import Order
SQLAlchemy applications can expose their declarative Base in the same way.
Table registration happens when model definitions execute. Importing only
SQLModel produces empty metadata; importing only some models can produce an
incomplete schema that the exporter cannot detect. Install applications with a
src/ layout, or explicitly configure their Python import path. Resolution uses
the interpreter's ordinary import path and the attributes named in the target.
Python API
from sqlmodel_export import export_ddl, load_metadata
metadata = load_metadata("myapp.models:Base.metadata")
sql = export_ddl(metadata, dialect="postgresql")
Both functions validate the metadata. export_ddl returns the entire SQL string;
the caller chooses where to write it. Library calls preserve the caller's streams.
Export behavior
The output follows SQLAlchemy's metadata creation sequence, including applicable
tables, constraints, indexes, PostgreSQL enums, and creation hooks. Cyclic foreign
keys can produce separate ALTER TABLE statements on PostgreSQL and MySQL.
SQLite follows its own constraint and ALTER behavior. Each emitted fragment ends
with a semicolon, fragments are separated by a blank line, and output ends with
a newline. Ordering follows SQLAlchemy and may vary across versions or processes.
Use metadata valid for the chosen dialect and database server version.
Vendor-specific types retain their dialect requirements. Schemas, extensions,
externally managed enums (create_type=False), and other external objects must
already exist unless your creation hooks emit them. This is an initial creation
export; schema comparison, migrations, DROP scripts, and data export are outside
its scope.
Import only trusted application code whose initialization works offline. Imports and DDL hooks execute Python code, and that code can open its own connections. Hooks must support SQLAlchemy's mock-engine DDL contract, without result-bearing database queries. Custom DDL must emit complete SQL fragments, placing any final semicolon after the last comment. The CLI sends ordinary Python stdout writes during import and generation to stderr. Application code manages its own direct file-descriptor and subprocess output.
Generation completes in memory before the destination is written. For file
output, the parent directory must exist. The CLI writes a temporary UTF-8 file
with LF newlines in that directory, closes it, and replaces the destination.
Existing files are replaced automatically; existing permissions and ownership
are not guaranteed to be preserved. A destination symlink is replaced while its
referent stays intact. Relative paths use the working directory; - names a
literal file. Generation failure preserves existing files and emits no SQL to
stdout. A stdout write failure can leave partial output.
Successful exports exit 0, usage errors exit 2, and ordinary import, compilation, or output failures exit 1 with their original traceback. Application exits and interrupts retain Python behavior.
Development
uv sync --locked
uv run --locked pytest
uv run --locked --group compatibility pytest tests/compatibility
uv build
The default suite runs core tests. uv sync --locked creates a core environment
without SQLModel; the separate compatibility dependency group adds SQLModel.
The CI workflow runs every test under tests/ on pushes
to main and pull requests, using the Python and uv versions configured in the
workflow. It builds and installs a wheel in an isolated environment and enables
the compatibility dependency group before running pytest tests.
Installed-wheel tests use an isolated environment containing the wheel and its runtime dependencies only:
uv build
uv venv .venv-wheel
uv pip install --python .venv-wheel/bin/python dist/sqlmodel_export-0.1.0-py3-none-any.whl
SQLMODEL_EXPORT_WHEEL_PYTHON="$PWD/.venv-wheel/bin/python" uv run --locked --group compatibility pytest tests
Use the corresponding Scripts/python.exe path on Windows. Without
SQLMODEL_EXPORT_WHEEL_PYTHON, the installation suite reports skips. Compatibility
validation covers Python 3.14 with SQLAlchemy 2.0.54 and 2.1.4.
Build artifacts are written to
dist/; building does not publish them.
Release
Create the pypi environment in the GitHub repository and register a
Trusted Publisher
for the PyPI project using these values:
| Field | Value |
|---|---|
| Repository owner | himkt |
| Repository name | sqlmodel-export |
| Workflow filename | release.yml |
| Environment name | pypi |
For a new PyPI project, register a
pending publisher
with the project name sqlmodel-export and the same values.
Set project.version in pyproject.toml, run uv lock, and commit the changes.
Run the development checks, then push the release commit and a matching
v<version> tag to GitHub. For example, for version 0.1.0:
git push origin main
git tag v0.1.0
git push origin v0.1.0
The Release workflow verifies that the tag matches
uv version --short, builds the wheel and source distribution with uv build,
and publishes them to PyPI with uv publish. Authentication uses GitHub's OIDC
identity through Trusted Publishing.
Metadata
Release files for sqlmodel-export 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| sqlmodel_export-0.1.0.tar.gz | 45.8 kB | Without provenance | Details for sqlmodel_export-0.1.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| sqlmodel_export-0.1.0-py3-none-any.whl | Python 3 | none | any | Details for sqlmodel_export-0.1.0-py3-none-any.whl |
Total release size: 53.6 kB
Release files / sqlmodel_export-0.1.0.tar.gz
| Download URL | sqlmodel_export-0.1.0.tar.gz |
|---|---|
| Size | 45.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
97a5d1c7c1d27a281863f540902ee4ab61b15a5c8b1fe5ecb355990f13ca35b4
|
|
BLAKE2b-256 checksum How to use checksums |
237410b15fe99c4b8e0c02d27769c395a9ef6308515c850ad6490bcdc6e9ffe2
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.12.23 {"installer":{"name":"uv","version":"0.12.23","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / sqlmodel_export-0.1.0-py3-none-any.whl
| Download URL | sqlmodel_export-0.1.0-py3-none-any.whl |
|---|---|
| Size | 7.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
7e42ef6b9b7f4c0e0f98aeb599808fad9506a7de126065eadf46c3fc48a12ca0
|
|
BLAKE2b-256 checksum How to use checksums |
a929fc9434626082e794630239518c6a7a02f89c4819625f209b63173d6d05c8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.12.23 {"installer":{"name":"uv","version":"0.12.23","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Security for sqlmodel-export 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.