Coverage for src / lexigram / contracts / plugins.py: 100%
13 statements
« prev ^ index » next coverage.py v7.13.5, created at 2026-08-19 05:41 +0800
« prev ^ index » next coverage.py v7.13.5, created at 2026-08-19 05:41 +0800
1"""Plugin descriptor contract type.
3A ``PluginDescriptor`` is metadata-only — discovering it via the
4``lexigram.plugins`` entry-point group (``EP_PLUGINS``) never imports or
5instantiates the plugin's actual DI ``Provider``. That keeps listing
6available plugins (e.g. for an admin UI) cheap even when a plugin's
7provider class is heavy to import.
8"""
10from __future__ import annotations
12from dataclasses import dataclass
14__all__ = ["PluginDescriptor"]
17@dataclass(frozen=True)
18class PluginDescriptor:
19 """Metadata describing an admin-manageable plugin.
21 ``provider_entry_point`` is the entry-point *name* (not dotted path)
22 this descriptor maps to within the ``lexigram.providers`` (``EP_PROVIDERS``)
23 group — the identifier that goes into the ``disabled`` set passed to
24 ``lexigram.plugins.discovery.discover_providers``.
26 ``requires``/``conflicts`` name other plugins' ``provider_entry_point``
27 values. They are advisory metadata: the boot engine evaluates them via
28 ``validate_plan`` and skips plugins whose dependencies are missing or
29 whose conflicts are enabled, logging non-fatal issues — boot is never
30 blocked.
31 """
33 name: str
34 display_name: str
35 description: str
36 icon: str
37 provider_entry_point: str
38 version: str = ""
39 requires: tuple[str, ...] = ()
40 conflicts: tuple[str, ...] = ()