Source code for errbot.plugin_info
import sys
import inspect
from configparser import ConfigParser
from dataclasses import dataclass
from importlib._bootstrap import module_from_spec
from importlib._bootstrap_external import spec_from_file_location
from errbot.utils import version2tuple
from pathlib import Path
from typing import Tuple, List, Type
from configparser import Error as ConfigParserError
VersionType = Tuple[int, int, int]
[docs]@dataclass
class PluginInfo:
name: str
module: str
doc: str
core: bool
python_version: VersionType
errbot_minversion: VersionType
errbot_maxversion: VersionType
dependencies: List[str]
location: Path = None
[docs] @staticmethod
def load(plugfile_path: Path) -> 'PluginInfo':
with plugfile_path.open(encoding='utf-8') as plugfile:
return PluginInfo.load_file(plugfile, plugfile_path)
[docs] @staticmethod
def load_file(plugfile, location: Path) -> 'PluginInfo':
cp = ConfigParser()
cp.read_file(plugfile)
pi = PluginInfo.parse(cp)
pi.location = location
return pi
[docs] @staticmethod
def parse(config: ConfigParser) -> 'PluginInfo':
"""
Throws ConfigParserError with a meaningful message if the ConfigParser doesn't contain the minimal
information required.
"""
name = config.get('Core', 'Name')
module = config.get('Core', 'Module')
core = config.get('Core', 'Core', fallback='false').lower() == 'true'
doc = config.get('Documentation', 'Description', fallback=None)
python_version = config.get('Python', 'Version', fallback=None)
# Old format backward compatibility
if python_version:
if python_version in ('2+', '3'):
python_version = (3, 0, 0)
elif python_version == '2':
python_version = (2, 0, 0)
else:
try:
python_version = tuple(version2tuple(python_version)[0:3]) # We can ignore the alpha/beta part.
except ValueError as ve:
raise ConfigParserError(f'Invalid Python Version format: {python_version} ({ve})')
min_version = config.get('Errbot', 'Min', fallback=None)
max_version = config.get('Errbot', 'Max', fallback=None)
try:
if min_version:
min_version = version2tuple(min_version)
except ValueError as ve:
raise ConfigParserError(f'Invalid Errbot min version format: {min_version} ({ve})')
try:
if max_version:
max_version = version2tuple(max_version)
except ValueError as ve:
raise ConfigParserError(f'Invalid Errbot max version format: {max_version} ({ve})')
depends_on = config.get('Core', 'DependsOn', fallback=None)
deps = [name.strip() for name in depends_on.split(',')] if depends_on else []
return PluginInfo(name, module, doc, core, python_version, min_version, max_version, deps)
[docs] def load_plugin_classes(self, base_module_name: str, baseclass: Type):
# load the module
module_name = base_module_name + '.' + self.module
spec = spec_from_file_location(module_name, self.location.parent / (self.module + '.py'))
modu1e = module_from_spec(spec)
spec.loader.exec_module(modu1e)
sys.modules[module_name] = modu1e
# introspect the modules to find plugin classes
def is_plugin(member):
return inspect.isclass(member) and issubclass(member, baseclass) and member != baseclass
plugin_classes = inspect.getmembers(modu1e, is_plugin)
return plugin_classes