Blissfully naive PostgreSQL database object manager for views, materialized views, functions, and triggers
Project description
Dbsamizdapper
The "blissfully naive PostgreSQL database object manager"
This is based on the original dbsamizdat code from https://git.sr.ht/~nullenenenen/DBSamizdat/ a version of which was previously hosted at https://github.com/catalpainternational/dbsamizdat
Full disclosure: That one (https://git.sr.ht/~nullenenenen/DBSamizdat/ which is also on pypi) is definitely less likely to have bugs, it was written by a better coder than I am, the original author is "nullenenenen nullenenenen@gavagai.eu"
Quick Start
For detailed usage examples, see USAGE.md
Basic Example
- Create a module with your database views:
# myapp/views.py
from dbsamizdat import SamizdatView
class UserStats(SamizdatView):
sql_template = """
${preamble}
SELECT COUNT(*) as total_users FROM users
${postamble}
"""
- Sync to your database:
# Using CLI (modules are automatically imported)
python -m dbsamizdat.runner sync postgresql:///mydb myapp.views
# Or using library API
python -c "from dbsamizdat import sync; sync('postgresql:///mydb', samizdatmodules=['myapp.views'])"
Key Points
- Module Import: The CLI automatically imports modules you specify - no need to manually import them first
- Database Connection: Use
DBURLenvironment variable or pass connection string directly - Python 3.12+: Requires Python 3.12 or later
- PostgreSQL Only: Works exclusively with PostgreSQL databases
- Dollar-Quoting:
$$does not work in SQL functions - use tags like$BODY$instead (see USAGE.md)
Installation
For Users
pip install dbsamizdapper
For Development
This project uses UV for fast dependency management.
Install UV:
curl -LsSf https://astral.sh/uv/install.sh | sh
# or
pip install uv
Setup development environment:
# Clone the repository
git clone <repo-url>
cd dbsamizdapper
# Install dependencies (includes dev tools)
uv sync --group dev --group testing
# Optional: Install Django type stubs for Django integration development
uv sync --group dev --group testing --extra django
Available dependency groups (development):
dev- Development tools (black, isort, flake8, mypy, etc.)testing- Test framework and PostgreSQL testing with psycopg2-binary
Available extras (optional runtime features):
django- Django 4.2 and type stubs for Django integrationpsycopg3- Use psycopg3 instead of psycopg2
New features
This fork is based on a rewrite which I did to better understand the internals of dbsamizdat as we use it in a few different projects. The changes include:
- Python 3.12+
- Type hints throughout the codebase
- Changed from
ABCtoProtocoltype for inheritance - UV for fast dependency management
- Table Management (new in 0.0.6)
SamizdatTable- Manage database tables as Samizdat objects- UNLOGGED table support for performance-critical use cases
- Django QuerySet integration (0.0.5)
SamizdatQuerySet- Create views from Django QuerySetsSamizdatMaterializedQuerySet- Materialized views from QuerySetsSamizdatModel- Unmanaged Django models as viewsSamizdatMaterializedModel- Materialized views from models
- Compat with both
psycopgandpsycopg3 - Opinionated code formatting
- black + isort
- replaced
lambdas
- some simple
pytestfunctions
and probably many more undocumented changes
Table Management Example
from dbsamizdat import SamizdatTable
class MyTable(SamizdatTable):
"""Manage a table as a Samizdat object"""
sql_template = """
CREATE TABLE ${samizdatname} (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL,
created_at TIMESTAMP DEFAULT NOW()
)
"""
class MyCacheTable(SamizdatTable):
"""UNLOGGED table for better performance"""
unlogged = True
sql_template = """
CREATE TABLE ${samizdatname} (
key TEXT PRIMARY KEY,
value JSONB,
expires_at TIMESTAMP
)
"""
Django QuerySet Example
from dbsamizdat import SamizdatMaterializedQuerySet
from myapp.models import MyModel
class MyComplexView(SamizdatMaterializedQuerySet):
"""Create a materialized view from a complex QuerySet"""
queryset = MyModel.objects.select_related('related').filter(
active=True
).annotate(
custom_field=F('field1') + F('field2')
)
# Optionally specify tables that trigger refresh
refresh_triggers = [("myapp", "mymodel")]
Development Commands
Run tests:
uv run pytest
Linting and formatting:
uv run ruff check .
uv run ruff format .
uv run mypy dbsamizdat
Pre-commit hooks: This project uses pre-commit for automated code quality checks. Install it using uv:
# Install pre-commit with uv (recommended method)
uv tool install pre-commit --with pre-commit-uv
# Install Git hooks (runs automatically on commit)
pre-commit install
# Run on all files manually
pre-commit run --all-files
# Run on staged files only
pre-commit run
# Run a specific hook
pre-commit run ruff --all-files
# Update pre-commit hooks to latest versions
pre-commit autoupdate
# Upgrade pre-commit itself
uv tool upgrade pre-commit
Note: Pre-commit hooks will automatically run when you commit. To skip hooks (not recommended), use git commit --no-verify.
Build package:
uv build
Running Tests
Spin up a podman or docker container
podman run -p 5435:5432 -e POSTGRES_HOST_AUTH_METHOD=trust docker.io/library/postgres
docker run -p 5435:5432 -e POSTGRES_HOST_AUTH_METHOD=trust postgres:latest
The db url for this container would be:
"postgresql:///postgres@localhost:5435/postgres"
Make this the environment variable DB_URL, or add it to the .env file
Documentation
- USAGE.md - Comprehensive usage guide with examples for:
- Non-Django projects
- Django integration
- Library API usage
- Common patterns and troubleshooting
Original README
Check out README.original.md for the original rationale and advanced features
Publishing
- bump the version number in
pyproject.toml - tag a release on github
uv builduv publish- username: token
- token: (get it from pypi)
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 dbsamizdapper-0.1.1.tar.gz.
File metadata
- Download URL: dbsamizdapper-0.1.1.tar.gz
- Upload date:
- Size: 146.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.9 {"installer":{"name":"uv","version":"0.9.9"},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"13","id":"trixie","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bbe948a748ce1d3bfa51630d20df6431b4ec03e042eeb84d74c4bafe83505602
|
|
| MD5 |
248624af7ac525441321a727def06be2
|
|
| BLAKE2b-256 |
9096a98bd95eced46a64e67ed8d52dde072737b163284ef22ca1b752f3c3b810
|
File details
Details for the file dbsamizdapper-0.1.1-py3-none-any.whl.
File metadata
- Download URL: dbsamizdapper-0.1.1-py3-none-any.whl
- Upload date:
- Size: 58.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.9 {"installer":{"name":"uv","version":"0.9.9"},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"13","id":"trixie","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c601bdc8631ff9659997192f1f6e54f96030e321a5a7f3736b22df7026f0c1b0
|
|
| MD5 |
9c880d42f1a05b80d4db06b2d700a2bf
|
|
| BLAKE2b-256 |
3537006f3d3bc1e43d3575a1178d5bde6fe2d6cd64db921600b627e2337c3fbc
|