Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Log rewrite #107

Merged
merged 13 commits into from
May 18, 2024
4 changes: 2 additions & 2 deletions IoTuring/ClassManager/ClassManager.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ def GetModuleFilePaths(self) -> list[Path]:
if not classesRootPath.exists:
raise Exception(f"Path does not exist: {classesRootPath}")

self.Log(self.LOG_DEVELOPMENT,
self.Log(self.LOG_DEBUG,
f'Looking for python files in "{classesRootPath}"...')

python_files = classesRootPath.rglob("*.py")
Expand All @@ -63,7 +63,7 @@ def GetModuleFilePaths(self) -> list[Path]:
raise FileNotFoundError(
f"No module files found in {classesRootPath}")

self.Log(self.LOG_DEVELOPMENT,
self.Log(self.LOG_DEBUG,
f"Found {str(len(filepaths))} modules files")

return filepaths
Expand Down
13 changes: 6 additions & 7 deletions IoTuring/Configurator/Configurator.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import os
import subprocess
import shutil
import sys

from IoTuring.Configurator.MenuPreset import QuestionPreset
Expand All @@ -13,6 +12,7 @@
from IoTuring.Logger.LogObject import LogObject
from IoTuring.Exceptions.Exceptions import UserCancelledException
from IoTuring.MyApp.SystemConsts import OperatingSystemDetection as OsD
from IoTuring.MyApp.SystemConsts import TerminalDetection

from InquirerPy import inquirer
from InquirerPy.separator import Separator
Expand Down Expand Up @@ -457,16 +457,13 @@ def DisplayMenu(self, choices: list, message: str = "", add_back_choice=True, **
# Default max_height:
kwargs["max_height"] = "100%"

# Actual lines in the terminal. fallback to 0 on error:
terminal_lines = shutil.get_terminal_size(fallback=(0, 0)).lines

# Check for pinned messages:
if terminal_lines > 0 and self.pinned_lines > 0:
if TerminalDetection.CheckTerminalSupportsSize() and self.pinned_lines > 0:

# Lines of message and instruction if too long:
if "instruction" in kwargs:
message_lines = ((len(kwargs["instruction"]) + len(message) + 3)
/ shutil.get_terminal_size().columns) // 1
message_lines = TerminalDetection.CalculateNumberOfLines(
len(kwargs["instruction"]) + len(message) + 3)
# Add only the line of the message:
else:
message_lines = 1
Expand All @@ -475,6 +472,8 @@ def DisplayMenu(self, choices: list, message: str = "", add_back_choice=True, **
required_lines = len(choices) + \
self.pinned_lines + message_lines

terminal_lines = TerminalDetection.GetTerminalLines()

# Set the calculated height:
if required_lines > terminal_lines:
kwargs["max_height"] = terminal_lines \
Expand Down
8 changes: 4 additions & 4 deletions IoTuring/Configurator/ConfiguratorIO.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ def readConfigurations(self):
try:
with open(self.getFilePath(), "r", encoding="utf-8") as f:
config = json.loads(f.read())
self.Log(self.LOG_MESSAGE, f"Loaded \"{self.getFilePath()}\"")
self.Log(self.LOG_INFO, f"Loaded \"{self.getFilePath()}\"")
except FileNotFoundError:
self.Log(self.LOG_WARNING, f"It seems you don't have a configuration yet. Use configuration mode (-c) to enable your favourite entities and warehouses.\
\nConfigurations will be saved in \"{str(self.getFolderPath())}\"")
Expand All @@ -48,7 +48,7 @@ def writeConfigurations(self, data):
self.createFolderPathIfDoesNotExist()
with open(self.getFilePath(), "w", encoding="utf-8") as f:
f.write(json.dumps(data, indent=4, ensure_ascii=False))
self.Log(self.LOG_MESSAGE, f"Saved \"{str(self.getFilePath())}\"")
self.Log(self.LOG_INFO, f"Saved \"{str(self.getFilePath())}\"")
except Exception as e:
self.Log(self.LOG_ERROR, f"Error saving configuration file: {str(e)}")
sys.exit(str(e))
Expand Down Expand Up @@ -152,7 +152,7 @@ def manageOldConfig(self, moveFile: bool) -> None:
self.createFolderPathIfDoesNotExist()
# copy file from old to new location
self.oldFolderPath().joinpath(CONFIGURATION_FILE_NAME).rename(self.getFilePath())
self.Log(self.LOG_MESSAGE,
self.Log(self.LOG_INFO,
f"Copied to \"{str(self.getFilePath())}\"")
else:
# create dont move file
Expand All @@ -161,7 +161,7 @@ def manageOldConfig(self, moveFile: bool) -> None:
"This file is here to remember you that you don't want to move the configuration file into the new location.",
"If you want to move it, delete this file and run the script in -c mode."
]))
self.Log(self.LOG_MESSAGE, " ".join([
self.Log(self.LOG_INFO, " ".join([
"You won't be asked again. A new blank configuration will be used;",
f"if you want to move the existing configuration file, delete \"{self.oldFolderPath().joinpath(DONT_MOVE_FILE_FILENAME)}",
"and run the script in -c mode."
Expand Down
15 changes: 12 additions & 3 deletions IoTuring/Configurator/ConfiguratorLoader.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,16 @@ def LoadEntities(self) -> list[Entity]:
# - pass the configuration to the warehouse function that uses the configuration to init the Warehouse
# - append the Warehouse to the list

def LoadSettings(self) -> list[Settings]:
def LoadSettings(self, early_init:bool = False) -> list[Settings]:
""" Load all Settings classes

Args:
early_init (bool, optional): True when loaded before configurator menu, False when added to SettingsManager. Defaults to False.

Returns:
list[Settings]: Loaded classes
"""

settings = []
scm = ClassManager(KEY_SETTINGS)
settingsClasses = scm.ListAvailableClasses()
Expand All @@ -80,11 +89,11 @@ def LoadSettings(self) -> list[Settings]:
.GetConfigsOfType(sClass.NAME)

if savedConfigs:
sc = sClass(savedConfigs[0])
sc = sClass(savedConfigs[0], early_init)

# Fallback to default:
else:
sc = sClass(sClass.GetDefaultConfigurations())
sc = sClass(sClass.GetDefaultConfigurations(), early_init)

settings.append(sc)
return settings
Expand Down
58 changes: 33 additions & 25 deletions IoTuring/Logger/LogLevel.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from IoTuring.Logger import consts
from __future__ import annotations
import logging
from IoTuring.Logger.Colors import Colors
from IoTuring.Exceptions.Exceptions import UnknownLoglevelException

Expand All @@ -7,42 +8,49 @@ class LogLevel:
""" A loglevel with numeric and string values"""

def __init__(self, level_const: str) -> None:
level_dict = next(
(l for l in consts.LOG_LEVELS if l["const"] == level_const), None)

if not level_dict:
self.string = level_const.upper()
if self.string.startswith("LOG_"):
self.string = self.string[4:]

try:
self.number = getattr(logging, self.string)
except AttributeError:
raise UnknownLoglevelException(level_const)

self.const = level_const
self.string = level_dict["string"]
self.number = int(level_dict["number"])
if "color" in level_dict.keys():
self.color = getattr(Colors, level_dict["color"])
# WARNING is yellow:
if self.number == 30:
self.color = Colors.yellow
# ERROR and CRITICAL red:
elif self.number > 30:
self.color = Colors.red
else:
self.color = None
self.color = ""

def __str__(self) -> str:
return self.string

def __int__(self) -> int:
return self.number

def get_colored_string(self, string: str) -> str:
""" Get colored text according to LogLevel """
if self.color:
out_string = self.color + string + Colors.reset
else:
out_string = string
return out_string



class LogLevelObject:
""" Base class for loglevel properties """

LOG_MESSAGE = LogLevel("LOG_MESSAGE")
LOG_ERROR = LogLevel("LOG_ERROR")
LOG_WARNING = LogLevel("LOG_WARNING")
LOG_INFO = LogLevel("LOG_INFO")
LOG_DEBUG = LogLevel("LOG_DEBUG")
LOG_DEVELOPMENT = LogLevel("LOG_DEVELOPMENT")
LOG_DEBUG = LogLevel("DEBUG")
LOG_INFO = LogLevel("INFO")
LOG_WARNING = LogLevel("WARNING")
LOG_ERROR = LogLevel("ERROR")
LOG_CRITICAL = LogLevel("CRITICAL")

LOGTARGET_FILE = "file"
LOGTARGET_CONSOLE = "console"

@classmethod
def GetLoglevels(cls) -> list[LogLevel]:
"""Get all available log levels

Returns:
list[LogLevel]: List of LogLevel objects
"""
return [getattr(cls, l) for l in dir(cls) if isinstance(getattr(cls, l), LogLevel)]
8 changes: 5 additions & 3 deletions IoTuring/Logger/LogObject.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@

class LogObject(LogLevelObject):

def Log(self, loglevel: LogLevel, message):
Logger().Log(
def Log(self, loglevel: LogLevel, message, **kwargs):
logger = Logger()
logger.Log(
source=self.LogSource(),
message=message,
loglevel=loglevel
loglevel=loglevel,
**kwargs
)

# to override in classes where I want a source different from class name
Expand Down
Loading
Loading