MCPcopy Create free account
hub / github.com/Dispatcharr/Dispatcharr / PluginManager

Class PluginManager

apps/plugins/loader.py:39–853  ·  view source on GitHub ↗

Singleton manager that discovers and runs plugins from /data/plugins.

Source from the content-addressed store, hash-verified

37
38
39class PluginManager:
40 """Singleton manager that discovers and runs plugins from /data/plugins."""
41
42 _instance: Optional["PluginManager"] = None
43
44 @classmethod
45 def get(cls) -> "PluginManager":
46 if not cls._instance:
47 cls._instance = PluginManager()
48 return cls._instance
49
50 def __init__(self) -> None:
51 self.plugins_dir = os.environ.get("DISPATCHARR_PLUGINS_DIR", "/data/plugins")
52 self._registry: Dict[str, LoadedPlugin] = {}
53 self._package_names: Dict[str, str] = {}
54 self._alias_names: Dict[str, str] = {}
55 self._reload_token_path = os.path.join(self.plugins_dir, ".reload_token")
56 self._last_reload_token = 0.0
57 self._discovery_completed = False
58 self._lock = threading.RLock()
59
60 # Ensure plugins directory exists
61 os.makedirs(self.plugins_dir, exist_ok=True)
62 if self.plugins_dir not in sys.path:
63 sys.path.append(self.plugins_dir)
64
65 def discover_plugins(
66 self,
67 *,
68 sync_db: bool = True,
69 force_reload: bool = False,
70 use_cache: bool = False,
71 ) -> Dict[str, LoadedPlugin]:
72 token = self._get_reload_token()
73 if use_cache and not force_reload:
74 with self._lock:
75 if self._discovery_completed and token <= self._last_reload_token:
76 return self._registry
77 if token > self._last_reload_token:
78 force_reload = True
79 if force_reload:
80 self._touch_reload_token()
81 token = self._get_reload_token()
82
83 if sync_db:
84 logger.info(f"Discovering plugins in {self.plugins_dir}")
85 else:
86 logger.debug(f"Discovering plugins (no DB sync) in {self.plugins_dir}")
87
88 with self._lock:
89 previous_packages = dict(self._package_names)
90 previous_aliases = dict(self._alias_names)
91 previous_paths = {
92 key: lp.path for key, lp in self._registry.items() if lp and lp.path
93 }
94
95 try:
96 return self._discover_plugins_impl(

Calls

no outgoing calls