Skip to main content

sqlalchemy-deprecated-column

PyPi PyVersions Coverage License

Safely remove SQLAlchemy ORM columns through a gradual deprecation process. Inspired by django-deprecate-fields.

Installation

pip install sqlalchemy-deprecated-column

While the project is pre-1.0, breaking changes may land in minor releases (e.g. 0.1.x → 0.2.0), following the SemVer convention for 0.y.z versions. Patch releases (0.1.3 → 0.1.4) remain backwards-compatible. To avoid surprise breakage, pin to a specific minor version:

sqlalchemy-deprecated-column~=0.1.0

How it works

Removing a column from a live database requires coordination between code and schema changes. Dropping the column in a single step would break any running application instances that still reference it. deprecated_column() lets you do this safely in three steps:

  1. Deprecate: replace mapped_column() with deprecated_column() and run an Alembic migration. The column stays in the database but becomes nullable if it wasn't already.
  2. Deploy: the column is hidden from the ORM — it no longer appears in any generated SQL. Any remaining code that reads or writes the column gets a DeprecationWarning at runtime (or raises ColumnDeprecatedError if raise_on_access=True), making stale references easy to find and remove.
  3. Remove: once all references are gone, delete the deprecated_column() definition from the model and run a final migration to drop the column from the database.

Usage

deprecated_column() is a drop-in replacement for mapped_column() and accepts the same arguments. For columns declared with only a bare Mapped[T] annotation, add deprecated_column() with no arguments.

Before:

class User(Base):
    __tablename__ = "users"

    id: Mapped[int] = mapped_column(primary_key=True)
    email: Mapped[str] = mapped_column(String)
    old_username: Mapped[str] = mapped_column(String(200), index=True)
    old_email: Mapped[str]

After:

from sqlalchemy_deprecated_column import deprecated_column

class User(Base):
    __tablename__ = "users"

    id: Mapped[int] = mapped_column(primary_key=True)
    email: Mapped[str] = mapped_column(String)
    old_username: Mapped[str] = deprecated_column(String(200), index=True)
    old_email: Mapped[str] = deprecated_column()

While the column is deprecated the library:

  • Hides it from the ORM: the column is excluded from all generated SQL queries — existing application code stays compatible even after the column is eventually dropped from the database.
  • Warns on instance read: instance.old_username returns None and emits a DeprecationWarning naming the model and column, so the call site is easy to locate.
  • Warns on class-level reference: User.old_username (e.g. in filter expressions) emits a DeprecationWarning and evaluates to SQL NULL.
  • Warns on write and discards the value: instance.old_username = "x" emits a DeprecationWarning and silently drops the value, so no stale data is written to the database.

Pass raise_on_access=True to raise a ColumnDeprecatedError on any access instead of emitting a warning. This is useful when you want to enforce that all stale references are removed — for example, by letting the exception surface in tests or CI:

from sqlalchemy_deprecated_column import ColumnDeprecatedError, deprecated_column

old_username: Mapped[str] = deprecated_column(String(200), raise_on_access=True)

Alembic integration

Add the following at the top of alembic/env.py, before any model imports:

import sqlalchemy_deprecated_column
sqlalchemy_deprecated_column.configure(alembic_mode=True)

# model imports must come after configure()
from myapp import mymodel
target_metadata = mymodel.Base.metadata

In Alembic mode, deprecated_column() acts as mapped_column(nullable=True). Alembic will:

  • Not generate DROP COLUMN for deprecated columns.
  • Generate ALTER TABLE … DROP NOT NULL if the column was originally non-nullable. This is needed because once the column is deprecated the ORM stops including it in INSERT statements — a NOT NULL column without a value would cause those inserts to fail.

Requirements

  • Python 3.10+
  • SQLAlchemy 2.0+

License

The code in this project is licensed under MIT license. See LICENSE for more information.

Metadata

Release files for sqlalchemy-deprecated-column 0.3.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for sqlalchemy-deprecated-column 0.3.0
File Size Uploaded
sqlalchemy_deprecated_column-0.3.0.tar.gz 5.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for sqlalchemy-deprecated-column 0.3.0
File Interpreter ABI Platform
sqlalchemy_deprecated_column-0.3.0-py3-none-any.whl Python 3 none any Details

Total release size: 11.8 kB

Release files / sqlalchemy_deprecated_column-0.3.0.tar.gz

Download URL sqlalchemy_deprecated_column-0.3.0.tar.gz
Size 5.1 kB
Tags Source
SHA-256 checksum
How to use checksums
656a779c5f954c53a9403ab0292a3a3e9311e5cbee765e9c2f5ae5ec3587a12c
BLAKE2b-256 checksum
How to use checksums
cfcc679d3cfa7abf022f7407f6eecd8f66fa2122703496d7d6f36142fe07d9f5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.11.13 {"installer":{"name":"uv","version":"0.11.13","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 / sqlalchemy_deprecated_column-0.3.0-py3-none-any.whl

Download URL sqlalchemy_deprecated_column-0.3.0-py3-none-any.whl
Size 6.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
3d38db400904a43e1493f62e9ee0eeb323a1f70305d92f53219c3b1d82e8eecf
BLAKE2b-256 checksum
How to use checksums
28a1a7ee836630a10edc64569a3a9d0bba95e5bfd601028d1df69beba2059d78
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.11.13 {"installer":{"name":"uv","version":"0.11.13","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 history Release notifications | RSS feed

This release

0.3.0 This release

2 release files

0.2.0

2 release files

0.1.4

2 release files

0.1.3

2 release files

0.1.2

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page