"""
Utility classes and functions for RSMTool logging.

:author: Jeremy Biggs (jbiggs@ets.org)
:author: Anastassia Loukina (aloukina@ets.org)
:author: Nitin Madnani (nmadnani@ets.org)

:organization: ETS
"""

import logging


class LogFormatter(logging.Formatter):
    """
    Custom logging formatter.

    Note
    ----
    This class is adapted from https://stackoverflow.com/q/1343227.
    """

    info_fmt = "%(msg)s"
    warn_fmt = "WARNING: %(msg)s"

    err_fmt = "ERROR: %(msg)s"
    dbg_fmt = "DEBUG: %(module)s: %(lineno)d: %(msg)s"

    def __init__(self, fmt="%(levelno)s: %(msg)s"):  # noqa: D107
        logging.Formatter.__init__(self, fmt)

    def format(self, record):
        """
        Format the given record.

        Parameters
        ----------
        record : logging.LogRecord
            The record to format.
        """
        # Save the original format configured by the user
        # when the logger formatter was instantiated
        format_orig = self._fmt

        # Replace the original format with one customized by logging level
        if record.levelno == logging.DEBUG:
            self._fmt = LogFormatter.dbg_fmt
            self._style = logging.PercentStyle(self._fmt)

        elif record.levelno == logging.WARNING:
            self._fmt = LogFormatter.warn_fmt
            self._style = logging.PercentStyle(self._fmt)

        elif record.levelno == logging.INFO:
            self._fmt = LogFormatter.info_fmt
            self._style = logging.PercentStyle(self._fmt)

        elif record.levelno == logging.ERROR:
            self._fmt = LogFormatter.err_fmt
            self._style = logging.PercentStyle(self._fmt)

        # Call the original formatter class to do the grunt work
        result = logging.Formatter.format(self, record)

        # Restore the original format configured by the user
        self._fmt = format_orig

        return result

@@ -209,23 +209,56 @@
 %0Aimport 
-logging
+contextlib%0Aimport logging%0A%0Aimport joblib
 %0A%0A%0Aclass
@@ -1916,16 +1916,16 @@
 t_orig%0A%0A
-
         
@@ -1938,8 +1938,1815 @@
  result%0A
+%0A%0Adef get_file_logger(logger_name, log_file_path):%0A    %22%22%22%0A    Create and return a file-based logger.%0A%0A    Instantiate a logger with the given name and attach a%0A    file handler that uses the given log file. The logging%0A    level is set to INFO.%0A    %0A    Parameters%0A    ----------%0A    logger_name : str%0A        Name to use for the logger.%0A    log_file_path : str%0A        File path to which the logger should output messages.%0A    %0A    Returns%0A    -------%0A    TYPE%0A        Description%0A    %22%22%22%0A    logger = logging.getLogger(logger_name)%0A    logger.propagate = False%0A    formatter = logging.Formatter('%25(message)s')%0A    file_handler = logging.FileHandler(log_file_path, mode=%22w%22)%0A    file_handler.setFormatter(formatter)%0A    file_handler.setLevel(logging.INFO)%0A    logger.addHandler(file_handler)%0A    logger.setLevel(logging.INFO)%0A    return logger%0A%0A%0A@contextlib.contextmanager%0Adef tqdm_joblib(tqdm_object):%0A    %22%22%22%0A    Patch joblib to report into tqdm progress bar given as argument.%0A    %0A    This function creates a joblib-compatible context manager with%0A    a progress bar attached.%0A    %0A    Adapted from: https://stackoverflow.com/a/58936697%0A    %0A    Parameters%0A    ----------%0A    tqdm_object : tqdm progress bar%0A        The given tqdm progress bar into which joblib should report    %0A    %22%22%22%0A    class TqdmBatchCompletionCallback(joblib.parallel.BatchCompletionCallBack):%0A        def __call__(self, *args, **kwargs):%0A            tqdm_object.update(n=self.batch_size)%0A            return super().__call__(*args, **kwargs)%0A%0A    old_batch_callback = joblib.parallel.BatchCompletionCallBack%0A    joblib.parallel.BatchCompletionCallBack = TqdmBatchCompletionCallback%0A    try:%0A        yield tqdm_object%0A    finally:%0A        joblib.parallel.BatchCompletionCallBack = old_batch_callback%0A        tqdm_object.close()%0A

Add new logging utilities