#!python3
# Copyright 2007-2017 Gemr. All Rights Reserved.
# Licensed to MIT see LICENSE.txt
import os
import re
import json
__author__ = 'Suryavarman (http://sourceforge.net/u/suryavarman/profile/)'
[docs]class MacroReporting:
""" reporting m_Errors = errors dictionary, m_Warnings = warnings dictionary
Example :
1) Print each codblocks.workspace errors from the target all.
Don't use directly a key name like that. In this case it's to
illustrate the key name meaning:
for error in aMacroReporting.m_Errors["all - codblocks.workspace"]:
print( error )
2) Test if there a error:
assert not aMacroReporting.m_Errors, "There some errors."
@link http://www.pyregex.com/
@link https://regex101.com/#python
"""
def __init__(self):
self.m_Errors = {}
self.m_Warnings = {}
[docs] def appendIssues(self, inIssues, inReportingId, outDictionary):
if not inReportingId in outDictionary:
outDictionary[inReportingId] = []
for aIssue in inIssues:
outDictionary[inReportingId].append(aIssue)
[docs] def append(self, inReporting, inReportingId, inLogFilePath="output.log", inOnlyError=False):
""" send a GDeps.Reporting object, an Id to represent the log file, the
log file name and if you want only the errors.
"""
aReporting = inReporting.get(inLogFilePath, inOnlyError)
self.appendIssues(aReporting[0], inReportingId, self.m_Errors)
self.appendIssues(aReporting[1], inReportingId, self.m_Warnings)
[docs] def append2(self, inMacroReporting):
""" add the report from a GDeps.MacroReporting"""
for aId, aErrors in inMacroReporting.m_Errors.items():
self.appendIssues(aErrors, aId, self.m_Errors)
for aId, aWarnings in inMacroReporting.m_Warnings.items():
self.appendIssues(aWarnings, aId, self.m_Warnings)
[docs] def getlen(self, inReports):
aResult = 0
for aIssues in inReports.values():
aResult += len(aIssues)
return aResult
[docs] def getCountReports(self, inReports):
""" Warning : You can have an empty reports """
return len(inReports)
[docs] def printIssues(self):
print("----------------------------------------------------------------------")
print("Total count issues :")
print(" - errors : " + str(self.getlen(self.m_Errors)))
print(" - warnings : " + str(self.getlen(self.m_Warnings)))
print("======================================================================")
print("Count errors reports : " + str(self.getCountReports(self.m_Errors)))
for aErrorId, aErrorDescs in self.m_Errors.items():
print("----------------------------------------------------------------------")
print("Error Report : " + aErrorId)
for aErrorDesc in aErrorDescs:
print(aErrorDesc)
print("======================================================================")
print("Count warnings reports : " + str(self.getCountReports(self.m_Warnings)))
for aWarningId, aWarningDescs in self.m_Warnings.items():
print("----------------------------------------------------------------------")
print("Warning Report : " + aWarningId)
for aWarningDesc in aWarningDescs:
print(aWarningDesc)
print("======================================================================")
print("======================================================================")
[docs] def exportJson(self, inFileName='report.json', inPath=r'.\\'):
""" Export the reporting to a json file
:param inFileName: This is the filename and the wildcard has to be include.
:type inFileName: str
:param inPath: By default the local path
:type inPath: str
.. note::
aFullFileName = inPath + '\\' + inFileName
:raise if the output file cannot be create
"""
aReport = {"errors": self.m_Errors, "warnings": self.m_Warnings}
aFullFileName = inPath + r'\\' + inFileName
with open(aFullFileName, 'w') as aFile:
json.dump(aReport, aFile)
assert os.path.exists(aFullFileName), 'The file ' + aFullFileName + ' cannot be save.'
[docs]class Reporting:
""" Define your expression regular to find the error, warnings in your
objects log.
"""
def __init__(self, inErrorRegEx=r"error", inWarningRegEx=r"warning", inSplitRegexp=r"\n+", inErrorRegexpMultiline="", inWarningRegexpMultiline=""):
self.m_SplitRegexp = inSplitRegexp
""" slpit the log in group. Each group matching group will be send in
the report
"""
self.m_ErrorRegexp = inErrorRegEx
""" if a splitting group match with this expression, this group will be
send like a error
"""
self.m_WarningRegexp = inWarningRegEx
""" if a splitting group match with this expression, this group will be
send like a warning.
"""
self.m_ErrorRegexpMultiline = inErrorRegexpMultiline
""" if a group match with this expression, this group will be
send like a error.
@remarks Multi-line mean the search/match will be execute on the
entire text.
"""
self.m_WarningRegexpMultiline = inWarningRegexpMultiline
""" if a group match with this expression, this group will be
send like a warning.
@remarks Multi-line mean the search/match will be execute on the
entire text.
"""
[docs] def get(self, inLogFilePath="output.log", inOnlyError=False):
""" Get the errors and the warning from inLogFilePath.
return an array of arrays [0][ errors ] [1][ warnings ]
"""
aReporting = []
aLogFileExist = os.path.exists(inLogFilePath)
assert aLogFileExist, "The log file doesn't exist : " + inLogFilePath
aErrors = []
aWarnings = []
if aLogFileExist:
""" @link https://docs.python.org/3/library/re.html
@link http://apprendre-python.com/page-expressions-regulieres-regular-python
@link https://stackoverflow.com/questions/5820779/python-regular-expression-to-get-filename-in-a-long-path
"""
with open(inLogFilePath, "r") as aLog:
aLogstr = aLog.read()
if self.m_ErrorRegexpMultiline:
aErrorSearch = re.search(self.m_ErrorRegexpMultiline, aLogstr)
if aErrorSearch and (aErrorSearch.span()[0] != aErrorSearch.span()[1]):
aEntrie = aLogstr[aErrorSearch.span()[0]: aErrorSearch.span()[1]]
aErrors.append(aEntrie)
if self.m_WarningRegexpMultiline:
aWarningSearch = re.search(self.m_WarningRegexpMultiline, aLogstr)
if aWarningSearch and (aWarningSearch.span()[0] != aWarningSearch.span()[1]):
aEntrie = aLogstr[aWarningSearch.span()[0]: aWarningSearch.span()[1]]
aWarnings.append(aEntrie)
aEntries = re.split(self.m_SplitRegexp, aLogstr)
for aEntrie in aEntries:
if self.m_ErrorRegexp and re.match(self.m_ErrorRegexp, aEntrie):
aErrors.append(aEntrie)
if not inOnlyError and self.m_WarningRegexp and re.match(self.m_WarningRegexp, aEntrie):
aWarnings.append(aEntrie)
aReporting.append(aErrors)
aReporting.append(aWarnings)
return aReporting
[docs] def printIssues(self, inReportingResult):
aErrors = inReportingResult[0]
aWarnings = inReportingResult[1]
print("----------------------------------------------------------------------")
print("Count errors : " + str(len(aErrors)))
for aError in aErrors:
print(aError)
print("----------------------------------------------------------------------")
print("Count warnings : " + str(len(aWarnings)))
for aWarning in aWarnings:
print(aWarning)
print("======================================================================")
print("======================================================================")
[docs]def getLogFileContent(inLogFilePath):
"""
Use this function to save the previous log.
>>> GDeps.call('call "app1.exe" > "test.log" 2>&1')
>>> aContent = GDeps.getLogFileContent('test.log')
>>> GDeps.call('call "app2.exe" > "test.log" 2>&1')
>>> GDeps.pushFrontLogFileContent('test.log', aContent)
"""
aResult = ''
with open(inLogFilePath) as aFile:
aResult = aFile.read()
return aResult
[docs]def pushFrontLogFileContent(inLogFilePath, inContent):
"""
Use this function to save the previous log.
>>> GDeps.call('call "app1.exe" > "test.log" 2>&1')
>>> aContent = GDeps.getLogFileContent('test.log')
>>> GDeps.call('call "app2.exe" > "test.log" 2>&1')
>>> GDeps.pushFrontLogFileContent('test.log', aContent)
"""
with open(inLogFilePath, 'r+') as aFile:
aNewContent = aFile.read()
aFile.seek(0, 0)
aFile.write(inContent)
aFile.write(aNewContent)
[docs]def clearLogFile(inLogFilePath):
"""
Use this function before to the first time to write into the log file.
:param inLogFilePath: The log file path.
:type inLogFilePath: str
"""
open(inLogFilePath, 'w').close()