您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

198 行
7.9 KiB

此行包含模棱两可的 Unicode 字符!

此文件包含模棱两可的 Unicode 字符,这些字符可能会与您当前语言环境的其他字符混淆。 如果您是有意且正当地使用它们,您可以安全地忽略这个警告。使用 Escape 按钮来高亮这些字符。

import os
import asyncio
import importlib
from typing import Dict, Optional, List, Union
from logging.config import dictConfig
from logging import getLogger, Logger
from ..variables.loader import Datavars
from ..commands.commands import Command, CommandRunner
from .utils.responses import ResponseStructure
# from .utils.workers import Worker
from .schemas.config import ConfigSchema
from calculate.utils.tools import Singleton
# Получаем конфигурацию сервера.
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(metaclass=Singleton):
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 и экземпляров процессов-воркеров, передаваемых воркерам.
# TODO добавить менеджера воркеров.
# 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
class Commands:
'''Предварительная реализация контейнера описаний команд.'''
def __init__(self, *commands: List[Command]):
self._by_id: dict = dict()
self._by_command: dict = dict()
for command in commands:
self._by_id[command.id] = command
self._by_command[command.command] = command
def get_commands(self, base_url: str) -> Dict[str, dict]:
response = dict()
for command in self._by_id.values():
data = ResponseStructure(base_url)
data.add_data(id=command.id,
title=command.title,
category=command.category,
command=command.command)
data.add_link("self", f"/commands/{command.id}?by_id=true")
data.add_link("parameters", f"/commands/{command.id}/parameters")
data.add_link("configure", f"/configs/{command.id}")
response[command.id] = data.get_dict()
return response
def get_by_id(self, command_id: str, base_url: str) -> Dict[str, Dict]:
if command_id in self._by_id:
command = self._by_id[command_id]
data = ResponseStructure(base_url)
data.add_data(id=command.id,
title=command.title,
category=command.category,
command=command.command)
data.add_link("self", f"/commands/{command.id}?by_id=1")
data.add_link("parameters", f"/commands/{command.id}/parameters")
data.add_link("configure", f"/configs/{command.id}")
parameters_data = self._get_parameters_data(command.parameters,
command.id, base_url)
data.embed("parameters", parameters_data)
return data.get_dict()
return None
def find_command(self, console_command: str,
base_url: str) -> Union[dict, None]:
if console_command in self._by_command:
command = self._by_command[console_command]
data = ResponseStructure(base_url)
data.add_data(id=command.id,
title=command.title,
category=command.category,
command=command.command)
data.add_link("self", f"/commands/{command.id}?by_id=1")
data.add_link("parameters", f"/commands/{command.id}/parameters")
data.add_link("configure", f"/configs/{command.id}")
parameters_data = self._get_parameters_data(command.parameters,
command.id, base_url)
data.embed("parameters", parameters_data)
return data.get_dict()
else:
return None
def get_parameters(self, command_id: str, base_url: str
) -> Union[dict, None]:
if command_id in self._by_id:
command = self._by_id[command_id]
parameters_data = self._get_parameters_data(command.parameters,
command.id, base_url)
return parameters_data
else:
return None
def get_command_object(self, command_id: str) -> Command:
if command_id in self._by_id:
return self._by_id[command_id]
return None
def _get_parameters_data(self, parameters: list, command_id: str,
base_url: str) -> List[dict]:
data = ResponseStructure(base_url)
data.add_data(parameters)
data.add_link("self", f"/commands/{command_id}/parameters")
return data.get_dict()