import os import asyncio import importlib from typing import Dict, Optional from logging.config import dictConfig from logging import getLogger, Logger from ..variables.loader import Datavars from ..commands.commands import Command, CommandRunner from .utils.workers import Worker from .schemas.config import ConfigSchema # Получаем конфигурацию сервера. TESTING = bool(os.environ.get("TESTING", False)) if not TESTING: from .config import config server_config = ConfigSchema(**config) else: from tests.server.config import config server_config = ConfigSchema(**config) class ServerData: def __init__(self, config: ConfigSchema = server_config): self.event_loop = asyncio.get_event_loop() self._variables_path = config.variables_path # Конфигурируем логгирование. dictConfig(config.logger_config) self.logger: Logger = getLogger("main") self.log_message = {'DEBUG': self.logger.debug, 'INFO': self.logger.info, 'WARNING': self.logger.warning, 'ERROR': self.logger.error, 'CRITICAL': self.logger.critical} self._datavars: Optional[Datavars] = None # Словарь описаний команд. self.commands: Dict[str, Command] = self._get_commands_descriptions( config.commands_path) # Словарь CID и экземпляров команд, передаваемых воркерам. self.commands_runners: Dict[str, CommandRunner] = {} # Словарь WID и экземпляров процессов-воркеров, передаваемых воркерам. self.workers: Dict[int, Worker] = {} @property def datavars(self): if self._datavars is not None: return self._datavars else: self._datavars = self._load_datavars(self._variables_path, self.logger) return self._datavars def _load_datavars(vars_path: str, logger: Logger) -> Datavars: return Datavars(variables_path=vars_path, logger=logger) def _get_commands_descriptions(self, commands_path: str ) -> Dict[str, Command]: '''Метод для получения совокупности описаний команд.''' output = {} package = ".".join(commands_path.split("/")) for entry in os.scandir(commands_path): if (not entry.name.endswith('.py') or entry.name in {"commands.py", "__init__.py"}): continue module_name = entry.name[:-3] try: module = importlib.import_module("{}.{}".format(package, module_name)) for obj_name in dir(module): obj = module.__getattribute__(obj_name) if isinstance(obj, Command): output[obj.id] = obj except Exception: continue return output def make_command(self, command_id: str, ) -> int: '''Метод для создания команды по ее описанию.''' command_description = self.commands[command_id] def _get_worker_object(self, wid: Optional[int] = None) -> Worker: '''Метод для получения воркера для команды.''' if wid is not None: worker = Worker(wid, self._event_loop, self._datavars) self._workers[wid] = worker elif not self._workers: worker = Worker(0, self._event_loop, self._datavars) self._workers[0] = worker else: wid = max(self._workers.keys()) + 1 worker = Worker(wid, self._event_loop, self._datavars) self._workers[wid] = worker return worker