mirror of
https://gitflic.ru/project/maks1ms/ocab.git
synced 2025-10-11 06:22:37 +03:00
добавлена проверка зависимостей
This commit is contained in:
@@ -12,6 +12,8 @@ class ModuleInfo:
|
||||
description: str
|
||||
version: str
|
||||
author: str
|
||||
privileged: bool
|
||||
dependencies: dict
|
||||
|
||||
|
||||
class AbstractLoader:
|
||||
|
@@ -18,13 +18,9 @@ class FSLoader(UnsafeFSLoader):
|
||||
self.builtins["__import__"] = self._hook_import
|
||||
|
||||
def load(self):
|
||||
# TODO handle dependencies from info
|
||||
|
||||
self.info()
|
||||
|
||||
# with open(os.path.join(self.path, "__init__.py"), "r") as f:
|
||||
# source = f.read()
|
||||
|
||||
info = self.info()
|
||||
if info.privileged:
|
||||
raise Exception("Only non privileged modules are allowed to be imported")
|
||||
return self._hook_import(".")
|
||||
|
||||
def _resolve_module_from_path(self, module_name: str):
|
||||
@@ -52,8 +48,7 @@ class FSLoader(UnsafeFSLoader):
|
||||
if name == allowed or name.startswith(f"{allowed}."):
|
||||
return __import__(name, *args, **kwargs)
|
||||
|
||||
# TODO: allow only public api for modules
|
||||
if name.startswith("ocab_core."):
|
||||
if name == "ocab_core.modules_system.public_api":
|
||||
return __import__(name, *args, **kwargs)
|
||||
|
||||
module_file_path = self._resolve_module_from_path(name)
|
||||
|
@@ -1,12 +1,48 @@
|
||||
import semver
|
||||
|
||||
from ocab_core.modules_system.loaders.base import AbstractLoader
|
||||
|
||||
|
||||
def is_version_compatible(version, requirement):
|
||||
def parse_requirement(req):
|
||||
if req.startswith("^"):
|
||||
base_version = req[1:]
|
||||
base_version_info = semver.VersionInfo.parse(base_version)
|
||||
range_start = base_version_info
|
||||
range_end = base_version_info.bump_major()
|
||||
return [f">={range_start}", f"<{range_end}"]
|
||||
else:
|
||||
return [req]
|
||||
|
||||
for r in parse_requirement(requirement):
|
||||
if not semver.Version.parse(version).match(r):
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
class ModulesManager:
|
||||
def __init__(self):
|
||||
self.modules = {}
|
||||
|
||||
def load(self, loader: AbstractLoader):
|
||||
info = loader.info()
|
||||
|
||||
if info.id in self.modules:
|
||||
return
|
||||
|
||||
for dependency, version in info.dependencies.items():
|
||||
if dependency not in self.modules:
|
||||
raise Exception(
|
||||
f"Module {info.id} depends on {dependency}, but it is not loaded"
|
||||
)
|
||||
loaded_dependency_info = self.modules[dependency]["info"]
|
||||
if not is_version_compatible(loaded_dependency_info.version, version):
|
||||
raise Exception(
|
||||
f"Module {info.id} depends on {dependency}, "
|
||||
f"but version {version} is not compatible"
|
||||
)
|
||||
|
||||
module = loader.load()
|
||||
|
||||
self.modules[info.id] = {
|
||||
|
@@ -1 +1,3 @@
|
||||
from ocab_core.logger import log # noqa
|
||||
|
||||
from .public_api import Storage, get_module, register_router
|
||||
|
@@ -3,7 +3,7 @@
|
||||
"name": "Config YAML",
|
||||
"description": "Модуль для работы с конфигурационным файлом бота (YAML)",
|
||||
"author": "OCAB Team",
|
||||
"version": "1.0",
|
||||
"version": "1.0.0",
|
||||
"privileged": true,
|
||||
"dependencies": {}
|
||||
}
|
||||
|
@@ -3,7 +3,7 @@
|
||||
"name": "Database",
|
||||
"description": "Модуль для работы с БД",
|
||||
"author": "OCAB Team",
|
||||
"version": "1.0",
|
||||
"version": "1.0.0",
|
||||
"privileged": true,
|
||||
"dependencies": {}
|
||||
}
|
||||
|
@@ -1,24 +1,18 @@
|
||||
# flake8: noqa
|
||||
from typing import Any, Type
|
||||
from typing import Type
|
||||
|
||||
from aiogram import Bot
|
||||
from aiogram.types import Message
|
||||
|
||||
from ocab_core.logger import log
|
||||
from ocab_core.modules_system.public_api import get_module
|
||||
from ocab_core.modules_system.public_api import get_module, log
|
||||
|
||||
from .interfaces import IDbApi, IRoles
|
||||
|
||||
# from src.modules.standard.database import db_api
|
||||
|
||||
|
||||
db_api: Type[IDbApi] = get_module(
|
||||
"standard.database",
|
||||
"db_api",
|
||||
)
|
||||
|
||||
# db_api.init_db_connection()
|
||||
|
||||
Roles: Type[IRoles] = get_module("standard.roles", "Roles")
|
||||
|
||||
|
||||
|
@@ -3,9 +3,10 @@
|
||||
"name": "Info",
|
||||
"description": "Модуль с информацией",
|
||||
"author": "OCAB Team",
|
||||
"version": "1.0",
|
||||
"version": "1.0.0",
|
||||
"privileged": false,
|
||||
"dependencies": {
|
||||
"standard.roles": "^1.0.0"
|
||||
"standard.roles": "^1.0.0",
|
||||
"standard.database": "^1.0.0"
|
||||
}
|
||||
}
|
||||
|
@@ -3,7 +3,7 @@
|
||||
"name": "Roles",
|
||||
"description": "Модуль для работы с ролями",
|
||||
"author": "OCAB Team",
|
||||
"version": "1.0",
|
||||
"version": "1.0.0",
|
||||
"privileged": true,
|
||||
"dependencies": {
|
||||
"standard.config": "^1.0.0",
|
||||
|
Reference in New Issue
Block a user