Skip to content

Plugin Architecture

Plugin System

from yapfm import YAPFileManager
from typing import Any, Dict, List, Optional, Protocol
import importlib
import os

class Plugin(Protocol):
    """Plugin protocol for extending file manager functionality."""

    def initialize(self, file_manager: YAPFileManager) -> None:
        """Initialize the plugin with the file manager."""
        ...

    def before_load(self, file_manager: YAPFileManager) -> None:
        """Called before loading the file."""
        ...

    def after_load(self, file_manager: YAPFileManager) -> None:
        """Called after loading the file."""
        ...

    def before_save(self, file_manager: YAPFileManager) -> None:
        """Called before saving the file."""
        ...

    def after_save(self, file_manager: YAPFileManager) -> None:
        """Called after saving the file."""
        ...

class PluginManager:
    """Manager for file manager plugins."""

    def __init__(self, file_manager: YAPFileManager):
        self.file_manager = file_manager
        self.plugins: List[Plugin] = []

    def register_plugin(self, plugin: Plugin) -> None:
        """Register a plugin."""
        plugin.initialize(self.file_manager)
        self.plugins.append(plugin)

    def load_plugins_from_directory(self, directory: str) -> None:
        """Load plugins from a directory."""
        for filename in os.listdir(directory):
            if filename.endswith('.py') and not filename.startswith('_'):
                module_name = filename[:-3]
                module = importlib.import_module(f"{directory}.{module_name}")

                # Look for plugin classes
                for attr_name in dir(module):
                    attr = getattr(module, attr_name)
                    if (isinstance(attr, type) and 
                        hasattr(attr, 'initialize') and
                        hasattr(attr, 'before_load')):
                        plugin = attr()
                        self.register_plugin(plugin)

    def before_load(self) -> None:
        """Call before_load on all plugins."""
        for plugin in self.plugins:
            plugin.before_load(self.file_manager)

    def after_load(self) -> None:
        """Call after_load on all plugins."""
        for plugin in self.plugins:
            plugin.after_load(self.file_manager)

    def before_save(self) -> None:
        """Call before_save on all plugins."""
        for plugin in self.plugins:
            plugin.before_save(self.file_manager)

    def after_save(self) -> None:
        """Call after_save on all plugins."""
        for plugin in self.plugins:
            plugin.after_save(self.file_manager)

class LoggingPlugin:
    """Plugin for logging file operations."""

    def __init__(self):
        self.logger = None

    def initialize(self, file_manager: YAPFileManager) -> None:
        import logging
        self.logger = logging.getLogger("file_manager_plugin")

    def before_load(self, file_manager: YAPFileManager) -> None:
        self.logger.info(f"Loading file: {file_manager.path}")

    def after_load(self, file_manager: YAPFileManager) -> None:
        self.logger.info(f"File loaded: {file_manager.path}")

    def before_save(self, file_manager: YAPFileManager) -> None:
        self.logger.info(f"Saving file: {file_manager.path}")

    def after_save(self, file_manager: YAPFileManager) -> None:
        self.logger.info(f"File saved: {file_manager.path}")

class ValidationPlugin:
    """Plugin for validating configuration."""

    def __init__(self):
        self.validation_rules = {}

    def initialize(self, file_manager: YAPFileManager) -> None:
        pass

    def before_save(self, file_manager: YAPFileManager) -> None:
        # Validate configuration before saving
        if not self._validate_config(file_manager.data):
            raise ValueError("Configuration validation failed")

    def _validate_config(self, data: Dict[str, Any]) -> bool:
        # Add your validation logic here
        return True

# Usage
fm = YAPFileManager("plugin_config.json", auto_create=True)
plugin_manager = PluginManager(fm)

# Register plugins
plugin_manager.register_plugin(LoggingPlugin())
plugin_manager.register_plugin(ValidationPlugin())

# Use file manager with plugins
with fm:
    plugin_manager.before_load()
    fm.load()
    plugin_manager.after_load()

    fm.set_key("value", dot_key="key")

    plugin_manager.before_save()
    fm.save()
    plugin_manager.after_save()