pluginlist.py 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. import os
  2. import sys
  3. from typing import Dict, List, Optional, Tuple
  4. def load_plugin_list_if_exists(path: str) -> Optional[List[str]]:
  5. if not os.path.exists(path):
  6. return None
  7. plugins = []
  8. for plugin in load_plugin_list(path):
  9. if "@" in plugin:
  10. plugin, path = plugin.split("@", 1)
  11. sys.path.append(path)
  12. plugins.append(plugin)
  13. return plugins
  14. def load_plugin_list(path: str) -> List[str]:
  15. with open(path, "r") as f:
  16. data = f.read()
  17. return parse_plugins_list(data)
  18. def parse_plugins_list(data: str) -> List[str]:
  19. plugins: List[str] = []
  20. modules: Dict[str, Tuple[int, str]] = {}
  21. for line, entry in enumerate(data.splitlines()):
  22. plugin = entry.strip()
  23. if "#" in plugin:
  24. comment_start = plugin.find("#")
  25. plugin = plugin[:comment_start].strip()
  26. if not plugin:
  27. continue
  28. if "@" in plugin:
  29. module, path = map(lambda x: x.strip(), plugin.split("@", 1))
  30. plugin = f"{module}@{path}"
  31. validate_local_plugin(line, module, path)
  32. else:
  33. module = plugin
  34. if module in modules:
  35. first_line, first_entry = modules[module]
  36. raise ValueError(
  37. f"plugin '{module}' is listed more than once: "
  38. f"at line {first_line} ('{first_entry}') and at {line} ('{entry}')"
  39. )
  40. modules[module] = line, entry
  41. plugins.append(plugin)
  42. return plugins
  43. def validate_local_plugin(line: int, module: str, path: str):
  44. if not module:
  45. raise ValueError(f"local plugin entry at line {line} is missing a module name")
  46. if not path:
  47. raise ValueError(f"local plugin entry at line {line} is missing a path")