audit_trail.diff¶
Entity change sets and per-column field policies.
Everything here reads the in-memory state of ORM instances and never emits
SQL, so it is safe to call from after_flush (also under AsyncSession).
A column's policy is set where the column is defined::
hook_secret: Mapped[str] = mapped_column(info={"audit": "redact"})
email: Mapped[str] = mapped_column(info={"audit": "hash"})
embeddings: Mapped[bytes] = mapped_column(info={"audit": "exclude"})
FieldPolicy
module-attribute
¶
Policy of one column, from mapped_column(info={"audit": ...}).
ChangeKind
module-attribute
¶
Which change set to build: a new, a modified or a deleted instance.
Changes
module-attribute
¶
{attribute key: [old, new]} with JSON-ready values.
REDACTED
module-attribute
¶
Stored in place of a non-null value of a redact column.
UNKNOWN
module-attribute
¶
Marker stored where a value is not available without SQL.
SNAPSHOT_INFO_KEY
module-attribute
¶
InstanceState.info key holding the snapshot_on_load copies.
FieldPolicyError ¶
Bases: ValueError
A column's audit policy is invalid or cannot be applied.
AuditOptionError ¶
Bases: TypeError
An audit option (label, scope, target) is misconfigured.
UseContext ¶
Bases: Enum
Result of :func:resolve_scope meaning "take the scope from context".
ResolvedTarget ¶
Bases: NamedTuple
A target as stored in target_type and target_id.
options_of ¶
Return the model's __audit__ options, or the defaults.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
model
|
type[Any]
|
A mapped class. |
required |
Returns:
| Type | Description |
|---|---|
AuditOptions
|
The model's |
Source code in audit_trail/diff.py
object_type_of ¶
Return the object_type of an instance.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
obj
|
object
|
A mapped instance. |
required |
Returns:
| Type | Description |
|---|---|
str
|
|
Source code in audit_trail/diff.py
field_policy ¶
Return the audit policy set on a column.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
model
|
type[Any]
|
The mapped class, named in the error message. |
required |
key
|
str
|
The column's attribute key, named in the error message. |
required |
column
|
Column[Any]
|
The column. |
required |
Returns:
| Type | Description |
|---|---|
FieldPolicy | None
|
The policy, or |
Raises:
| Type | Description |
|---|---|
FieldPolicyError
|
|
Source code in audit_trail/diff.py
entity_changes ¶
entity_changes(
obj: object,
kind: ChangeKind,
*,
keys: KeyRing | None = None,
json_encoder: type[JSONEncoder] | None = None,
global_redact: Collection[str] = (),
) -> Changes
Build the changes of an entity.* entry from an instance.
Meant for after_flush, while session.new / dirty / deleted
and attribute history still describe the flush. Reads only what is in
memory and never emits SQL.
created: every audited column as[None, value], empty ones too.updated: only columns with a net change. Old and new raw values are compared withcolumn.type.compare_valuesbefore any redaction or encoding, soDecimal("1.5")vsDecimal("1.50")is no change. An empty result means there is nothing to record.deleted: every audited column as[value, None].
exclude columns are left out. redact stores "***" and
hash stores hv{n}:<hex>; both keep null as null. Every other value
goes through encode_value.
"<unknown>" is a marker, not a value: it stands where the value is not
in memory. That is the old value of a JSON column changed in place
(MutableDict) without snapshot_on_load, a deleted column that
is not loaded (for example deferred), and a created column filled
by a server-side default (server_default, Computed, Identity)
that was not fetched back. On PostgreSQL the mapper's default
eager_defaults="auto" fetches them with RETURNING on INSERT, so
created entries hold the real values; only a mapper with
eager_defaults=False leaves them "<unknown>". A created column
that was not set and has no server-side default is None, as stored.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
obj
|
object
|
A mapped instance. |
required |
kind
|
ChangeKind
|
Which change set to build. |
required |
keys
|
KeyRing | None
|
Key ring for |
None
|
json_encoder
|
type[JSONEncoder] | None
|
Host encoder for types |
None
|
global_redact
|
Collection[str]
|
Attribute keys or column names redacted when the column has no explicit policy. An extra safety net, not a replacement for per-column policies. |
()
|
Returns:
| Type | Description |
|---|---|
Changes
|
|
Raises:
| Type | Description |
|---|---|
FieldPolicyError
|
A column has an unknown policy, or the model has a
|
UnserializableValueError
|
A value cannot be encoded. |
Source code in audit_trail/diff.py
174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 | |
object_id_of ¶
Return the object_id of an instance.
Uses the identity key when the instance has one. Inside after_flush
that is still the key from before the flush, so a changed primary key
yields the old id. Objects inserted by the flush have no identity key yet;
their primary key is read from the instance.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
obj
|
object
|
A mapped instance. |
required |
Returns:
| Type | Description |
|---|---|
str
|
|
str
|
form), a compact JSON array of strings ( |
str
|
composite one. |
Raises:
| Type | Description |
|---|---|
ValueError
|
The instance has no primary key value yet. |
Source code in audit_trail/diff.py
state_object_id ¶
Return the object_id of an instance state, as :func:object_id_of.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
state
|
InstanceState[Any]
|
The state of a mapped instance. |
required |
Returns:
| Type | Description |
|---|---|
str | None
|
The id, or |
Source code in audit_trail/diff.py
object_id_for ¶
Return the object_id for a primary key of model.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
model
|
type[Any]
|
A mapped class. |
required |
pk
|
object
|
The key value, or a tuple of values in primary key column order for a composite key. |
required |
Returns:
| Type | Description |
|---|---|
str
|
The same string |
Raises:
| Type | Description |
|---|---|
ValueError
|
The number of values does not match the primary key, or
a value is |
Source code in audit_trail/diff.py
resolve_label ¶
Evaluate options.label for object_label without emitting SQL.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
obj
|
object
|
A mapped instance. |
required |
options
|
AuditOptions
|
The model's options. |
required |
Returns:
| Type | Description |
|---|---|
str | None
|
The label as a string, or |
str | None
|
it returns |
str | None
|
logged once per model, attribute and option on the |
str | None
|
|
Raises:
| Type | Description |
|---|---|
AuditOptionError
|
The option read a |
Source code in audit_trail/diff.py
resolve_scope ¶
Evaluate options.scope for scope_id without emitting SQL.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
obj
|
object
|
A mapped instance. |
required |
options
|
AuditOptions
|
The model's options. |
required |
Returns:
| Type | Description |
|---|---|
str | UseContext | None
|
|
str | UseContext | None
|
attribute that is not loaded (then logged once per model, attribute |
str | UseContext | None
|
and option on the |
str | UseContext | None
|
when the option returned |
str | UseContext | None
|
value as a string. |
Raises:
| Type | Description |
|---|---|
AuditOptionError
|
The option read a |
Source code in audit_trail/diff.py
resolve_target ¶
Evaluate options.target for target_type/target_id.
Never emits SQL. The id is formatted like object_id: a tuple becomes
a composite id, anything else str().
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
obj
|
object
|
A mapped instance. |
required |
options
|
AuditOptions
|
The model's options. |
required |
Returns:
| Type | Description |
|---|---|
ResolvedTarget | None
|
The stored target, or |
ResolvedTarget | None
|
option, it returns |
ResolvedTarget | None
|
attribute that is not loaded (then logged once per model, attribute |
ResolvedTarget | None
|
and option on the |
Raises:
| Type | Description |
|---|---|
AuditOptionError
|
The option read a |
Source code in audit_trail/diff.py
format_target ¶
Format a target as stored in target_type and target_id.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
target
|
Target
|
The type name and the id; a tuple id is a composite key. |
required |
Returns:
| Type | Description |
|---|---|
ResolvedTarget | None
|
The stored target, or |