Add logemit event callbacks and kanta.tty terminal formatting
All change-related output (transactions, bootstrap, migrations) is now described by a mutable LogEvent carrying full state plus the preferred logger and level, and dispatched through emit_event. @kanta.logemit callbacks receive the event and decide what is logged where: falsy return marks it handled, truthy passes it (possibly modified) down the chain, with default_emit - Kanta's own formatting, now just another emitter - as the fallback. Pretty header and diff lines are lazy event properties. New kanta.tty module: Line builder (call to append content, .colorname arms a palette color for the next call with automatic folded reset, width/align padding), a mutable Colors palette storing bare SGR params (0 clears, sequential last-wins stacking), and strip_ansi/displaywidth/pad helpers that count wide chars and emoji correctly.
This commit is contained in:
@@ -222,6 +222,54 @@ def resolve_user_key(value: str) -> str | None:
|
||||
`kanta.transaction.diff` child logger so applications can route or silence
|
||||
them separately from the headers.
|
||||
|
||||
#### Log Emitters
|
||||
|
||||
- Every change-related message Kanta emits (transaction/bootstrap/migration
|
||||
changes, `Created <file>`, migration summaries) is described by a
|
||||
`kanta.logging.LogEvent` and dispatched through `kanta.logging.emit_event`.
|
||||
Kanta's own output goes through the same mechanism: when no `logemit`
|
||||
callback handles an event, `kanta.logging.default_emit` renders it with the
|
||||
built-in formatting.
|
||||
- A `LogEvent` carries the event `kind` (`"change"`, `"created"`,
|
||||
`"migrated"`), the preferred `logger` and `level`, and all relevant state:
|
||||
`action`, `user`, `extra`, `diff`, `previous`/`current` state dicts, the
|
||||
built `logfmt` chain, and version info for migration events. Pretty
|
||||
`header` and `diff_lines` are lazy properties, built only if accessed.
|
||||
- `@kanta.logemit` registers a callback receiving the event. The callback
|
||||
decides what is logged and where: it may log one or more messages on
|
||||
`event.logger`, log somewhere else, or nothing at all. A falsy return
|
||||
value marks the event handled and stops the chain; a truthy return value
|
||||
passes the event — possibly modified — to the next registered callback.
|
||||
When all callbacks pass, `default_emit` renders the event; a callback may
|
||||
also call `default_emit(event)` itself to delegate events it does not
|
||||
customize. Operational diagnostics (rollback warnings, integrity errors)
|
||||
do not go through this mechanism.
|
||||
|
||||
```python
|
||||
@kanta.logemit
|
||||
def emit(ev: LogEvent):
|
||||
if ev.kind != "change":
|
||||
return default_emit(ev) # delegate, no chaining needed
|
||||
actor = ev.current.get("users", {}).get(ev.user, {}).get("name", ev.user)
|
||||
line = Line().user(actor, width=20)(" ").action(ev.action)
|
||||
ev.logger.log(ev.level, f"{line}\n" + "\n".join(ev.diff_lines))
|
||||
```
|
||||
|
||||
#### Terminal Formatting Helpers
|
||||
|
||||
- `kanta.tty` provides the building blocks used by Kanta's own rendering:
|
||||
- `colors`: the mutable color palette. Colors are bare SGR parameter
|
||||
strings (e.g. `"1;34"`, `"38;5;226"`) without escape framing. Attributes
|
||||
are read at render time, so assignments (`colors.action = "36"`) and
|
||||
additions (`colors.session = "38;5;226"`) take effect immediately.
|
||||
- `Line`: builds a terminal string part by part. Calling it appends
|
||||
content (`str`-converted); `.<colorname>` arms a palette color for the
|
||||
next call only, and the reset is folded into a single escape sequence
|
||||
with whatever color comes next. `width=`/`align=` pad by display width;
|
||||
`str(line)` finishes the line and restores default colors.
|
||||
- `strip_ansi`, `displaywidth` (wide chars and emoji count correctly) and
|
||||
`pad` for working with pre-colored strings.
|
||||
|
||||
## Migrations
|
||||
|
||||
- Migration source is configured on `Kanta(...)` via `migrations=`.
|
||||
|
||||
Reference in New Issue
Block a user