spacr.qt.verbose_logger¶
Verbose diagnostic logger for the Qt GUI.
When the “Verbose logging” preference is on, spaCR’s Python loggers are dialled up to DEBUG and the log files keep those records. The active ConsolePanel shows only the levels switched on for the console on the Logging tab of Preferences. That puts a detailed trail on disk, which is what you want when triaging a bug report.
The handler is a lazy module-level singleton so multiple
apply_verbose_logging() calls (e.g. every time the Preferences
dialog is saved) don’t stack up handlers or leak references. Turning
verbose off leaves the handler attached but silent — cheaper than
tearing it down and rebuilding it, and safer for cases where a log
record fires mid-toggle.
Design:
One
_ConsoleForwarderhandler is added to the rootspacrlogger. Its emit() hands the formatted line to_ConsoleRelay, which delivers it to whatever ConsolePanel is registered viaregister_console_target().Registration is a weak reference to avoid keeping a closed screen alive. If the target has been garbage-collected the record is silently dropped.
Level and format are set once at first registration; only the
verbosegate flips DEBUG ↔ INFO afterwards.
Warning
emit() runs on whatever thread logged the record — Python’s
logging module calls handlers inline. A ConsolePanel answers
append_stdout by constructing QWidgets (a topic bar and a text
block), and Qt forbids building a QWidget anywhere but the GUI
thread. Calling the panel straight from emit() therefore built
widgets on a worker thread; Qt printed QObject::setParent: Cannot
set parent, new parent is in a different thread and then took the
process down. It was reproducible from
spacr.qt.hf_download._HFDownloadWorker.run(), whose exception
path logs a warning from inside the download thread.
_ConsoleRelay is the fix: a QObject pinned to the GUI
thread whose line signal is connected to its own bound
method, so Qt queues the delivery whenever the emitting thread is
not the GUI thread and the panel only ever touches widgets on the
thread that owns them.
Functions¶
|
Gate the in-app console to an explicit set of levels. |
|
Flip DEBUG ↔ INFO on every attached spaCR logger + handlers. |
|
The levels the console is currently showing. |
Mark the calling thread as being inside a console write. |
|
|
Whether this thread is currently writing into the console panel. |
|
Path of today's rotating log file. |
|
Cheap runtime check — decorated functions call this on entry so |
|
Fire a one-line trace record documenting a UI button press. |
|
Decorator: log entry + return of |
|
Return |
|
Point the verbose logger at |
Module Contents¶
- spacr.qt.verbose_logger.apply_console_levels(levels) None[source]¶
Gate the in-app console to an explicit set of levels.
Called by
spacr.logging_util.apply_level_policy(), which has already clampedlevelsto a subset of what the log files record – a line the user cannot find in the log they are about to attach to a bug report should not appear in the console either.The handler keeps passing everything and a filter decides, so the set can change while another thread is mid-log without the handler being swapped underneath it.
- Parameters:
levels – numeric logging levels the console should show; anything outside DEBUG-CRITICAL is dropped, and attached spaCR loggers are lowered to the lowest level kept.
- spacr.qt.verbose_logger.apply_verbose_logging(on: bool) None[source]¶
Flip DEBUG ↔ INFO on every attached spaCR logger + handlers.
The user reaches this via the Preferences dialog. It’s idempotent and cheap — safe to call on every dialog save. Also ensures the rotating file handler is attached so bug reports always have a trail on disk regardless of verbose state.
The
cellposelogger goes to INFO while verbose is on, so it can say which model it loaded, and back to WARNING when verbose is off.- Parameters:
on –
Truesets the console handler, file handler and attached spaCR loggers to DEBUG (andcellposeto INFO);Falsesets them to INFO (andcellposeto WARNING).
- spacr.qt.verbose_logger.console_levels() frozenset[source]¶
The levels the console is currently showing.
- spacr.qt.verbose_logger.console_write()[source]¶
Mark the calling thread as being inside a console write.
Re-entrant by design:
append_errormay be reached from insideappend_stdout’s own bookkeeping, and unwinding must restore the previous depth rather than clear the latch outright.
- spacr.qt.verbose_logger.console_write_in_progress() bool[source]¶
Whether this thread is currently writing into the console panel.
Log sinks that feed the console must return without delivering while this is true — see
_DELIVERY_STATE.
- spacr.qt.verbose_logger.current_log_file() pathlib.Path[source]¶
Path of today’s rotating log file.
- spacr.qt.verbose_logger.is_verbose() bool[source]¶
Cheap runtime check — decorated functions call this on entry so they emit NOTHING when verbose mode is off.
It reads the verbose PREFERENCE as
apply_verbose_logging()last applied it, not the console forwarder’s level, whichapply_console_levels()holds at DEBUG in every session.
- spacr.qt.verbose_logger.log_button_press(button_name: str, context: dict | None = None) None[source]¶
Fire a one-line trace record documenting a UI button press.
Wire this from Qt slot handlers so the console shows exactly which button the user hit, with any relevant context values (e.g. the current settings dict on a Run press).
- Parameters:
button_name – name of the pressed button, shown in the
[button:<name>]trace line; nothing is logged unless verbose mode is on.
- spacr.qt.verbose_logger.log_call(fn: Callable) Callable[source]¶
Decorator: log entry + return of
fnwhen verbose mode is on.Zero cost when verbose is off (the wrapper does one attribute check and forwards). When on, emits:
[class.func] args=… kwargs=… [class.func] -> return-repr
Truncates giant reprs to 240 chars so a settings dict with 100 entries doesn’t wreck the console.
- Parameters:
fn – the function or method to wrap; its arguments, return value or raised exception are logged to
spacr.tracewhile verbose mode is on.
- spacr.qt.verbose_logger.log_dir() pathlib.Path[source]¶
Return
~/.spacr/logs/— created if it doesn’t exist.Overridable via the
SPACR_LOG_DIRenv var so tests can point the log at a tmp directory.
- spacr.qt.verbose_logger.register_console_target(panel: Any) None[source]¶
Point the verbose logger at
panel(a ConsolePanel).The target is stored as a
weakref.refso a closed screen doesn’t keep the panel alive. Any earlier target is replaced.Called from the GUI thread (the AppScreen constructor), which is where the relay wants to be built — see
_ConsoleRelay.- Parameters:
panel – the console panel that receives log lines; it is held by weak reference and dropped when its
destroyedsignal fires.
Nested helpers¶
- log_call.wrapper(*args, **kwargs)¶
Call the function, logging it only when verbose is on.
The check is INSIDE rather than at decoration time, so switching verbose on mid-session takes effect without rebuilding anything.
spacr/qt/verbose_logger.py:512