Skip to content

Commit

Permalink
Feature/logtab (#19)
Browse files Browse the repository at this point in the history
* doc: removed bitbucket pipeline [ci-skip]

* chore: moved pipeline and created reduced conda env spec

* feat: added tab to log messages

---------

Co-authored-by: Julien Lerat <[email protected]>
  • Loading branch information
jlerat and Julien Lerat authored Feb 16, 2024
1 parent e509101 commit 90a6d7e
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 31 deletions.
84 changes: 61 additions & 23 deletions hydrodiy/io/iutils.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,24 +118,48 @@ def script_template(filename, comment,
class StartedCompletedLogger():
""" Add context to logging messages via the context attribute """

def __init__(self, logger):
def __init__(self, logger, \
separator_charac="-", \
separator_length=50, \
dictseparator_charac="+", \
dictseparator_length=30, \
tab_length=4):
errmess = "Expected a logger object"
assert isinstance(logger, logging.Logger), errmess
self._logger = logger

self.separator_charac = separator_charac
self.separator_length = separator_length

self.dictseparator_charac = dictseparator_charac
self.dictseparator_length = dictseparator_length

self.tab_length = tab_length

def get_separator(self, nsep, sep):
return sep*nsep

def error(self, msg, *args, **kwargs):
def add_tab(self, msg, ntab):
if ntab==0:
return msg

tab_space = " "*self.tab_length*ntab
return tab_space+msg

def error(self, msg, ntab=0, *args, **kwargs):
msg = self.add_tab(msg, ntab)
return self._logger.error(msg, *args, **kwargs)

def info(self, msg, *args, **kwargs):
def info(self, msg, ntab=0, *args, **kwargs):
msg = self.add_tab(msg, ntab)
return self._logger.info(msg, *args, **kwargs)

def warning(self, msg, *args, **kwargs):
def warning(self, msg, ntab=0, *args, **kwargs):
msg = self.add_tab(msg, ntab)
return self._logger.warning(msg, *args, **kwargs)

def critical(self, msg, *args, **kwargs):
def critical(self, msg, ntab=0, *args, **kwargs):
msg = self.add_tab(msg, ntab)
return self._logger.critical(msg, *args, **kwargs)

@property
Expand All @@ -144,24 +168,28 @@ def handlers(self):

def started(self):
self.info("@@@ Process started @@@")
self.info(self.get_separator("-", 30))
self.info(self.get_separator(self.separator_charac, \
self.separator_length))
self.info("")

def completed(self):
self.info("")
self.info(self.get_separator("-", 30))
self.info(self.get_separator(self.separator_charac, \
self.separator_length))
self.info("@@@ Process completed @@@")

def log_dict(self, tolog, name="", level="info"):
""" Add log entry for dictionnary (e.g. created from argparse using vars)"""
assert level in ["info", "warning", "critical", "error"]
logfun = getattr(self, level)
sep = self.get_separator("+", 20)
sep = self.get_separator(self.dictseparator_charac, \
self.dictseparator_length)
logfun(sep)
if name!="":
logfun(f"{name}:")
for k, v in tolog.items():
logfun(" "*4+f"{k} = {v}")
msg = self.add_tab(f"{k} = {v}", 1)
logfun(msg)

logfun(sep)
logfun("")
Expand All @@ -171,9 +199,17 @@ def log_dict(self, tolog, name="", level="info"):
class ContextualLogger(StartedCompletedLogger):
""" Add context to logging messages via the context attribute """

def __init__(self, logger):
def __init__(self, logger, \
context_hasheader=False, \
context_charac="#", \
context_length=3, \
*args, **kwargs):
self._context = ""
super(ContextualLogger, self).__init__(logger)
self.context_hasheader = context_hasheader
self.context_charac = context_charac
self.context_length = context_length

super(ContextualLogger, self).__init__(logger, *args, **kwargs)

@property
def context(self):
Expand All @@ -184,34 +220,36 @@ def context(self, value):
self._context = ""
self.info("")
self._context = str(value)
if self._context != "":
sep = self.get_separator("#", 3)
if self._context != "" and self.context_hasheader:
sep = self.get_separator(self.context_charac, \
self.context_length)
mess = sep+" "+self._context+" "+sep
self.info(mess)

def completed(self):
self.context = ""
super(ContextualLogger, self).completed()

def get_message(self, msg):
def get_message(self, msg, ntab):
if self.context != "":
return "{{ {0} }} {1}".format(self.context, msg)
tab = " "*self.tab_length*ntab if ntab>0 else ""
return "{{ {0} }} {1}{2}".format(self.context, tab, msg)
return msg

def error(self, msg, *args, **kwargs):
msg = self.get_message(msg)
def error(self, msg, ntab=0, *args, **kwargs):
msg = self.get_message(msg, ntab)
return self._logger.error(msg, *args, **kwargs)

def info(self, msg, *args, **kwargs):
msg = self.get_message(msg)
def info(self, msg, ntab=0, *args, **kwargs):
msg = self.get_message(msg, ntab)
return self._logger.info(msg, *args, **kwargs)

def warning(self, msg, *args, **kwargs):
msg = self.get_message(msg)
def warning(self, msg, ntab=0, *args, **kwargs):
msg = self.get_message(msg, ntab)
return self._logger.warning(msg, *args, **kwargs)

def critical(self, msg, *args, **kwargs):
msg = self.get_message(msg)
def critical(self, msg, ntab=0, *args, **kwargs):
msg = self.get_message(msg, ntab)
return self._logger.critical(msg, *args, **kwargs)


Expand Down
29 changes: 21 additions & 8 deletions hydrodiy/io/tests/test_hyio_iutils.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,8 @@ def test_get_logger():
mess = ["flog1 A", "flog1 B"]
logger1.info(mess[0])
logger1.info(mess[1])
logger1.info("test tab1", 1)
logger1.info("test tab2", 2)
logger1.error("error")
logger1.critical("critical")
logger1.warning("warning")
Expand All @@ -134,11 +136,14 @@ def test_get_logger():
ck = txt[0].strip().endswith("INFO | @@@ Process started @@@")
ck = ck & txt[3].strip().endswith("INFO | "+mess[0])
ck = ck & txt[4].strip().endswith("INFO | "+mess[1])
ck = ck & txt[5].strip().endswith("ERROR | error")
ck = ck & txt[6].strip().endswith("CRITICAL | critical")
ck = ck & txt[7].strip().endswith("WARNING | warning")
ck = ck & txt[9].strip().endswith("WARNING | test:")
ck = ck & txt[10].strip().endswith("WARNING | a = 1")
ck = ck & txt[5].strip().endswith("INFO | test tab1")
ck = ck & txt[6].strip().endswith("INFO | test tab2")
ck = ck & txt[7].strip().endswith("ERROR | error")
ck = ck & txt[8].strip().endswith("CRITICAL | critical")
ck = ck & txt[9].strip().endswith("WARNING | warning")
ck = ck & txt[11].strip().endswith("WARNING | test:")
ck = ck & txt[12].strip().endswith("WARNING | a = 1")

assert ck

# Test logging with different format
Expand All @@ -155,8 +160,13 @@ def test_get_logger():

with open(flog2, "r") as fl:
txt = fl.readlines()
expected = ["@@@ Process started @@@", "-"*30, ""]+mess+\
["", "-"*30, "@@@ Process completed @@@"]
expected = ["@@@ Process started @@@", \
logger2.separator_charac*logger2.separator_length, \
""]+\
mess+\
["", \
logger2.separator_charac*logger2.separator_length, \
"@@@ Process completed @@@"]
assert expected == [t.strip() for t in txt]

# Close log file handler and delete files
Expand All @@ -174,6 +184,7 @@ def test_get_logger_contextual():
# Test logging
logger = iutils.get_logger("bidule", flog=flog,\
contextual=True)
logger.context_hasheader = True

mess = ["flog1 A", "flog1 B"]
logger.context = "context1"
Expand All @@ -184,6 +195,7 @@ def test_get_logger_contextual():
logger.error("error")
logger.critical("critical")
logger.warning("warning")
logger.info("test tab3", 3)

logger.completed()

Expand All @@ -198,7 +210,8 @@ def test_get_logger_contextual():
ck &= bool(re.search("ERROR . \\{ context2 \\}", txt[9]))
ck &= bool(re.search("CRITICAL . \\{ context2 \\}", txt[10]))
ck &= bool(re.search("WARNING . \\{ context2 \\}", txt[11]))
ck &= bool(re.search("@@@ Process completed @@@", txt[15]))
ck &= bool(re.search("INFO . \\{ context2 \\} test tab3", txt[12]))
ck &= bool(re.search("@@@ Process completed @@@", txt[16]))
assert ck

logger.handlers[1].close()
Expand Down

0 comments on commit 90a6d7e

Please sign in to comment.