diff --git a/.gitignore b/.gitignore index eba74f4..e5a42ed 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ -venv/ \ No newline at end of file +venv/ +*.log \ No newline at end of file diff --git a/src/__init__.py b/src/__init__.py index 8f96e54..90bc100 100644 --- a/src/__init__.py +++ b/src/__init__.py @@ -1,11 +1,12 @@ -from lib import BaseLogger -from lib import Logger +from .lib.Logger import Logger _logger = None -def get_or_create_logger() -> Logger: +def get_or_create_logger(logger: Logger = None) -> Logger: global _logger if _logger is None: - _logger = Logger() + if not logger: + raise Exception("Global logger not found.") + _logger = logger return _logger diff --git a/src/lib/BaseLogger.py b/src/lib/BaseLogger.py deleted file mode 100644 index 20dc40b..0000000 --- a/src/lib/BaseLogger.py +++ /dev/null @@ -1,36 +0,0 @@ -from .Log import Log -from .LogLevels import basic_levels, Level -from .console import util -import inspect - - -class BaseLogger: - def __init__(self, name: str = "Generic", do_colors = True): - self.name = name - self.do_colors = do_colors - - def _log(self, log: Log): - l_pre = f"{log.level.short} [{log.format_time('%Y-%m-%d %H:%M:%S')}] <{log.class_str() or log.file}>" - l_str = f"{log.format_text()}" - if self.do_colors: - print(f"{log.level.color}{l_pre}{util.reset} {l_str}") - else: - print(f'{l_pre} {l_str}') - - def custom(self, level: Level, text: str, *args, _class=None, _file=inspect.stack()[1].filename): - self._log(Log(level, text, *args, _class=None, _file=inspect.stack()[1].filename)) - - def debug(self, text: str, *args, _class=None): - self._log(Log(basic_levels['DEBUG'], text, *args, _class=_class, _file=inspect.stack()[1].filename)) - - def info(self, text: str, *args, _class=None): - self._log(Log(basic_levels['INFO'], text, *args, _class=_class, _file=inspect.stack()[1].filename)) - - def warn(self, text: str, *args, _class=None): - self._log(Log(basic_levels['WARNING'], text, *args, _class=_class, _file=inspect.stack()[1].filename)) - - def err(self, text: str, *args, _class=None): - self._log(Log(basic_levels['ERROR'], text, *args, _class=_class, _file=inspect.stack()[1].filename)) - - def fatal(self, text: str, *args, _class=None): - self._log(Log(basic_levels['FATAL'], text, *args, _class=_class, _file=inspect.stack()[1].filename)) diff --git a/src/lib/Log.py b/src/lib/Log.py index 9673478..f7b9800 100644 --- a/src/lib/Log.py +++ b/src/lib/Log.py @@ -5,7 +5,7 @@ from .LogLevels import Level class Log: - def __init__(self, level: Level, text: str, *args, _class=None, _file=inspect.stack()[1].filename): + def __init__(self, level: Level, text: str, *args, _object=None, _file=inspect.stack()[1].filename): """ Create a log message. """ @@ -14,17 +14,17 @@ class Log: self.args = args self.created_on = time.time() self.file = _file - self._class = _class + self._object = _object def format_time(self, fmt: str): return datetime.datetime.fromtimestamp(self.created_on).strftime(fmt) def class_str(self): - if self._class: - prefix = f'{type(self._class).__name__}' - if hasattr(self._class, 'name'): + if self._object: + prefix = f'{type(self._object).__name__}' + if hasattr(self._object, 'name'): prefix += ":" - prefix += self._class.name + prefix += self._object.name return prefix else: return None diff --git a/src/lib/LogLevels.py b/src/lib/LogLevels.py index 01b73dc..2bd6992 100644 --- a/src/lib/LogLevels.py +++ b/src/lib/LogLevels.py @@ -1,7 +1,7 @@ -from lib import console +from . import console class Level: - def __init__(self, name: str, weight: int, short_name: str or None = None, _color: str = console.fg.white): + def __init__(self, name: str, weight: int, short_name: str or None = None, _color: str = console.FG.white): """ Create a logging level. """ @@ -15,9 +15,9 @@ class Level: basic_levels = { - 'FATAL': Level('FATAL', 10, _color=(console.fg.red + console.util.bold)), - 'ERROR': Level('ERROR', 3, _color=console.fg.red), - 'WARNING': Level('WARNING', 2, _color=console.fg.yellow), - 'INFO': Level('INFO', 1, _color=console.fg.blue), - 'DEBUG': Level('DEBUG', 0, _color=console.fg.green) + 'FATAL': Level('FATAL', 10, _color=(console.FG.red + console.Utils.bold)), + 'ERROR': Level('ERROR', 3, _color=console.FG.red), + 'WARNING': Level('WARNING', 2, _color=(console.FG.yellow + console.Utils.bold + console.Utils.underline)), + 'INFO': Level('INFO', 1, _color=console.FG.blue), + 'DEBUG': Level('DEBUG', 0, _color=console.FG.green) } diff --git a/src/lib/Logger.py b/src/lib/Logger.py index d68ed25..f56f0ef 100644 --- a/src/lib/Logger.py +++ b/src/lib/Logger.py @@ -1,4 +1,41 @@ -from .BaseLogger import BaseLogger +import sys +from .Log import Log +from .LogLevels import basic_levels, Level +from .console import Utils +import inspect -class Logger(BaseLogger): - pass \ No newline at end of file + +class Logger: + def __init__(self, name: str = "Generic", do_colors = True, output = sys.stdout): + self.name = name + self.do_colors = do_colors + self.output = output + + def _print(self, data: str, terminator: str = '\r\n'): + self.output.write(data + terminator) + + def _log(self, log: Log): + l_pre = f"{log.level.short} [{log.format_time('%Y-%m-%d %H:%M:%S')}] <{log.class_str() or log.file}>" + l_str = f"{log.format_text()}" + if self.do_colors: + self._print(f"{log.level.color}{l_pre}{Utils.reset} {l_str}") + else: + self._print(f'{l_pre} {l_str}') + + def custom(self, level: Level, text: str, *args, _object=None, _file=inspect.stack()[1].filename): + self._log(Log(level, text, *args, _object=None, _file=inspect.stack()[1].filename)) + + def debug(self, text: str, *args, _object=None): + self._log(Log(basic_levels['DEBUG'], text, *args, _object=_object, _file=inspect.stack()[1].filename)) + + def info(self, text: str, *args, _object=None): + self._log(Log(basic_levels['INFO'], text, *args, _object=_object, _file=inspect.stack()[1].filename)) + + def warn(self, text: str, *args, _object=None): + self._log(Log(basic_levels['WARNING'], text, *args, _object=_object, _file=inspect.stack()[1].filename)) + + def err(self, text: str, *args, _object=None): + self._log(Log(basic_levels['ERROR'], text, *args, _object=_object, _file=inspect.stack()[1].filename)) + + def fatal(self, text: str, *args, _object=None): + self._log(Log(basic_levels['FATAL'], text, *args, _object=_object, _file=inspect.stack()[1].filename)) diff --git a/src/lib/MultiLogger.py b/src/lib/MultiLogger.py new file mode 100644 index 0000000..b9a86f3 --- /dev/null +++ b/src/lib/MultiLogger.py @@ -0,0 +1,12 @@ +from .Logger import Logger +from .Log import Log + + +class MultiLogger(Logger): + def __init__(self, sub_loggers: list[Logger], _name="Generic_MultiLogger"): + super().__init__(name=_name) + self._sub_loggers = sub_loggers + + def _log(self, log: Log): + for sl in self._sub_loggers: + sl._log(log) diff --git a/src/lib/console.py b/src/lib/console.py index 3153931..b94c759 100644 --- a/src/lib/console.py +++ b/src/lib/console.py @@ -1,93 +1,95 @@ from sys import stdout, stdin from time import sleep -class fg: - black = "\u001b[30m" - red = "\u001b[31m" - green = "\u001b[32m" - yellow = "\u001b[33m" - blue = "\u001b[34m" - magenta = "\u001b[35m" - cyan = "\u001b[36m" - white = "\u001b[37m" - def rgb(r, g, b): return f"\u001b[38;2;{r};{g};{b}m" +class FG: + black = "\u001b[30m" + red = "\u001b[31m" + green = "\u001b[32m" + yellow = "\u001b[33m" + blue = "\u001b[34m" + magenta = "\u001b[35m" + cyan = "\u001b[36m" + white = "\u001b[37m" -class bg: - black = "\u001b[40m" - red = "\u001b[41m" - green = "\u001b[42m" - yellow = "\u001b[43m" - blue = "\u001b[44m" - magenta = "\u001b[45m" - cyan = "\u001b[46m" - white = "\u001b[47m" - - def rgb(r, g, b): return f"\u001b[48;2;{r};{g};{b}m" + def rgb(r, g, b): return f"\u001b[38;2;{r};{g};{b}m" -class util: - reset = "\u001b[0m" - bold = "\u001b[1m" - underline = "\u001b[4m" - reverse = "\u001b[7m" +class BG: + black = "\u001b[40m" + red = "\u001b[41m" + green = "\u001b[42m" + yellow = "\u001b[43m" + blue = "\u001b[44m" + magenta = "\u001b[45m" + cyan = "\u001b[46m" + white = "\u001b[47m" - clear = "\u001b[2J" - clearline = "\u001b[2K" + def rgb(r, g, b): return f"\u001b[48;2;{r};{g};{b}m" - up = "\u001b[1A" - down = "\u001b[1B" - right = "\u001b[1C" - left = "\u001b[1D" - nextline = "\u001b[1E" - prevline = "\u001b[1F" +class Utils: + reset = "\u001b[0m" + bold = "\u001b[1m" + underline = "\u001b[4m" + reverse = "\u001b[7m" - top = "\u001b[0;0H" + clear = "\u001b[2J" + clear_line = "\u001b[2K" - def to(x, y): - return f"\u001b[{y};{x}H" + up = "\u001b[1A" + down = "\u001b[1B" + right = "\u001b[1C" + left = "\u001b[1D" - def write(text="\n"): - stdout.write(text) - stdout.flush() + nextline = "\u001b[1E" + prevline = "\u001b[1F" - def writew(text="\n", wait=0.5): - for char in text: - stdout.write(char) - stdout.flush() - sleep(wait) + top = "\u001b[0;0H" - def read(begin=""): - text = "" + def to(x, y): + return f"\u001b[{y};{x}H" - stdout.write(begin) - stdout.flush() + def write(text="\n"): + stdout.write(text) + stdout.flush() - while True: - char = ord(stdin.read(1)) + def writew(text="\n", wait=0.5): + for char in text: + stdout.write(char) + stdout.flush() + sleep(wait) - if char == 3: - return - elif char in (10, 13): - return text - else: - text += chr(char) + def read(begin=""): + text = "" - def readw(begin="", wait=0.5): - text = "" + stdout.write(begin) + stdout.flush() - for char in begin: - stdout.write(char) - stdout.flush() - sleep(wait) + while True: + char = ord(stdin.read(1)) - while True: - char = ord(stdin.read(1)) + if char == 3: + return + elif char in (10, 13): + return text + else: + text += chr(char) - if char == 3: - return - elif char in (10, 13): - return text - else: - text += chr(char) \ No newline at end of file + def readw(begin="", wait=0.5): + text = "" + + for char in begin: + stdout.write(char) + stdout.flush() + sleep(wait) + + while True: + char = ord(stdin.read(1)) + + if char == 3: + return + elif char in (10, 13): + return text + else: + text += chr(char) diff --git a/src/test.py b/src/test.py index 916caf3..72e195a 100644 --- a/src/test.py +++ b/src/test.py @@ -1,8 +1,27 @@ -from lib.BaseLogger import BaseLogger +from lib.Logger import Logger +from lib.MultiLogger import MultiLogger from lib.LogLevels import Level from lib.Log import Log from lib import console -_LOGGER = BaseLogger("Generic") +_LOGGER = Logger("Generic") -_LOGGER.info("Started Loco {}", "v1") +_LOGGER.info("This is a simple log {}", "message.") + +custom_level = Level("FAULTY_LEVEL", 100, "*", (console.Utils.underline + console.Utils.bold + console.FG.cyan)) +_LOGGER.custom(custom_level, "ok") + +_temp_logger = Logger("tmp_logger", False, open("logs.log", 'a+')) +_MultiLogger = MultiLogger([_LOGGER, _temp_logger], "Potato") + +_MultiLogger.warn("OK") + + +class User: + name = "faulty" + pass + + +u = User() + +_LOGGER.info("logged in.", _object=u)