Skip to main content

Rails annotate_models for modern SQLAlchemy 2.x + Alembic projects.

Project description

sqlalchemy-annotate

Rails annotate_models for modern SQLAlchemy 2.x + Alembic projects.

It keeps a Schema Information comment block alongside every model class, in sync with your actual SQLAlchemy metadata, so reviewers and editors see the table shape without opening a database or a migration. The block sits below the class by default; flip position = "top" to put it above instead.

class User(Base):
    __tablename__ = "users"
    ...

# == Schema Information
#
# Table name: users
#
# id         : integer, primary key
# email      : varchar, not null
# created_at : timestamp
#
# Indexes
#   ix_users_email (email) UNIQUE
#
# Foreign Keys
#   profile_id -> profiles.id (ON DELETE CASCADE)
#
# == End Schema Information

Why it is safe

  • No database required. Everything is read from Base.metadata / __table__. A connection URL, if you pass one, is parsed only for its dialect so types compile correctly offline. No engine is ever connected.
  • No regex rewriting. Files are edited through a single libcst transformer. Imports, comments, blank lines and Black formatting are preserved byte-for-byte; only the region between the markers is touched.
  • Idempotent. Running generate twice produces no diff, which is what makes check reliable in CI and pre-commit.

Install

pip install sqlalchemy-annotate      # or: uv pip install sqlalchemy-annotate

Usage

sqlalchemy-annotate generate
sqlalchemy-annotate generate --models app.models --engine postgresql://localhost/db
sqlalchemy-annotate check        # exit 1 if stale (CI)
sqlalchemy-annotate remove       # strip every block
sqlalchemy-annotate generate --dry-run     # show the diff, write nothing

--models points at the dotted package path. Subpackages are imported recursively (app/models/user.py, app/models/post.py, ...), so every model registers regardless of how many files you split them across. A broken or circularly-importing module is reported as a warning and skipped, never fatal.

Configuration

Put defaults in pyproject.toml; CLI flags override them.

[tool.sqlalchemy-annotate]
models = "app.models"
engine = "postgresql+asyncpg://..."   # dialect only, never connected
include_indexes = true
include_foreign_keys = true
include_relationships = false
normalize_types = false               # true -> Rails-style (bigint, varchar(255))
sort = "definition"                   # or "alphabetical"
position = "bottom"                   # or "top" to place the block above the class
exclude = ["audit_*", "*_history"]

Type rendering

By default types are truthful: rendered exactly as SQLAlchemy compiles them for the resolved dialect (Mapped[int] PK -> integer, Mapped[str] -> varchar). Set normalize_types = true for Rails-style fabrication (autoincrement int PK -> bigint, unlengthed string -> varchar(255)).

The dialect is --dialect if given, else the backend of engine (async drivers collapse to their sync backend), else PostgreSQL.

Alembic / pre-commit

Run it right after a schema change:

alembic revision --autogenerate -m "add users"
alembic upgrade head
sqlalchemy-annotate generate

.pre-commit-config.yaml:

repos:
  - repo: https://github.com/abhinavs/sqlalchemy-annotate
    rev: v0.1.1
    hooks:
      - id: sqlalchemy-annotate

CI gate:

- run: sqlalchemy-annotate check

How it works

Module Responsibility
discovery.py import-walk the package, collect mapped classes -> files
schema.py Table/Mapper -> ModelSchema value objects (pure)
formatter.py ModelSchema -> comment lines (pure, pluggable renderer)
parser.py libcst helpers: build lines, locate the existing block
writer.py one libcst transformer: insert / replace / remove
config.py defaults <- pyproject.toml <- CLI
cli.py typer commands; heavy imports stay lazy

Roadmap (designed, not built)

The formatter is already a swappable Renderer behind the sqlalchemy_annotate.renderers entry-point group, leaving room for: Markdown schema export, ER diagram generation, a schema diff command, watch mode, and an IDE/VSCode integration.

Project

License

MIT (c) 2026 Abhinav Saxena

Project details


Download files

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

Source Distribution

sqlalchemy_annotate-0.1.1.tar.gz (23.6 kB view details)

Uploaded Source

Built Distribution

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

sqlalchemy_annotate-0.1.1-py3-none-any.whl (20.5 kB view details)

Uploaded Python 3

File details

Details for the file sqlalchemy_annotate-0.1.1.tar.gz.

File metadata

  • Download URL: sqlalchemy_annotate-0.1.1.tar.gz
  • Upload date:
  • Size: 23.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for sqlalchemy_annotate-0.1.1.tar.gz
Algorithm Hash digest
SHA256 d1695360994fd04e3886a2f798e76bf1c143e35022241246035fd295e1d8e959
MD5 57399868f63b5a980b1559f2dfd76602
BLAKE2b-256 7238d6b346e481bf1ffec781ebe040fcdee050b2b51c1316044c76e29fa8f564

See more details on using hashes here.

Provenance

The following attestation bundles were made for sqlalchemy_annotate-0.1.1.tar.gz:

Publisher: release.yml on abhinavs/sqlalchemy-annotate

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

File details

Details for the file sqlalchemy_annotate-0.1.1-py3-none-any.whl.

File metadata

File hashes

Hashes for sqlalchemy_annotate-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 009b422d65ae111101c84d926592a3c11290cef5d7498982524e3ebd22e50631
MD5 caf92e66fe5f27cc177482499e5fb18f
BLAKE2b-256 c3d644023b3dfa729a9557abfc004da002c0821c8da59abb803e8aa21f0f7aa4

See more details on using hashes here.

Provenance

The following attestation bundles were made for sqlalchemy_annotate-0.1.1-py3-none-any.whl:

Publisher: release.yml on abhinavs/sqlalchemy-annotate

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

Supported by

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