alt-python-boot-pydbc
Spring Boot-style CDI auto-configuration for relational databases via
pydbc. Provides PydbcTemplate,
NamedParameterPydbcTemplate, and a CDI auto-configuration factory that wires
a DataSource, SQL template, and SchemaInitializer into a Boot application
from a single config property.
Part of the alt-python/boot monorepo.
Quick Start
uv add alt-python-boot-pydbc pydbc-sqlite
# invoke.py
import os
os.chdir(os.path.dirname(os.path.abspath(__file__))) # resolve config/ relative to this file
import pydbc_sqlite # registers the SQLite driver
from boot import Boot
from cdi import Context, Singleton
from boot_pydbc import pydbc_auto_configuration
from services import NoteRepository, Application
Boot.boot({
'contexts': [
Context(pydbc_auto_configuration()),
Context([Singleton(NoteRepository), Singleton(Application)]),
]
})
// config/application.json
{
"boot": {
"datasource": {
"url": "pydbc:sqlite::memory:",
"pool": { "enabled": true, "max": 1 }
}
}
}
Boot reads config/application.json, creates a PooledDataSource, runs
config/schema.sql and config/data.sql, then starts the application.
What's Included
| Class / Function | Description |
|---|---|
PydbcTemplate |
Execute SQL with positional ? parameters |
NamedParameterPydbcTemplate |
Execute SQL with named :param parameters |
ConfiguredDataSource |
CDI bean that reads boot.datasource.* config |
SchemaInitializer |
CDI bean that runs config/schema.sql + config/data.sql at startup |
DataSourceBuilder |
Fluent builder for secondary datasources |
pydbc_auto_configuration() |
Returns 4 CDI Singletons ready for Context() |
pydbc_template_starter() |
One-call Boot.boot() entry point |
DEFAULT_PREFIX |
'boot.datasource' |
Configuration
All properties are under boot.datasource by default (override with a custom prefix).
| Property | Type | Default | Description |
|---|---|---|---|
boot.datasource.url |
string | — | pydbc JDBC-style URL, e.g. pydbc:sqlite::memory: |
boot.datasource.username |
string | — | Username (optional) |
boot.datasource.password |
string | — | Password (optional) |
boot.datasource.pool.enabled |
bool | false |
Use PooledDataSource instead of DataSource |
boot.datasource.pool.min |
int | — | Pool minimum size |
boot.datasource.pool.max |
int | — | Pool maximum size |
boot.datasource.initialize |
bool | true |
Set to false to skip schema initialisation |
boot.datasource.schema |
string | config/schema.sql |
Path to DDL file |
boot.datasource.data |
string | config/data.sql |
Path to seed data file |
If boot.datasource.url is absent, the ConfiguredDataSource bean is still
registered but its _delegate is None. Calling get_connection() will raise
RuntimeError. This lets you deploy with an optional datasource without
breaking the CDI wiring.
PydbcTemplate
PydbcTemplate wraps a DataSource and provides four methods:
from boot_pydbc import PydbcTemplate
template = PydbcTemplate(data_source)
# DDL
template.execute('CREATE TABLE notes (id INTEGER PRIMARY KEY, body TEXT)')
# DML — returns affected row count
count = template.update('INSERT INTO notes VALUES (?, ?)', (1, 'hello'))
# Query — returns list of row dicts
rows = template.query_for_list('SELECT * FROM notes')
# Query — returns exactly one row or raises RuntimeError
row = template.query_for_object('SELECT * FROM notes WHERE id = ?', (1,))
Column names are returned by the underlying driver. With pydbc-sqlite, column
names are uppercase (ID, BODY). Normalise in a row mapper:
def row_mapper(row, _index):
return {k.lower(): v for k, v in row.items()}
notes = template.query_for_list('SELECT * FROM notes', row_mapper=row_mapper)
NamedParameterPydbcTemplate
NamedParameterPydbcTemplate wraps PydbcTemplate and converts :param_name
placeholders to positional ? via ParamstyleNormalizer:
from boot_pydbc import NamedParameterPydbcTemplate
template = NamedParameterPydbcTemplate(data_source)
template.update(
'INSERT INTO notes VALUES (:id, :body)',
{'id': 1, 'body': 'hello'},
)
rows = template.query_for_list(
'SELECT * FROM notes WHERE id = :id',
{'id': 1},
)
SchemaInitializer
When boot.datasource.url is configured, SchemaInitializer.init() runs
config/schema.sql followed by config/data.sql before any application bean
is used. Both files are optional — if either is absent, it is silently skipped.
-- config/schema.sql
CREATE TABLE IF NOT EXISTS notes (
id INTEGER PRIMARY KEY,
title TEXT NOT NULL,
body TEXT,
done INTEGER NOT NULL DEFAULT 0
);
-- config/data.sql
INSERT INTO notes (id, title, body) VALUES (1, 'First note', '');
INSERT INTO notes (id, title, body) VALUES (2, 'Second note', '');
Set boot.datasource.initialize: false in config to skip initialisation
entirely (useful for production environments where schema is managed separately).
Secondary Datasources
DataSourceBuilder creates a second set of CDI beans with a custom config
prefix and custom bean names:
from boot_pydbc import DataSourceBuilder
from cdi import Context
reporting_beans = (
DataSourceBuilder.create()
.prefix('myapp.reporting')
.bean_names({
'data_source': 'reporting_ds',
'pydbc_template': 'reporting_template',
'named_parameter_pydbc_template': 'reporting_named_template',
'schema_initializer': 'reporting_schema_initializer',
})
.build()
)
# Or skip the schema initializer entirely:
read_only_beans = (
DataSourceBuilder.create()
.prefix('myapp.readonly')
.without_schema_initializer()
.build()
)
ctx = Context([*pydbc_auto_configuration(), *reporting_beans, ...])
Config for the secondary datasource lives under myapp.reporting.*:
{
"myapp": {
"reporting": {
"url": "pydbc:sqlite:reporting.db"
}
}
}
Using with Boot
pydbc_auto_configuration()
Returns a flat list of 4 Singleton beans. Concatenate with your application
beans and pass to Context():
from boot import Boot
from cdi import Context, Singleton
from boot_pydbc import pydbc_auto_configuration
Boot.boot({
'contexts': [
Context(pydbc_auto_configuration()),
Context([Singleton(MyService), Singleton(MyApp)]),
]
})
pydbc_template_starter()
One-call entry point for applications that need only a single datasource:
from boot_pydbc import pydbc_template_starter
from cdi import Context, Singleton
pydbc_template_starter({
'contexts': [Context([Singleton(MyService), Singleton(MyApp)])],
})
SQLite In-Memory Databases
When using an in-memory SQLite URL (pydbc:sqlite::memory:), you must use a
connection pool to prevent PydbcTemplate from destroying the database on
conn.close():
{
"boot": {
"datasource": {
"url": "pydbc:sqlite::memory:",
"pool": { "enabled": true, "max": 1 }
}
}
}
Without the pool, the finally: conn.close() block in PydbcTemplate closes
the DBAPI connection, which destroys the in-memory database. With
PooledDataSource(max=1), conn.close() returns the connection to the pool
instead.
Running Tests
uv run pytest packages/boot-pydbc -v
License
MIT
Metadata
Release files for alt-python-boot-pydbc 1.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| alt_python_boot_pydbc-1.1.1.tar.gz | 8.9 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| alt_python_boot_pydbc-1.1.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 16.9 kB
Release files / alt_python_boot_pydbc-1.1.1.tar.gz
| Download URL | alt_python_boot_pydbc-1.1.1.tar.gz |
|---|---|
| Size | 8.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
2cff3e57d811fe4870a2b50b48c38bdcffba04ed1709370b44be614fb3552a2d
|
|
BLAKE2b-256 checksum How to use checksums |
38b30855bae9f3c3c97d9461429475b648b6b13cc9eb1db4b3c3056669c4ba46
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.11.2 {"installer":{"name":"uv","version":"0.11.2","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 / alt_python_boot_pydbc-1.1.1-py3-none-any.whl
| Download URL | alt_python_boot_pydbc-1.1.1-py3-none-any.whl |
|---|---|
| Size | 8.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
9567a070ddcaf0c460594b7e7e16ee9760fc4aa99b4013a527ad5268dbd21972
|
|
BLAKE2b-256 checksum How to use checksums |
da710c9b238587331507a314bf34bf75154afd68dff79412c81cfa5775bc7b34
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.11.2 {"installer":{"name":"uv","version":"0.11.2","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}
|
Security for alt-python-boot-pydbc 1.1.1
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.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.