Async-native seeder and factory library for SQLAlchemy
Project description
sqlalchemy-seedling
Async-native seeder and factory library for SQLAlchemy. Dependency-aware runners, declarative factories, and a CLI — Laravel-style ergonomics for the Python async ecosystem.
Why seedling?
- Dependency-aware — declare
depends_onbetween seeders and the runner resolves the correct execution order automatically (Kahn's topological sort). - Async-native — built for
async/awaitand SQLAlchemy's async session from the ground up; no sync wrappers. - Declarative factories —
Factory[T]withLazyAttribute,Sequence,SubFactory, andas_trait()for composable test data. - Environment filtering — tag seeders with
environments = {DEV, TEST, PROD}and the runner skips what doesn't belong. - Zero boilerplate CLI — one line in
pyproject.tomland you getseed run,seed fresh, andseed list.
Installation
pip install sqlalchemy-seedling
# or
uv add sqlalchemy-seedling
Requires Python 3.11+ and SQLAlchemy 2.0+.
Quick start
1. Define seeders
# myapp/seeders/user_seeder.py
from seedling import Seeder, DEV_AND_TEST
from sqlalchemy.ext.asyncio import AsyncSession
from myapp.models import User
class UserSeeder(Seeder):
environments = DEV_AND_TEST
async def run(self, session: AsyncSession) -> None:
session.add(User(email="admin@example.com", name="Admin"))
await session.commit()
async def truncate(self, session: AsyncSession) -> None:
await session.execute(delete(User))
await session.commit()
# myapp/seeders/post_seeder.py
from seedling import Seeder, DEV_AND_TEST
class PostSeeder(Seeder):
depends_on = [UserSeeder] # runs after UserSeeder automatically
environments = DEV_AND_TEST
async def run(self, session: AsyncSession) -> None:
...
2. Create a runner factory
# myapp/seeders/__init__.py
from seedling import SeederRunner
from myapp.db import async_session_maker
from myapp.seeders.user_seeder import UserSeeder
from myapp.seeders.post_seeder import PostSeeder
def create_runner(env: str = "development") -> SeederRunner:
runner = SeederRunner(session_factory=async_session_maker, env=env)
runner.register(UserSeeder, PostSeeder)
return runner
3. Configure the CLI
# pyproject.toml
[tool.seedling]
runner = "myapp.seeders:create_runner"
4. Run
seed run # run all seeders for the default env
seed run UserSeeder # run a specific seeder (+ its dependencies)
seed fresh # truncate then re-seed
seed list # print execution order without running
seed run --env production # target a different environment
Factories
Use Factory[T] to build and persist model instances with minimal boilerplate.
from seedling import Factory, LazyAttribute, Sequence, SubFactory, faker
from myapp.models import User, Post
class UserFactory(Factory[User]):
model = User
email = LazyAttribute(lambda f: faker.unique.email())
name = Sequence(lambda n: f"User {n}")
class PostFactory(Factory[Post]):
model = Post
author = SubFactory(UserFactory) # creates a User row automatically
title = LazyAttribute(lambda f: faker.sentence())
# In tests or seeders:
user = await UserFactory.create(session)
posts = await PostFactory.create_batch(session, 5)
# build() never touches the DB — useful in pure unit tests:
user = UserFactory.build(email="test@example.com")
# Traits for scenario-specific variants:
AdminUser = UserFactory.as_trait(is_superuser=True)
admin = await AdminUser.create(session)
Helpers
from seedling import upsert
# Idempotent insert — ON CONFLICT DO NOTHING (PostgreSQL) / INSERT OR IGNORE (SQLite)
await upsert(session, MyModel, {"id": 1, "name": "Foo"})
await upsert(session, MyModel, {"id": 1, "name": "Foo"}, constraint="uq_mymodel_name")
Environment constants
from seedling import DEV, TEST, PROD, ALL, DEV_AND_TEST
| Constant | Value |
|---|---|
DEV |
"development" |
TEST |
"test" |
PROD |
"production" |
DEV_AND_TEST |
{"development", "test"} |
ALL |
{"development", "test", "production"} |
On the horizon
- State tracking —
seedling_statetable records every run with timestamps, status, and a content hash for drift detection.seed statusand--new-onlyflag coming in 0.3. - Factory power —
AutoFactory[Model]with mapper introspection, declarativeTraitclasses,@post_generationhooks,RelatedFactory, and bulk insert. Coming in 0.4. - Scaffolding —
seed init,seed make:seeder,seed make:factory, and a transactional pytest fixture. Coming in 0.5.
See ROADMAP.md for the full plan.
License
MIT — see LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file sqlalchemy_seedling-0.5.0.tar.gz.
File metadata
- Download URL: sqlalchemy_seedling-0.5.0.tar.gz
- Upload date:
- Size: 53.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.8 {"installer":{"name":"uv","version":"0.11.8","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}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a46ddd1fbe1fa11a22c314232334d34f58f60ea2ee3424ed1203a69a4dc89b3e
|
|
| MD5 |
89dff4a20fe18598cd935faced9b7e23
|
|
| BLAKE2b-256 |
7632f6dfdcd27723303ba42c6c2a26cc8752aa991d7960fdcd3287a56a8ca393
|
File details
Details for the file sqlalchemy_seedling-0.5.0-py3-none-any.whl.
File metadata
- Download URL: sqlalchemy_seedling-0.5.0-py3-none-any.whl
- Upload date:
- Size: 32.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.8 {"installer":{"name":"uv","version":"0.11.8","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}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
39b02604e3ef4f956b36b7521629f0011232bef439037f30ef1281f1e4ae09e2
|
|
| MD5 |
60d78a7fe188be219045de2e0e01a878
|
|
| BLAKE2b-256 |
e7621fe77705d539688e19c03757c1018c58945d0038861a62911a4c25292619
|