Source code for src.Libs.LogClass

#!/usr/bin/env python3
"""
This file is part of the PAFFrontendSim.

The PAFFrontendSim is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License v3 as published by the Free Software Foundation.

The PAFFrontendSim 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 the PAFFrontendSim. If not, see https://www.gnu.org/licenses/.
"""
#############################################################################
# import libs
#############################################################################
import subprocess
import datetime
from   copy                           import copy, deepcopy
from pathlib import Path
#############################################################################
# constants
#############################################################################
# Log-Class constants
_endMarker      = " => "            # label end-marker
_labelInter     = "."               # marker in between lables
_LabelLength    = 15                # length of the initial label
_AddLabelLength = 10                # length of each nested label attached

_Scenarios      = {                 # implemented output scenarios
                   # name           USER    FLOW   DATA   DEBUG  WARN   ERROR
                    'verbose'     : [True,  True,  True,  True,  True,  True ], # all output-messages
                    'quiet'       : [False, False, False, False, False, True ], # only errors
                    'data'        : [True,  True,  True,  False, True,  True ], # no debug-messages
                    'run'         : [True,  True,  False, False, True,  True ]  # no debug-messages and no data statements but full program-flow (default scenario)
                  }

############################################################################
# classes
############################################################################
[docs] class LogClass : """ Module to replace Pythons built-in print function with a more complex alternative. Since the simulator consists of multiple modules, it is important to discern the origin of printed messages. For this reason, messages printed by LogClass are preceeded by a header. This header contains the name of the module producing the message as well as the object hierarchy. Optionally all messages can be stored in .log-files. There is a .log-file for each module as well as a global file with all messages. Additionally each message has a type of importance. The importance affects the color of the text (for example red for errors). It is also relevant for the verbosity. A low verbosity setting will only cause the most important messages to be printed. """ def __init__ ( self, label = "", logPath = None ): self.label = "" # name of the calling task as ID self.logList = [] # log of all outputs which have a line-feed at the end self.USER_TYPE = "user" # User defined messages in the individual Apps (usually not used in Libs) self.FLOW_TYPE = "flow" # statements documenting the work-flow of the program and the lib-method calls self.DATA_TYPE = "data" # statements providing information on input or output data of methods or apps self.DEBUG_TYPE = "debug" # all kinds of debugging messages self.WARNING_TYPE = "warning" # all kinds of warning messages self.ERROR_TYPE = "error" # error messages self.message_type_dict = { self.USER_TYPE : [True, '\033[0m' ], # default color self.FLOW_TYPE : [True, '\033[92m'], # green self.DATA_TYPE : [True, '\033[94m'], # blue self.DEBUG_TYPE : [True, '\033[96m'], # cyan self.WARNING_TYPE : [True, '\033[93m'], # yellow self.ERROR_TYPE : [True, '\033[91m'] # red } self.setScenario() self.logPath = logPath # flag if output should go into log self.addLabel(label)
[docs] def writelog(self, message, message_type): """ Write the message to the log files. Parameters: message (string): The content of the message message_type (string): What kind of message it is, info, warning, error, etc. """ timeInUTC = datetime.datetime.now(datetime.timezone.utc) # Get the current time in UTC with open(Path(self.logPath, self.label.replace(" ", "")+".log"), 'a') as f: # Write to dedicated log file f.write( message + " (" + message_type + ")\n" ) # Include message and message_type (for color) f.close() with open(Path(self.logPath, "global.log"), 'a') as f : # Write to global log file f.write( str(timeInUTC) + " " + self.label + _endMarker + message + " (" + message_type + ")\n" ) # Include time and label f.close()
[docs] def printOut ( self, Message, message_type = "user", noSpace = True, lineFeed = True ) : """ Class console output function. Parameters : Message (string): Message-text message_type (string): What type of message "Message" is. User, Error, etc. noSpace (boolean): print Class-name, otherwise only spces of the same length lineFeed (boolean): print line-feed at the end of the line """ # determine end character if lineFeed == True : endChar = "\n" else: endChar = "\r" # determine labeling and restrict it in length if noSpace and ( len( self.label ) > 0 ) : header = self.label + _endMarker else : header = self.label + _endMarker + " " # check for verbose and output label and message if self.message_type_dict[message_type][0] == True : print('\033[90m' + header + self.message_type_dict[message_type][1] + Message+'\033[0m', end = endChar) # Print colored message if (self.logPath != None) and (lineFeed == True): self.writelog( Message, message_type)
[docs] def addLabel ( self, cls = "" ) : """ Add additional label to the label list. Parameters: cls (object): Object of a class whose label should be added to the label """ if isinstance( cls, str ): addLabel = cls else: addLabel = type(cls).__name__ if len( addLabel ) == 0 : return if len( self.label ) == 0 : #self.label = addLabel self.label = ( addLabel + " " * _LabelLength )[0:_LabelLength] else : #self.label += _labelInter + addLabel self.label += _labelInter + ( addLabel + " " * _AddLabelLength )[0:_AddLabelLength]
[docs] def setScenario ( self, Type = "" ) : """ Set predefined output scenarios. Parameters: Type (string): id-string of the output scenario (so far defined, see constant-definitions above) """ outputList = _Scenarios.get( Type, _Scenarios['run'] ) for idx, messageType in enumerate(self.message_type_dict) : self.message_type_dict[ messageType ][0] = outputList[idx]