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