From 20170ce11a71e0a3202ec552437e7c2b2930db37 Mon Sep 17 00:00:00 2001 From: Nyanraltotlapun <38155247+Nyanraltotlapun@users.noreply.github.com> Date: Wed, 6 Aug 2025 14:17:44 +0200 Subject: [PATCH] Small cleanup and add FileLogger --- .gitignore | 2 + .../asynchronous/log_writers/file_writer.py | 52 +++++++++++++++++++ src/nyanger/asynchronous/nyan.py | 6 +-- .../process/log_writers/file_writer.py | 50 ++++++++++++++++++ src/nyanger/simple/log_writers/file_writer.py | 50 ++++++++++++++++++ 5 files changed, 157 insertions(+), 3 deletions(-) create mode 100644 src/nyanger/asynchronous/log_writers/file_writer.py create mode 100644 src/nyanger/process/log_writers/file_writer.py create mode 100644 src/nyanger/simple/log_writers/file_writer.py diff --git a/.gitignore b/.gitignore index 2dc53ca..d5d6fbf 100644 --- a/.gitignore +++ b/.gitignore @@ -158,3 +158,5 @@ cython_debug/ # and can be added to the global gitignore or merged into this file. For a more nuclear # option (not recommended) you can uncomment the following to ignore the entire idea folder. .idea/ + +uv.lock diff --git a/src/nyanger/asynchronous/log_writers/file_writer.py b/src/nyanger/asynchronous/log_writers/file_writer.py new file mode 100644 index 0000000..96c2437 --- /dev/null +++ b/src/nyanger/asynchronous/log_writers/file_writer.py @@ -0,0 +1,52 @@ +# Nyanger is a simple logger designed to be simple to use and simple to modify. +# +# Copyright (C) 2024 Kirill Harmatulla Shakirov kirill.shakirov@protonmail.com +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +import asyncio +from nyanger.asynchronous.nyan import LogLevel, LogMessage, LogWriter + + +class FileWriter(LogWriter): + """ + Simple implementation of LogWriter. + Writes log messages to file + """ + def __init__(self, file_name: str, loging_level: LogLevel = LogLevel.DEBUG): + """ + Initialize FileWriter instance. + :param file_name: log file name + :param loging_level: messages with severity less than this field value will be filtered out. + """ + self._loging_level = loging_level + self._file_name = file_name + self._log_file = None + + async def start(self, loop: asyncio.AbstractEventLoop): + self._log_file = open(self._file_name, mode="ta") + + async def write(self, msg: LogMessage): + """ + Formats and writes msg to log file. + :param msg: message to be logged. + """ + if msg.severity.value <= self._loging_level.value: + log_text = f"{msg.time.isoformat()} {msg.severity.name}: {msg.text}\n" + await asyncio.to_thread(self._log_file.write, (log_text,)) + # await asyncio.to_thread(self._log_file.flush) + + async def stop(self): + self._log_file.flush() + self._log_file.close() diff --git a/src/nyanger/asynchronous/nyan.py b/src/nyanger/asynchronous/nyan.py index cd670af..f99b89f 100644 --- a/src/nyanger/asynchronous/nyan.py +++ b/src/nyanger/asynchronous/nyan.py @@ -55,8 +55,8 @@ class LogWriter(ABC): Abstract class representing log writer interface. Must be implemented by a concrete log writer class. Only write method must be implemented, start and stop methods one should implement as needed. - Start method will be called by Nyanger inside log precess on its start. - And stop method will be called inside log process after exiting logging loop. + Start method will be called by Nyanger instance on its start. + And stop method will be called when stop() method of Nyanger instance called. """ @abstractmethod async def start(self, loop: asyncio.AbstractEventLoop): @@ -144,7 +144,7 @@ class Nyanger: Sending stop message to logging process and waits timeout seconds for process end. If process still active after timeout seconds - terminates it. :param timeout: Number of seconds to wait for process to terminate. - :param supress_timeout_error: Pum + :param supress_timeout_error: Supress timeout error raised when logger fails to stop in time. :return: """ await self._log_queue.put(self._STOP_MESSAGE) diff --git a/src/nyanger/process/log_writers/file_writer.py b/src/nyanger/process/log_writers/file_writer.py new file mode 100644 index 0000000..099c441 --- /dev/null +++ b/src/nyanger/process/log_writers/file_writer.py @@ -0,0 +1,50 @@ +# Nyanger is a simple logger designed to be simple to use and simple to modify. +# +# Copyright (C) 2024 Kirill Harmatulla Shakirov kirill.shakirov@protonmail.com +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +from nyanger.process.nyan import LogLevel, LogMessage, LogWriter + +class FileWriter(LogWriter): + """ + Simple implementation of LogWriter. + Writes log messages to file + """ + def __init__(self, file_name: str, loging_level: LogLevel = LogLevel.DEBUG): + """ + Initialize FileWriter instance. + :param file_name: log file name + :param loging_level: messages with severity less than this field value will be filtered out. + """ + self._loging_level = loging_level + self._file_name = file_name + self._log_file = None + + def start(self): + self._log_file = open(self._file_name, mode="ta") + + def write(self, msg: LogMessage): + """ + Formats and writes msg to log file. + :param msg: message to be logged. + """ + if msg.severity.value <= self._loging_level.value: + log_text = f"{msg.time.isoformat()} {msg.severity.name}: {msg.text}\n" + self._log_file.write(log_text) + self._log_file.flush() + + def stop(self): + self._log_file.flush() + self._log_file.close() diff --git a/src/nyanger/simple/log_writers/file_writer.py b/src/nyanger/simple/log_writers/file_writer.py new file mode 100644 index 0000000..34072f1 --- /dev/null +++ b/src/nyanger/simple/log_writers/file_writer.py @@ -0,0 +1,50 @@ +# Nyanger is a simple logger designed to be simple to use and simple to modify. +# +# Copyright (C) 2024 Kirill Harmatulla Shakirov kirill.shakirov@protonmail.com +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +from nyanger.simple.nyan import LogLevel, LogMessage, LogWriter + +class FileWriter(LogWriter): + """ + Simple implementation of LogWriter. + Writes log messages to file + """ + def __init__(self, file_name: str, loging_level: LogLevel = LogLevel.DEBUG): + """ + Initialize FileWriter instance. + :param file_name: log file name + :param loging_level: messages with severity less than this field value will be filtered out. + """ + self._loging_level = loging_level + self._file_name = file_name + self._log_file = None + + def start(self): + self._log_file = open(self._file_name, mode="ta") + + def write(self, msg: LogMessage): + """ + Formats and writes msg to log file. + :param msg: message to be logged. + """ + if msg.severity.value <= self._loging_level.value: + log_text = f"{msg.time.isoformat()} {msg.severity.name}: {msg.text}\n" + self._log_file.write(log_text) + self._log_file.flush() + + def stop(self): + self._log_file.flush() + self._log_file.close() \ No newline at end of file