Connection & Registry¶
Functions for managing database connections and the global model registry. connect() registers a (optionally named) connection pool; reset_engine() tears everything down; the registry helpers control schema creation and the identity map. Sessionized routing is exposed via ferro.engines.session(name) / ferro.Session. See the Connections & Databases guide.
Session
dataclass
¶
Source code in src/ferro/session.py
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 | |
Attributes¶
connection_name = None
class-attribute
instance-attribute
¶
session_id = None
class-attribute
instance-attribute
¶
Functions¶
__aenter__()
async
¶
Source code in src/ferro/session.py
__aexit__(exc_type, exc, tb)
async
¶
close()
async
¶
Close this session and release its runtime state.
Safe to call from a different asyncio context than __aenter__.
Repeated calls are no-ops.
Raises:
| Type | Description |
|---|---|
RuntimeError
|
If the ambient session in this asyncio context does not match this handle (same-context lifecycle misuse), or if session-scoped transactions are still open. |
Source code in src/ferro/session.py
query(model_cls)
¶
__init__(connection_name=None, session_id=None, _token=None, _enter_context=None, _enter_task=None, _close_lock=None)
¶
connect(url, auto_migrate=False, name=None, default=False, pool=None, *, identity_map=True, migrate_updates=False, migrate_destructive=False)
async
¶
Establish a connection to the database.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
url
|
str
|
The database connection string (e.g., "sqlite:example.db?mode=rwc"). |
required |
auto_migrate
|
bool
|
If True, automatically create tables for all registered models.
Existing tables are left untouched unless |
False
|
name
|
str | None
|
Optional connection name. Omitted connections register as "default". |
None
|
default
|
bool
|
If True, make this named connection the default for unqualified operations. |
False
|
pool
|
PoolConfig | None
|
Optional per-connection pool configuration. |
None
|
identity_map
|
bool
|
If True (default), sessions opened on this connection keep an identity
map so the same primary key maps to a single Python instance within a session.
Identity maps are session-scoped: operations outside a session never cache or
dedup instances. If False, loads on this connection return fresh instances even
inside a session (lower memory use; no |
True
|
migrate_updates
|
bool
|
If True, additionally update existing tables to match the
registered models. Implies
After any schema change, the connection pool is refreshed so no cached statement can observe the pre-migration schema. |
False
|
migrate_destructive
|
bool
|
If True, additionally drop live columns that no
longer exist on the model (never whole tables). Implies
|
False
|
Raises:
| Type | Description |
|---|---|
ValueError
|
A connection with this name (or a default connection,
when |
For schema changes beyond these (renames, primary-key changes, complex
transforms), use the Alembic bridge — see docs/guide/migrations.md.
Source code in src/ferro/__init__.py
97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 | |
PoolConfig
¶
Bases: BaseModel
Connection pool settings for a named Ferro connection.
Source code in src/ferro/__init__.py
set_default_connection(name)
¶
Source code in src/ferro/_core.pyi
create_tables(using=None)
async
¶
Manually create tables for all registered models on a connected engine.
Compiles and pushes the current registry SchemaIR to the Rust runtime
before delegating to the Rust create entrypoint, so a model defined after
connect() (and thus absent from the connect-time snapshot) is still
created. The runtime emits each CREATE TABLE from this SchemaIR via the
shared emitter.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
using
|
Named connection to create tables on, or None for the default. |
None
|
Source code in src/ferro/__init__.py
migrate(using=None, updates=True, destructive=False)
async
¶
Manually run the auto-migrate pass against a connected engine.
Compiles and pushes the current registry SchemaIR to the Rust runtime, then delegates to the Rust migrate entrypoint.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
using
|
Named connection to migrate, or None for the default. |
None
|
|
updates
|
If True (default), add missing columns and reconcile type/nullability drift. |
True
|
|
destructive
|
If True, also drop live columns absent from the model. Implies |
False
|
Source code in src/ferro/__init__.py
clear_registry()
¶
Reset the compiled/registered schema state.
Delegates to the Rust core (which clears the Rust model registry and the
pushed SchemaIR modelset) and additionally clears the Python join-table
registry. That registry must be reset here because
connect/create_tables/migrate compile the full registry via
compile_registry_schema_ir(): a join table left behind by a prior run
would be re-created with foreign keys to tables that no longer exist —
tolerated by SQLite but rejected by Postgres (relation ... does not
exist). (#153)
The Python model registry (_MODEL_REGISTRY_PY) is intentionally not
cleared here: clearing the Rust registry while keeping the declared Python
models is what allows cold re-hydration after reset_engine (see
tests/test_enum_cold_hydration.py). Callers that want a full Python-side
reset clear _MODEL_REGISTRY_PY / _PENDING_RELATIONS themselves.
Source code in src/ferro/__init__.py
evict_instance(model, pk, *, using=None, session=None)
¶
Remove one instance from the active scope's identity map.
model is a model class, its qualified identity, or an unambiguous
bare class name (ambiguity raises with the candidates listed).
Public wrapper around the FFI evict_instance (FF-D D3): resolves the
route once via resolve_operation_scope, then passes it through. Model
instance methods (save/delete/refresh) call the FFI symbol
directly with their already-resolved route instead of going through this
wrapper, so a route is never resolved twice for one operation.