import sys
import os
+import stat
import datetime
import re
import tempfile
+import shutil
import src
import printcolors
log_macro_command_file_expression = "^[0-9]{8}_+[0-9]{6}_+.*\.xml$"
log_all_command_file_expression = "^.*[0-9]{8}_+[0-9]{6}_+.*\.xml$"
+verbose = True # cvw TODO
+
class Logger(object):
"""\
Class to handle log mechanism.
# the external commands calls (cmake, make, git clone, etc...)
txtFileName = prefix + hour_command_host + ".txt"
txtFilePath = os.path.join(log_dir, "OUT", txtFileName)
-
- src.ensure_path_exists(os.path.dirname(logFilePath))
+
+ aDirLog = os.path.dirname(logFilePath)
+ if not os.path.exists(aDirLog):
+ print("create log dir %s" % aDirLog)
+ src.ensure_path_exists(aDirLog)
+ # sometimes other users make 'sat log' and create hat.xml file...
+ os.chmod(aDirLog,
+ stat.S_IRUSR |
+ stat.S_IRGRP |
+ stat.S_IROTH |
+ stat.S_IWUSR |
+ stat.S_IWGRP |
+ stat.S_IWOTH |
+ stat.S_IXUSR |
+ stat.S_IXGRP |
+ stat.S_IXOTH)
src.ensure_path_exists(os.path.dirname(txtFilePath))
# The path of the log files (one for sat traces, and the other for
self.config.VARS.command})
# version of salomeTools
self.xmlFile.append_node_attrib("Site", attrib={"satversion" :
- self.config.INTERNAL.sat_version})
+ src.get_salometool_version(self.config)})
# machine name on which the command has been launched
self.xmlFile.append_node_attrib("Site", attrib={"hostname" :
self.config.VARS.hostname})
self.config.VARS.user})
# The time when command was launched
Y, m, dd, H, M, S = date_to_datetime(self.config.VARS.datehour)
- date_hour = "%2s/%2s/%4s %2sh%2sm%2ss" % (dd, m, Y, H, M, S)
+ date_hour = "%4s/%2s/%2s %2sh%2sm%2ss" % (Y, m, dd, H, M, S)
self.xmlFile.append_node_attrib("Site", attrib={"beginTime" :
date_hour})
# The application if any
("sat command ...")
"""
xmlLinks = self.xmlFile.xmlroot.find("Links")
- src.xmlManager.add_simple_node(xmlLinks,
- "link",
- text = log_file_name,
- attrib = {"command" : command_name,
- "passed" : command_res,
- "launchedCommand" : full_launched_command})
+ flc = src.xmlManager.escapeSequence(full_launched_command)
+ att = {"command" : command_name, "passed" : str(command_res), "launchedCommand" : flc}
+ src.xmlManager.add_simple_node(xmlLinks, "link", text = log_file_name, attrib = att)
def write(self, message, level=None, screenOnly=False):
"""\
sys.stdout.write(message)
self.flush()
- def error(self, message):
- """Print an error.
-
- :param message str: The message to print.
- """
- # Print in the log file
- self.xmlFile.append_node_text("traces", _('ERROR:') + message)
+ def error(self, message, prefix="ERROR: "):
+ """Print an error.
+
+ :param message str: The message to print.
+ """
+ # Print in the log file
+ self.xmlFile.append_node_text("traces", prefix + message)
+
+ # Print in the terminal and clean colors if the terminal
+ # is redirected by user
+ if not ('isatty' in dir(sys.stderr) and sys.stderr.isatty()):
+ sys.stderr.write(printcolors.printcError(prefix + message + "\n"))
+ else:
+ sys.stderr.write(prefix + message + "\n")
+
+ def step(self, message):
+ """Print an step message.
+
+ :param message str: The message to print.
+ """
+ self.write('STEP: ' + message, level=4)
+
+ def trace(self, message):
+ """Print an trace message.
+
+ :param message str: The message to print.
+ """
+ self.write('TRACE: ' + message, level=5)
+
+ def debug(self, message):
+ """Print an debug message.
+
+ :param message str: The message to print.
+ """
+ self.write('DEBUG: ' + message, level=6)
+
+ def warning(self, message):
+ """Print an warning message.
+
+ :param message str: The message to print.
+ """
+ self.error(message, prefix="WARNING: ")
+
+ def critical(self, message):
+ """Print an critical message.
+
+ :param message str: The message to print.
+ """
+ self.error(message, prefix="CRITICAL: ")
+
- # Print in the terminal and clean colors if the terminal
- # is redirected by user
- if not ('isatty' in dir(sys.stderr) and sys.stderr.isatty()):
- sys.stderr.write(printcolors.printcError(_('ERROR:') + message))
- else:
- sys.stderr.write(_('ERROR:') + message)
def flush(self):
"""Flush terminal"""
# Call the method to write the xml file on the hard drive
self.xmlFile.write_tree(stylesheet = "command.xsl")
+
+ # so unconditionnaly copy stylesheet file(s)
+ xslDir = os.path.join(self.config.VARS.srcDir, 'xsl')
+ xslCommand = "command.xsl"
+ # xslHat = "hat.xsl" # have to be completed (one time at end)
+ xsltest = "test.xsl"
+ imgLogo = "LOGO-SAT.png"
+ files_to_copy = [xslCommand, xsltest, imgLogo]
+
+ logDir = src.get_log_path(self.config)
+ # copy the stylesheets in the log directory as soon as possible here
+ # because referenced in self.xmlFile.write_tree above
+ # OP We use copy instead of copy2 to update the creation date
+ # So we can clean the LOGS directories easily
+ for f in files_to_copy:
+ f_init = os.path.join(xslDir, f)
+ f_target = os.path.join(logDir, f)
+ if not os.path.isfile(f_target): # do not overrride
+ shutil.copy(f_init, logDir)
# Dump the config in a pyconf file in the log directory
- logDir = src.get_log_path(self.config)
- dumpedPyconfFileName = (self.config.VARS.datehour
+ dumpedPyconfFileName = (self.config.VARS.datehour
+ "_"
+ self.config.VARS.command
+ ".pyconf")
sys.stdout.write(printcolors.printcWarning("%s\n%s\n" % (msg, e)))
return False, None, None
- if 'application' in logFileXml.xmlroot.keys():
- appliLog = logFileXml.xmlroot.get('application')
- launched_cmd = logFileXml.xmlroot.find('Site').attrib['launchedCommand']
- # if it corresponds, then the log has to be shown
- if appliLog == application:
- return True, appliLog, launched_cmd
- elif application != 'None':
- return False, appliLog, launched_cmd
-
- return True, appliLog, launched_cmd
-
+ try:
+ if 'application' in logFileXml.xmlroot.keys():
+ appliLog = logFileXml.xmlroot.get('application')
+ launched_cmd = logFileXml.xmlroot.find('Site').attrib['launchedCommand']
+ # if it corresponds, then the log has to be shown
+ if appliLog == application:
+ return True, appliLog, launched_cmd
+ elif application != 'None':
+ return False, appliLog, launched_cmd
+
+ return True, appliLog, launched_cmd
+ except Exception as e:
+ msg = _("WARNING: the log file %s cannot be parsed:" % logFilePath)
+ sys.stdout.write(printcolors.printcWarning("%s\n%s\n" % (msg, e)))
+ return False, None, None
+
if application == 'None':
return True, None, None
"""
# Create an instance of XmlLogFile class to create hat.xml file
xmlHatFilePath = os.path.join(logDir, 'hat.xml')
- xmlHat = src.xmlManager.XmlLogFile(xmlHatFilePath,
- "LOGlist", {"application" : application})
+ xmlHat = src.xmlManager.XmlLogFile(xmlHatFilePath, "LOGlist", {"application" : application})
# parse the log directory to find all the command logs,
# then add it to the xml file
lLogFile = list_log_file(logDir, log_macro_command_file_expression)
# Write the file on the hard drive
xmlHat.write_tree('hat.xsl')
+ # Sometimes other users will make 'sat log' and update this file
+ os.chmod(xmlHatFilePath,
+ stat.S_IRUSR |
+ stat.S_IRGRP |
+ stat.S_IROTH |
+ stat.S_IWUSR |
+ stat.S_IWGRP |
+ stat.S_IWOTH )
+
# TODO for future
_currentLogger = []
def getCurrentLogger():
- """temporary send all in stdout as simple logging logger"""
- import src.loggingSimple as LOGSI
+ """get current logging logger, set as DefaultLogger if not set yet"""
if len(_currentLogger) == 0:
+ import src.loggingSimple as LOGSI
logger = LOGSI.getDefaultLogger()
_currentLogger.append(logger)
- logger.warning("set current logger as default %s" % logger.name)
+ logger.warning("set by default current logger as %s" % logger.name)
return _currentLogger[0]
def getDefaultLogger():
- """temporary send all in stdout as simple logging logger"""
+ """get simple logging logger DefaultLogger, set it as current"""
import src.loggingSimple as LOGSI
- if len(_currentLogger) == 0:
- logger = LOGSI.getDefaultLogger()
- _currentLogger.append(logger)
- logger.warning("set current logger as default %s" % logger.name)
- return _currentLogger[0]
+ logger = LOGSI.getDefaultLogger()
+ setCurrentLogger(logger) # set it as current
+ return logger
+
+def getUnittestLogger():
+ """get simple logging logger UnittestLogger, set it as current"""
+ import src.loggingSimple as LOGSI
+ logger = LOGSI.getUnittestLogger()
+ setCurrentLogger(logger) # set it as current
+ return logger
def setCurrentLogger(logger):
"""temporary send all in stdout as simple logging logger"""
- import src.loggingSimple as LOGSI
if len(_currentLogger) == 0:
_currentLogger.append(logger)
+ logger.debug("set current logger as %s" % logger.name)
else:
- logger.warning("quit current logger as default %s" % _currentLogger[0].name)
- _currentLogger[0] = logger
- logger.warning("change current logger as default %s" % logger.name)
+ if _currentLogger[0].name != logger.name:
+ # logger.debug("quit current logger as default %s" % _currentLogger[0].name)
+ _currentLogger[0] = logger
+ logger.warning("change current logger as %s" % logger.name)
return _currentLogger[0]
def isCurrentLoggerUnittest():
res = True
else:
res = False
- DBG.write("isCurrentLoggerUnittest %s" % logger.name, res)
+ #DBG.write("isCurrentLoggerUnittest %s" % logger.name, res)
return res
def sendMessageToCurrentLogger(message, level):
+ """
+ assume relay from obsolescent
+ logger.write(msg, 1/2/3...) to future
+ logging.critical/warning/info...(msg) (as logging package tips)
+ """
logger = getCurrentLogger()
if level is None:
lev = 2