[config] Suppression des nones dans le toml, sauvegarde de la config au chargement pour ajouter les nouveaux parametres

[bot-base] Gestion des erreurs
This commit is contained in:
Louis Chauvet 2020-04-24 12:10:33 +02:00
parent 1966b69d53
commit 75f524c509
Signed by: fomys
GPG Key ID: 1ECA046A9615ABA0
4 changed files with 66 additions and 31 deletions

View File

@ -5,6 +5,7 @@ import inspect
import logging
import os
import sys
import traceback
import discord
import toml
@ -85,7 +86,8 @@ class BotBase(discord.Client):
# Check if module exists
if not os.path.isdir(os.path.join(self.config["modules_folder"], module)):
self.warning(f"Attempt to load unknown module {module}.")
raise errors.ModuleNotFoundError(f"Module {module} not found in modules folder ({self.config['modules_folder']}.)")
raise errors.ModuleNotFoundError(
f"Module {module} not found in modules folder ({self.config['modules_folder']}.)")
if not os.path.isfile(os.path.join(self.config["modules_folder"], module, "infos.toml")):
self.warning(f"Attempt to load incompatible module {module}: no infos.toml found")
raise errors.IncompatibleModuleError(f"Module {module} is incompatible: no infos.toml found.")
@ -119,7 +121,11 @@ class BotBase(discord.Client):
# Check if module is meta
if infos.get("metamodule", False) == False:
# Check if module have __main_class__
try:
imported = importlib.import_module(module)
except Exception as e:
self.warning(f"Attempt to load incompatible module {module}: failed import")
raise e
try:
main_class = imported.__main_class__
except AttributeError:
@ -139,7 +145,8 @@ class BotBase(discord.Client):
dispatch = main_class.__dispatch__
except AttributeError:
self.warning(f"Attempt to load incompatible module {module}: __dispatch_ not found")
raise errors.IncompatibleModuleError(f"Module {module} mainclass ({main_class}) does not provide __dispatch__"
raise errors.IncompatibleModuleError(
f"Module {module} mainclass ({main_class}) does not provide __dispatch__"
f" attribute)")
# Check if __dispatch__ is function
if not inspect.isfunction(imported.__main_class__.__dispatch__):
@ -196,16 +203,19 @@ class BotBase(discord.Client):
for module in self.modules.values():
module["dispatch"](event, *args, **kwargs)
async def on_error(self, event_method, exc, *args, **kwargs):
self.error(f"Error in {event_method}: \n{exc}")
# Logging
def info(self, *args, **kwargs):
if self.log:
self.log.info(*args, **kwargs)
self.dispatch("log_info", *args, **kwargs)
def error(self, *args, **kwargs):
def error(self, e, *args, **kwargs):
if self.log:
self.log.error(*args, **kwargs)
self.dispatch("log_error", *args, **kwargs)
self.log.error(e, *args, **kwargs)
self.dispatch("log_error", e, *args, **kwargs)
def warning(self, *args, **kwargs):
if self.log:

View File

@ -1,5 +1,6 @@
from __future__ import annotations
import os
import typing
import toml
@ -75,8 +76,9 @@ class Config:
>>> config = Config("doctest_config.toml")
>>> config.register("my_parameter", factory(Int))
>>> config.set({"my_parameter": 3})
>>> config.save()
>>> config.save() #doctest: +SKIP
"""
os.makedirs(os.path.dirname(self.path), exist_ok=True)
with open(self.path, 'w') as file:
toml.dump({k: v.to_save() for k, v in self.fields.items()}, file)
@ -90,11 +92,11 @@ class Config:
>>> config = Config("doctest_config.toml")
>>> config.register("my_parameter", factory(Int))
>>> config.set({"my_parameter": 3})
>>> config.save()
>>> config.save() #doctest: +SKIP
>>> new_config = Config("doctest_config.toml")
>>> new_config.register("my_parameter", factory(Int))
>>> new_config.load()
>>> new_config["my_parameter"]
>>> new_config.load() #doctest: +SKIP
>>> new_config["my_parameter"] #doctest: +SKIP
3
:return: None
@ -103,6 +105,7 @@ class Config:
with open(self.path, 'r') as file:
self.set(toml.load(file))
except FileNotFoundError:
pass
self.save()
def __getitem__(self, item: str) -> typing.Any:

View File

@ -1,36 +1,57 @@
from __future__ import annotations
from typing import TYPE_CHECKING
import typing
import discord
from config.config_types.base_type import BaseType
if TYPE_CHECKING:
from main import LBI
if typing.TYPE_CHECKING:
from bot_base import BotBase
class Channel(BaseType):
client: LBI
client: BotBase
def __init__(self, client):
self.value = None
self.value = 0
self.channel_instance = None
self.client = client
def check_value(self, value):
id = value
if isinstance(value, discord.Guild):
id = value.id
if not self.client.is_ready():
self.client.warning(f"No check for channel {value} because client is not initialized!")
return True
if self.client.get_channel(id):
return True
return True
def set(self, value):
if self.check_value(value):
self.value = value
return
if not self.check_value(value):
raise ValueError("Tentative de définir une valeur incompatible")
self.value = value
self._update()
def get(self):
return self.value
self._update()
return self.channel_instance or self.value
def to_save(self):
return self.value
return self.value or 0
def load(self, value):
if self.check_value(value):
raise ValueError("Tentative de charger une donnée incompatible.")
self.value = value
self.set(value)
self._update()
def _update(self):
if self.client.is_ready() and self.channel_instance is None:
self.channel_instance = self.client.get_channel(self.value)
else:
self.channel_instance = None

View File

@ -29,7 +29,7 @@ class Guild(BaseType):
>>> Guild(client) #doctest: +SKIP
<config_types.discord_type.Guild object with value None>
"""
self.value = None
self.value = 0
self.guild_instance = None
self.client = client
@ -56,7 +56,7 @@ class Guild(BaseType):
if isinstance(value, discord.Guild):
id = value.id
if not self.client.is_ready():
self.client.warning("No check for guild `value` because client is not initialized!")
self.client.warning(f"No check for guild {value} because client is not initialized!")
return True
if self.client.get_guild(id):
return True
@ -119,7 +119,7 @@ class Guild(BaseType):
:return: Current id
:rtype: Optional[int]
"""
return self.value
return self.value or 0
def load(self, value):
"""
@ -140,6 +140,7 @@ class Guild(BaseType):
if self.check_value(value):
raise ValueError("Tentative de charger une donnée incompatible.")
self.set(value)
self._update()
def __repr__(self):
return f'<config_types.discord_types.guild object with value {self.value}>'