"""Singleton managing the various levels of messages
:author: Michel Bierlaire
:date: Mon Jul 22 16:12:00 2019
"""
# Too constraining
# pylint: disable=invalid-name,
import datetime
import biogeme.filenames as bf
import biogeme.version as bv
from biogeme.singleton import Singleton
[docs]class bioMessage(metaclass=Singleton):
"""Manages the Biogeme messages"""
[docs] def __init__(self, screenLevel=1):
"""Constructor
:param screenLevel: level of message that must be displayed on the
screen:
- 0: no output (default)
- 1: warnings only
- 2: only warnings and general information
- 3: more verbose
- 4: debug messages
:type screenLevel: int
"""
self.screenLevel = screenLevel #: screen verbosity level
self.types = {
0: 'Silent',
1: 'Warning',
2: 'General',
3: 'Detailed',
4: 'Debug',
} #: names of verbosity levels
self.resetMessages()
self.lastLevel = None #: last level used
[docs] def resetMessages(self):
"""Erase all messages"""
self.messages = []
[docs] def allMessages(self, screenLevel=None):
"""Report all the messages up to a given level.
:param screenLevel: level of message that must be reported in the file:
- 0: no output
- 1: warnings only
- 2: only warnings and general information
- 3: more verbose (default)
- 4: debug messages
If None (default), all messages are reported.
:type screenLevel: int
:return: all messages.
:rtype: str.
"""
result = (
f'*** Messages from biogeme {bv.getVersion()} [{bv.versionDate}]\n'
)
for m, i in self.messages:
if screenLevel is None or i <= screenLevel:
result += f'{m}\n'
return result
[docs] def createLog(self, fileLevel=None, fileName='_biogeme'):
"""Creates a log file
:param fileLevel: level of message that must be reported in the file:
- 0: no output
- 1: warnings only
- 2: only warnings and general information
- 3: more verbose (default)
- 4: debug messages
If None (default), all messages are reported.
:type fileLevel: int
:param fileName: name of the file (without extension).
Default: '_biogeme'. A file called _biogeme.log
will be created.
:type fileName: string
:return: name of the file
:rtype: str
"""
completeFileName = bf.getNewFileName(fileName, 'log')
with open(completeFileName, 'w') as f:
self.general(f'Log file created: {completeFileName}')
print(f'*** File created {datetime.datetime.now()} ***', file=f)
print(
f'*** Log file from biogeme {bv.getVersion()}'
f' [{bv.versionDate}]',
file=f,
)
for m, i in self.messages:
if fileLevel is None or i <= fileLevel:
print(m, file=f)
return completeFileName
[docs] def temporarySilence(self):
"""Temporarily turns off the message, remembering the current
screen level.
"""
self.lastLevel = self.screenLevel
self.screenLevel = 0
[docs] def resume(self):
"""Resume the regular operations of the logger after the use of
temporarySilence
"""
if self.lastLevel is not None:
self.screenLevel = self.lastLevel
[docs] def setSilent(self):
"""Set both screen and file levels to 0"""
self.screenLevel = 0
[docs] def setWarning(self):
"""Set both screen and file levels to 1"""
self.screenLevel = 1
[docs] def setGeneral(self):
"""Set both screen and file levels to 2"""
self.screenLevel = 2
[docs] def setDetailed(self):
"""Set both screen and file levels to 3"""
self.screenLevel = 3
[docs] def setDebug(self):
"""Set both screen and file levels to 4"""
self.screenLevel = 4
[docs] def setScreenLevel(self, level):
"""Change the level of messaging for the screen
:param level: level of message that must be displayed on the screen:
- 0: no output
- 1: warnings only
- 2: only warnings and general information
- 3: more verbose
- 4: debug messages
:type level: int
"""
self.screenLevel = level
[docs] def addMessage(self, text, level):
"""Add a message
:param text: text of the message.
:type text: string
:param level: level of the message
- 1: warning
- 2: general information
- 3: detailed information
- 4: debug message
:type level: int
:note: adding a message of level 0 is meaningless, as it correspond to
silentmode.
"""
theLevel = f'< {self.types[level]} >'
theMessage = (
f'[{datetime.datetime.now().strftime("%H:%M:%S")}] '
f'{theLevel:13} {text}'
)
if level != 0:
self.messages.append((theMessage, level))
if level <= self.screenLevel:
print(theMessage)
[docs] def warning(self, text):
"""Add a warning
:param text: text of the message.
:type text: string
"""
self.addMessage(text, 1)
[docs] def general(self, text):
"""Add a general message
:param text: text of the message.
:type text: string
"""
self.addMessage(text, 2)
[docs] def detailed(self, text):
"""Add a detailed message
:param text: text of the message.
:type text: string
"""
self.addMessage(text, 3)
[docs] def debug(self, text):
"""Add a debug message
:param text: text of the message.
:type text: string
"""
self.addMessage(text, 4)