Skip to main content

Tools for waudit: SQL generation, Alembic ops, SQLAlchemy mixins

Project description

waudit-tools

Utilities for CDC-based audit log systems. SQL generation, custom Alembic operations, and SQLAlchemy mixins for PostgreSQL + Debezium pipelines.

Installation

With pip:

pip install waudit-tools

With uv:

uv pip install waudit-tools

Requires Python 3.11+.


Quick Start

Alembic migration (recommended)

Create an empty migration:

alembic revision -m "setup waudit"

upgrade:

from alembic import op
from myproject.models import Base

def upgrade() -> None:
    op.waudit_setup_from_base(
        Base,
        exclude={"alembic_version"},
        create_heartbeat_table=True,
    )

downgrade:

def downgrade() -> None:
    op.waudit_remove_from_base(
        Base,
        exclude={"alembic_version"},
        drop_heartbeat_table=True,
    )

Use Cases

1. Manual table list

When you don't use a declarative base or want full control:

def upgrade() -> None:
    op.waudit_setup(
        include_audit_tables=["users", "articles", "comments"],
        exclude_audit_tables=["alembic_version", "spatial_ref_sys"],
        create_heartbeat_table=True,
        schema="public",
    )

def downgrade() -> None:
    op.waudit_remove(
        include_audit_tables=["users", "articles", "comments"],
        exclude_audit_tables=["alembic_version"],
        drop_heartbeat_table=True,
        schema="public",
    )

2. Single table

For targeted changes or incremental rollout:

def upgrade() -> None:
    op.waudit_setup_table("users", schema="public")

def downgrade() -> None:
    op.waudit_remove_table("users", schema="public")

3. Raw SQL generation (no Alembic)

Generate SQL strings for external tooling or manual execution:

from waudit_tools.sql.identity import generate_identity_sql, apply_identity_to_tables
from waudit_tools.sql.heartbeat import generate_heartbeat_sql, generate_drop_heartbeat_sql

# Single table
sql = generate_identity_sql("users", schema="public")
# ALTER TABLE public.users REPLICA IDENTITY FULL;

# Batch
batch = apply_identity_to_tables(["users", "articles", "comments"], schema="cms")

# Heartbeat
create_hb = generate_heartbeat_sql(schema="public")
drop_hb = generate_drop_heartbeat_sql(schema="public")

4. SQLAlchemy model mixins

Add last_modified_by to your models:

from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
from waudit_tools.sqlalchemy.mixins.str_mixin import WAuditStrMixin

class Base(DeclarativeBase):
    pass

class User(Base, WAuditStrMixin):
    __tablename__ = "users"
    id: Mapped[int] = mapped_column(primary_key=True)
    name: Mapped[str]
    # last_modified_by: str | None  -- injected by mixin

For UUID-based actor tracking:

from waudit_tools.sqlalchemy.mixins.uuid_mixin import WAuditUUIDMixin

class User(Base, WAuditUUIDMixin):
    __tablename__ = "users"
    id: Mapped[int] = mapped_column(primary_key=True)
    # last_modified_by: UUID | None  -- injected by mixin

5. Programmatic Alembic utils

If you build custom migration frameworks on top of Alembic:

from waudit_tools.alembic.utils import create_heartbeat, drop_heartbeat
from sqlalchemy.engine import Connection

def my_custom_setup(conn: Connection) -> None:
    create_heartbeat(conn, schema="public")
    # ... your logic

Why REPLICA IDENTITY FULL?

Debezium needs "before" values for UPDATE and DELETE events. PostgreSQL only sends the changed columns by default. REPLICA IDENTITY FULL forces Postgres to include the complete old row in the WAL, enabling full change-data-capture audit trails.


Architecture

waudit_tools/
├── alembic/
│   ├── setup.py      # WauditSetupOp, WauditSetupFromBaseOp, WauditSetupTableOp
│   ├── remove.py     # WauditRemoveOp, WauditRemoveFromBaseOp, WauditRemoveTableOp
│   ├── utils.py      # create_heartbeat, drop_heartbeat
│   └── __init__.py   # side-effect registration
├── sql/
│   ├── identity.py   # generate_identity_sql, apply_identity_to_tables
│   └── heartbeat.py  # generate_heartbeat_sql, generate_drop_heartbeat_sql
└── sqlalchemy/
    └── mixins/
        ├── str_mixin.py   # WAuditStrMixin
        └── uuid_mixin.py  # WAuditUUIDMixin

Development

This project uses uv for dependency management and builds.

git clone https://github.com/Mac3g0d/waudit-tools.git
cd waudit-tools

# Install with dev dependencies (uv will use the uv.lock file)
uv sync --group dev

# Run tests
uv run pytest

# Lint & typecheck
uv run ruff check src tests
uv run mypy src

# Build wheel + sdist
uv build

Quality gates:

  • ruff: select = ["ALL"]
  • mypy: strict mode
  • pytest-cov: 85% minimum (currently 100%)

License

MIT — see LICENSE.

Author

Wootya viktorzhirnov07@gmail.com

Links

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

waudit_tools-0.1.1.tar.gz (61.7 kB view details)

Uploaded Source

Built Distribution

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

waudit_tools-0.1.1-py3-none-any.whl (12.5 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: waudit_tools-0.1.1.tar.gz
  • Upload date:
  • Size: 61.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.7 {"installer":{"name":"uv","version":"0.11.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"22.04","id":"jammy","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for waudit_tools-0.1.1.tar.gz
Algorithm Hash digest
SHA256 90fd23e7f95c423a6ca961d628130997d474ac51708b4607f4215b7a763a1755
MD5 78f07cb5430af216abd4535a3b08a332
BLAKE2b-256 40978d4ee3249198070c1a31c6b5f1357cd37041bcef6f6ab04ca8e3a8ac1baa

See more details on using hashes here.

File details

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

File metadata

  • Download URL: waudit_tools-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 12.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.7 {"installer":{"name":"uv","version":"0.11.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"22.04","id":"jammy","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for waudit_tools-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 89817d59b26c95e9f29f86f4270491bf8c4e76d4c57fd9ace5c509e924ba8dbd
MD5 377b026190bfb95733cbf81f35626a36
BLAKE2b-256 6d8a90af7c7dab53ef2bff46be96e816f33d1eab76f53f16bdb116ea4b83b032

See more details on using hashes here.

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