Source code for paperap.plugins.base

"""
----------------------------------------------------------------------------

   METADATA:

       File:    base.py
        Project: paperap
       Created: 2025-03-04
        Version: 0.0.8
       Author:  Jess Mann
       Email:   jess@jmann.me
        Copyright (c) 2025 Jess Mann

----------------------------------------------------------------------------

   LAST MODIFIED:

       2025-03-04     By Jess Mann

"""

from __future__ import annotations

from abc import ABC, abstractmethod
from typing import TYPE_CHECKING, Any, ClassVar, NotRequired, TypedDict, override

import pydantic
from pydantic import ConfigDict, field_validator
from typing_extensions import Unpack

from paperap.exceptions import ModelValidationError

if TYPE_CHECKING:
    from paperap.client import PaperlessClient
    from paperap.plugins.manager import PluginManager


[docs] class ConfigType(TypedDict, total=False): type: NotRequired[type] description: NotRequired[str] required: NotRequired[bool]
[docs] class Plugin(pydantic.BaseModel, ABC): """Base class for all plugins.""" # Class attributes for plugin metadata name: ClassVar[str] description: ClassVar[str] = "No description provided" version: ClassVar[str] = "0.0.1" manager: "PluginManager" @override def __init_subclass__(cls, **kwargs: ConfigDict): # Enforce name is set if not getattr(cls, "name", None): raise ValueError("Plugin name must be set") return super().__init_subclass__(**kwargs) # type: ignore # Not sure why pyright is complaining model_config = ConfigDict( from_attributes=True, extra="ignore", use_enum_values=True, arbitrary_types_allowed=True, validate_default=True, validate_assignment=True, )
[docs] def __init__(self, **kwargs: Any) -> None: """ Initialize the plugin. Args: **kwargs: Plugin-specific configuration. """ # Pydantic handles config super().__init__(**kwargs) # Finalize setting up the plugin (defined by subclass) self.setup()
@property def client(self) -> "PaperlessClient": return self.manager.client
[docs] @abstractmethod def setup(self) -> None: """Register signal handlers and perform other initialization tasks."""
[docs] @abstractmethod def teardown(self) -> None: """Clean up resources when the plugin is disabled or the application exits."""
[docs] @classmethod def get_config_schema(cls) -> dict[str, ConfigType]: """ Get the configuration schema for this plugin. Returns: A dictionary describing the expected configuration parameters. Examples: >>> return { >>> "test_dir": { >>> "type": str, >>> "description": "Directory to save test data files", >>> "required": False, >>> } >>> } """ return {}