Skip to main content

alembic-adapter-sdk (python)

a small, dependency-free sdk for writing alembic external adapters in python.

network engineering lives in python, so adapters should be writable there too. alembic delegates backend i/o to external adapters: standalone programs the alembic host spawns as subprocesses, exchanging one json request and one json response over stdin/stdout. this sdk handles that protocol so you only write the backend logic.

the import package is alembic_adapter. (the pypi distribution is alembic-adapter-sdk; the bare name alembic belongs to sqlalchemy's migration tool and is unrelated.)

install

pip install alembic-adapter-sdk

or, from a checkout:

pip install -e .

the sdk has no runtime dependencies; it speaks json with the stdlib.

writing an adapter

subclass Adapter, implement the methods your backend needs, and call run:

from alembic_adapter import Adapter, ApplyReport, AppliedOp, Create, run


class MyAdapter(Adapter):
    def setup(self, config):
        # `config` is the parsed `setup:` block from the backend config.
        self.host = (config or {}).get("host", "http://localhost:8080")

    def read(self, schema, types, state):
        # observe backend state -> list[ExternalObject]; the engine diffs it
        # against the desired inventory to build a plan. emit-only adapters
        # return [] (the default).
        return []

    def write(self, schema, ops, state):
        # apply create/update/delete ops, then report what was applied.
        report = ApplyReport()
        for op in ops:
            if isinstance(op, Create):
                ...  # create op.desired on the backend
            report.applied.append(AppliedOp(uid=op.uid, type_name=op.type_name))
        return report


if __name__ == "__main__":
    run(MyAdapter())

run reads one request from stdin, dispatches it, and writes a newline-terminated json response to stdout. any exception your adapter raises is turned into a well-formed {"ok": false, "error": ...} response.

see examples/example_adapter.py for a copyable starting point, and examples/json_store_adapter.py for a finished adapter: it keeps objects in a json file, implements every method of the contract, and converges under alembic plan/apply.

the protocol

every request carries version (currently 1) and a method. the sdk parses the payload into typed objects and serializes your results back:

method you receive you return
read schema, types, state list[ExternalObject]
write schema, ops, state ApplyReport
ensure_schema schema ProvisionReport
preview_schema schema ProvisionReport or None
capabilities nothing Capabilities

preview_schema is called at plan time to show what ensure_schema would provision without writing; return None (the default) if your adapter cannot preview.

capabilities reports the adapter's role: adapter (read+write, the default), emitter (write-only), or observer (read-only), so the host can reject import/apply up front instead of calling into a side that does nothing.

setup is the setup: block from the backend config (parsed json, usually a dict); Adapter.setup is called once before each request.

the model mirrors alembic's ir:

  • Op is Create, Update, or Delete (dispatch with isinstance). Create and Update carry the full desired Object; Update also carries changes and backend_id; Delete carries key and backend_id.
  • Object has uid, type_name, key, and attrs.
  • State.backend_id(type_name, uid) looks up the engine's existing backend id for an object, so renames stay stable.
  • Schema parses into TypeSchema / FieldSchema / FieldType, so schema-driven adapters can, for example, find reference fields via field.type.kind == "ref" and field.type.target.

for the full request/response shapes, see alembic's docs/external-adapters.md.

wiring into alembic

point a backend config at your program (see examples/backend.yaml):

backend: external
command: python3
args: ["examples/example_adapter.py"]
setup:
  host: http://localhost:8080
alembic plan  --backend external --backend-config examples/backend.yaml \
  -f inventory.yaml -o plan.json
alembic apply --backend external --backend-config examples/backend.yaml \
  -p plan.json

you can also debug the protocol by hand by piping a request into your adapter:

echo '{"version":1,"setup":{},"method":"read","schema":{"types":{}},"types":[],"state":{"mappings":{}}}' \
  | python3 examples/example_adapter.py

develop

pip install -e ".[dev]"

# tests
PYTHONPATH=src python -m unittest discover -s tests

# tests with the coverage gate (fails under 100%, matching ci)
coverage run -m unittest discover -s tests
coverage report

ruff check
ruff format --check

the unit tests assert json shapes on their own, so ci also checks the sdk against the real host, pinned to one alembic release:

# protocol conformance, with the runner that ships alongside alembic
alembic-adapter-test -- python examples/example_adapter.py

# a full converge cycle driven by the alembic cli (create, re-plan, update, delete)
bash tests/e2e-alembic.sh

both need binaries from an alembic release on your PATH; the e2e skips itself when alembic is missing.

license

Apache-2.0

Metadata

Release files for alembic-adapter-sdk 0.3.1

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

Source distribution (sdist)

Source distribution for alembic-adapter-sdk 0.3.1
File Size Uploaded
alembic_adapter_sdk-0.3.1.tar.gz 24.8 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for alembic-adapter-sdk 0.3.1
File Interpreter ABI Platform
alembic_adapter_sdk-0.3.1-py3-none-any.whl Python 3 none any Details

Total release size: 39.5 kB

Release files / alembic_adapter_sdk-0.3.1.tar.gz

Download URL alembic_adapter_sdk-0.3.1.tar.gz
Size 24.8 kB
Tags Source
SHA-256 checksum
How to use checksums
b4ae70e1a001282f2003435aa3cde8c6b075e2cb4d1df63480dd4f439adffe93
BLAKE2b-256 checksum
How to use checksums
eeb17607e134c8be482e7a235de68d5a1531bd5ec9aeea367dbd6e1bc3146cb0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 13, 2026.

Transparency log

Release files / alembic_adapter_sdk-0.3.1-py3-none-any.whl

Download URL alembic_adapter_sdk-0.3.1-py3-none-any.whl
Size 14.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
2d06e5c3cb6bcbfa4535e243a4fd1db5b7f8977056e1f4ff151f5eb0e40b4ba5
BLAKE2b-256 checksum
How to use checksums
0f1c62667030ecaa16c715c862fd734ac92e5c7903bf5b36f98dd699b7865afd
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 13, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.3.1 This release

2 release files

0.3.0

2 release files

0.2.0

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