|
@@ -0,0 +1,62 @@
|
|
|
|
+import os
|
|
|
|
+import sys
|
|
|
|
+from typing import Dict, List, Optional, Tuple
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+def load_plugin_list_if_exists(path: str) -> Optional[List[str]]:
|
|
|
|
+ if not os.path.exists(path):
|
|
|
|
+ return None
|
|
|
|
+
|
|
|
|
+ plugins = []
|
|
|
|
+ for plugin in load_plugin_list(path):
|
|
|
|
+ if "@" in plugin:
|
|
|
|
+ plugin, path = plugin.split("@", 1)
|
|
|
|
+ sys.path.append(path)
|
|
|
|
+ plugins.append(plugin)
|
|
|
|
+
|
|
|
|
+ return plugins
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+def load_plugin_list(path: str) -> List[str]:
|
|
|
|
+ with open(path, "r") as f:
|
|
|
|
+ data = f.read()
|
|
|
|
+ return parse_plugins_list(data)
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+def parse_plugins_list(data: str) -> List[str]:
|
|
|
|
+ plugins: List[str] = []
|
|
|
|
+ modules: Dict[str, Tuple[int, str]] = {}
|
|
|
|
+
|
|
|
|
+ for line, entry in enumerate(data.splitlines()):
|
|
|
|
+ plugin = entry.strip()
|
|
|
|
+
|
|
|
|
+ if "#" in plugin:
|
|
|
|
+ comment_start = plugin.find("#")
|
|
|
|
+ plugin = plugin[:comment_start].strip()
|
|
|
|
+ if not plugin:
|
|
|
|
+ continue
|
|
|
|
+
|
|
|
|
+ if "@" in plugin:
|
|
|
|
+ module, path = map(lambda x: x.strip(), plugin.split("@", 1))
|
|
|
|
+ plugin = f"{module}@{path}"
|
|
|
|
+ validate_local_plugin(line, module, path)
|
|
|
|
+ else:
|
|
|
|
+ module = plugin
|
|
|
|
+ if module in modules:
|
|
|
|
+ first_line, first_entry = modules[module]
|
|
|
|
+ raise ValueError(
|
|
|
|
+ f"plugin '{module}' is listed more than once: "
|
|
|
|
+ f"at line {first_line} ('{first_entry}') and at {line} ('{entry}')"
|
|
|
|
+ )
|
|
|
|
+ modules[module] = line, entry
|
|
|
|
+
|
|
|
|
+ plugins.append(plugin)
|
|
|
|
+
|
|
|
|
+ return plugins
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+def validate_local_plugin(line: int, module: str, path: str):
|
|
|
|
+ if not module:
|
|
|
|
+ raise ValueError(f"local plugin entry at line {line} is missing a module name")
|
|
|
|
+ if not path:
|
|
|
|
+ raise ValueError(f"local plugin entry at line {line} is missing a path")
|