Skip to content

Events & Logging

biopro_sdk.plugin.events

Central EventBus for BioPro SDK.

Provides a singleton event bus using PyQt signals to allow asynchronous and decoupled communication between different plugins and the core application.

biopro_sdk.plugin.logging

BioPro SDK Logging Utilities.

Provides BioPro-aware loggers that automatically attach plugin metadata and route to the central diagnostic engine.

PluginLoggerAdapter

Bases: LoggerAdapter

Logger adapter that injects plugin_id into every log record.

Source code in src/biopro_sdk/plugin/logging.py
class PluginLoggerAdapter(logging.LoggerAdapter):
    """Logger adapter that injects plugin_id into every log record."""

    def __init__(self, logger: logging.Logger, plugin_id: str):
        """Initialize the logger adapter with a specific plugin identifier.

        Args:
            logger: The parent Python logger instance to adapt.
            plugin_id: The unique identifier of the target plugin.
        """
        super().__init__(logger, {"plugin_id": plugin_id})
        self.plugin_id = plugin_id

    def process(self, msg, kwargs):
        """Process log messages to inject the plugin metadata context.

        Args:
            msg: The actual log message content.
            kwargs: Thread or level attributes associated with the log record.

        Returns:
            A tuple of (processed_message, kwargs) containing the updated extra dict.
        """
        # Ensure plugin_id is in the extra dict for the handler to find
        extra = kwargs.get("extra", {})
        extra["plugin_id"] = self.plugin_id
        kwargs["extra"] = extra
        return msg, kwargs

__init__(logger, plugin_id)

Initialize the logger adapter with a specific plugin identifier.

Parameters:

Name Type Description Default
logger Logger

The parent Python logger instance to adapt.

required
plugin_id str

The unique identifier of the target plugin.

required
Source code in src/biopro_sdk/plugin/logging.py
def __init__(self, logger: logging.Logger, plugin_id: str):
    """Initialize the logger adapter with a specific plugin identifier.

    Args:
        logger: The parent Python logger instance to adapt.
        plugin_id: The unique identifier of the target plugin.
    """
    super().__init__(logger, {"plugin_id": plugin_id})
    self.plugin_id = plugin_id

process(msg, kwargs)

Process log messages to inject the plugin metadata context.

Parameters:

Name Type Description Default
msg

The actual log message content.

required
kwargs

Thread or level attributes associated with the log record.

required

Returns:

Type Description

A tuple of (processed_message, kwargs) containing the updated extra dict.

Source code in src/biopro_sdk/plugin/logging.py
def process(self, msg, kwargs):
    """Process log messages to inject the plugin metadata context.

    Args:
        msg: The actual log message content.
        kwargs: Thread or level attributes associated with the log record.

    Returns:
        A tuple of (processed_message, kwargs) containing the updated extra dict.
    """
    # Ensure plugin_id is in the extra dict for the handler to find
    extra = kwargs.get("extra", {})
    extra["plugin_id"] = self.plugin_id
    kwargs["extra"] = extra
    return msg, kwargs

get_logger(name, plugin_id=None)

Get a logger instance, optionally adapted for a specific plugin.

Parameters:

Name Type Description Default
name str

The name of the logger (usually name)

required
plugin_id str | None

The ID of the plugin this logger belongs to

None

Returns:

Type Description
Logger | PluginLoggerAdapter

A logging.Logger or PluginLoggerAdapter instance.

Source code in src/biopro_sdk/plugin/logging.py
def get_logger(name: str, plugin_id: str | None = None) -> logging.Logger | PluginLoggerAdapter:
    """Get a logger instance, optionally adapted for a specific plugin.

    Args:
        name: The name of the logger (usually __name__)
        plugin_id: The ID of the plugin this logger belongs to

    Returns:
        A logging.Logger or PluginLoggerAdapter instance.
    """
    logger = logging.getLogger(name)
    if plugin_id:
        return PluginLoggerAdapter(logger, plugin_id)
    return logger

biopro_sdk.plugin.signals

Standard plugin signals for BioPro SDK.

This module defines all standard PyQt6 signals that plugins should emit to communicate state changes and results to the BioPro core application.

PluginSignals

Bases: QObject

Standard signals that all plugins emit.

Plugins should use these signals to ensure consistent communication with BioPro core and other plugins.

Attributes:

Name Type Description
status_message

Emitted with a short status string for the UI status bar

log_message

Emitted with detailed log messages

state_changed

Emitted when plugin state changes

undo_available

Emitted with bool indicating if undo is available

redo_available

Emitted with bool indicating if redo is available

analysis_started

Emitted when analysis begins

analysis_progress

Emitted with int (0-100) for progress

analysis_complete

Emitted when analysis finishes

analysis_error

Emitted with error message if analysis fails

data_changed

Emitted when underlying data changes

Source code in src/biopro_sdk/plugin/signals.py
class PluginSignals(QObject):
    """Standard signals that all plugins emit.

    Plugins should use these signals to ensure consistent communication
    with BioPro core and other plugins.

    Attributes:
        status_message: Emitted with a short status string for the UI status bar
        log_message: Emitted with detailed log messages
        state_changed: Emitted when plugin state changes
        undo_available: Emitted with bool indicating if undo is available
        redo_available: Emitted with bool indicating if redo is available
        analysis_started: Emitted when analysis begins
        analysis_progress: Emitted with int (0-100) for progress
        analysis_complete: Emitted when analysis finishes
        analysis_error: Emitted with error message if analysis fails
        data_changed: Emitted when underlying data changes
    """

    # Status / Logging
    status_message = pyqtSignal(str)  # Short status for UI (e.g. "Processing...")
    log_message = pyqtSignal(str)  # Detailed log message

    # State Management
    state_changed = pyqtSignal()  # Plugin state changed
    undo_available = pyqtSignal(bool)  # Whether undo is available
    redo_available = pyqtSignal(bool)  # Whether redo is available

    # Analysis Results
    analysis_started = pyqtSignal()
    analysis_progress = pyqtSignal(int)  # 0-100
    analysis_complete = pyqtSignal()
    analysis_error = pyqtSignal(str)  # Error message

    # Data Changed
    data_changed = pyqtSignal()  # Some data changed (image, parameters, etc)