Module geodata_harvester.write_logs

Expand source code
import datetime
import logging
import os


def logging_addLevel(levelName, levelNum, methodName=None):
    """Add new logging level to `logger`

    Credit to https://stackoverflow.com/a/35804945

    Args:
        levelName (_type_): Name of the logging level.
        levelNum (_type_): Numeric value of the logging level.
        methodName (_type_, optional): Name of the method to call. Defaults to None.

    Example:
    >>> addLoggingLevel('TRACE', logging.DEBUG - 5)
    >>> logging.getLogger(__name__).setLevel("TRACE")
    >>> logging.getLogger(__name__).trace('that worked')
    >>> logging.trace('so did this')
    >>> logging.TRACE
    5
    """
    if not methodName:
        methodName = levelName.lower()

    if hasattr(logging, levelName):
        raise AttributeError("{} already defined in logging module".format(levelName))
    if hasattr(logging, methodName):
        raise AttributeError("{} already defined in logging module".format(methodName))
    if hasattr(logging.getLoggerClass(), methodName):
        raise AttributeError("{} already defined in logger class".format(methodName))

    # http://stackoverflow.com/q/2183233/2988730,
    # http://stackoverflow.com/a/13638084/2988730
    def logForLevel(self, message, *args, **kwargs):
        if self.isEnabledFor(levelNum):
            self._log(levelNum, message, args, **kwargs)

    def logToRoot(message, *args, **kwargs):
        logging.log(levelNum, message, *args, **kwargs)

    logging.addLevelName(levelNum, levelName)
    setattr(logging, levelName, levelNum)
    setattr(logging.getLoggerClass(), methodName, logForLevel)
    setattr(logging, methodName, logToRoot)


# =============================================================================
# Create new logging level that is between INFO and WARNING
# TODO: figure out where to put this?
logging_addLevel("PRINT", logging.INFO + 5)
# =============================================================================


def setup(path="data/debug", level="print"):
    """Set up the logging system for the AgReFed Data Harvester.

    Note that because this function is custom, 3 levels can be selected: "info", "print",
    "warning". Obviously, other levels are accessible, just not used (we assume that any level
    higher than WARNING should be in the log file, and not printed).

    Args:
        path (str, optional): path to log file. Defaults to "data/log".
        level (bool, optional): debug level. Defaults to "print". Valid options are "info", "print", and "warning".
    """

    printf = "%(message)s"  # print format
    logf = "%(asctime)s %(levelname)-8s - %(message)s"  # log format

    # Create logger
    logger = logging.getLogger()
    logger.setLevel(logging.INFO)

    # Validate directory, create if necessary
    dir = os.path.normpath(path)
    if not os.path.exists(dir):
        os.makedirs(dir)

    # Generate logfile
    logfile = os.path.join(dir, datetime.date.today().strftime("%Y-%m-%d") + ".log")

    # Log to file settings
    file = logging.FileHandler(logfile)
    fileformat = logging.Formatter(logf)
    file.setLevel(logging.INFO)
    file.setFormatter(fileformat)

    # Log to console settings
    stream = logging.StreamHandler()
    streamformat = logging.Formatter(printf)
    if level == "info":
        stream.setLevel(logging.INFO)
    elif level == "print":
        stream.setLevel(logging.PRINT)
    elif level == "warning":
        stream.setLevel(logging.WARNING)
    stream.setFormatter(streamformat)

    # Flush handlers (for compatibility with R)
    if logger.hasHandlers():
        logger.handlers.clear()

    # Then, add handlers
    logger.addHandler(file)
    logger.addHandler(stream)

Functions

def logging_addLevel(levelName, levelNum, methodName=None)

Add new logging level to logger

Credit to https://stackoverflow.com/a/35804945

Args

levelName : _type_
Name of the logging level.
levelNum : _type_
Numeric value of the logging level.
methodName : _type_, optional
Name of the method to call. Defaults to None.

Example:

>>> addLoggingLevel('TRACE', logging.DEBUG - 5)
>>> logging.getLogger(__name__).setLevel("TRACE")
>>> logging.getLogger(__name__).trace('that worked')
>>> logging.trace('so did this')
>>> logging.TRACE
5
Expand source code
def logging_addLevel(levelName, levelNum, methodName=None):
    """Add new logging level to `logger`

    Credit to https://stackoverflow.com/a/35804945

    Args:
        levelName (_type_): Name of the logging level.
        levelNum (_type_): Numeric value of the logging level.
        methodName (_type_, optional): Name of the method to call. Defaults to None.

    Example:
    >>> addLoggingLevel('TRACE', logging.DEBUG - 5)
    >>> logging.getLogger(__name__).setLevel("TRACE")
    >>> logging.getLogger(__name__).trace('that worked')
    >>> logging.trace('so did this')
    >>> logging.TRACE
    5
    """
    if not methodName:
        methodName = levelName.lower()

    if hasattr(logging, levelName):
        raise AttributeError("{} already defined in logging module".format(levelName))
    if hasattr(logging, methodName):
        raise AttributeError("{} already defined in logging module".format(methodName))
    if hasattr(logging.getLoggerClass(), methodName):
        raise AttributeError("{} already defined in logger class".format(methodName))

    # http://stackoverflow.com/q/2183233/2988730,
    # http://stackoverflow.com/a/13638084/2988730
    def logForLevel(self, message, *args, **kwargs):
        if self.isEnabledFor(levelNum):
            self._log(levelNum, message, args, **kwargs)

    def logToRoot(message, *args, **kwargs):
        logging.log(levelNum, message, *args, **kwargs)

    logging.addLevelName(levelNum, levelName)
    setattr(logging, levelName, levelNum)
    setattr(logging.getLoggerClass(), methodName, logForLevel)
    setattr(logging, methodName, logToRoot)
def setup(path='data/debug', level='print')

Set up the logging system for the AgReFed Data Harvester.

Note that because this function is custom, 3 levels can be selected: "info", "print", "warning". Obviously, other levels are accessible, just not used (we assume that any level higher than WARNING should be in the log file, and not printed).

Args

path : str, optional
path to log file. Defaults to "data/log".
level : bool, optional
debug level. Defaults to "print". Valid options are "info", "print", and "warning".
Expand source code
def setup(path="data/debug", level="print"):
    """Set up the logging system for the AgReFed Data Harvester.

    Note that because this function is custom, 3 levels can be selected: "info", "print",
    "warning". Obviously, other levels are accessible, just not used (we assume that any level
    higher than WARNING should be in the log file, and not printed).

    Args:
        path (str, optional): path to log file. Defaults to "data/log".
        level (bool, optional): debug level. Defaults to "print". Valid options are "info", "print", and "warning".
    """

    printf = "%(message)s"  # print format
    logf = "%(asctime)s %(levelname)-8s - %(message)s"  # log format

    # Create logger
    logger = logging.getLogger()
    logger.setLevel(logging.INFO)

    # Validate directory, create if necessary
    dir = os.path.normpath(path)
    if not os.path.exists(dir):
        os.makedirs(dir)

    # Generate logfile
    logfile = os.path.join(dir, datetime.date.today().strftime("%Y-%m-%d") + ".log")

    # Log to file settings
    file = logging.FileHandler(logfile)
    fileformat = logging.Formatter(logf)
    file.setLevel(logging.INFO)
    file.setFormatter(fileformat)

    # Log to console settings
    stream = logging.StreamHandler()
    streamformat = logging.Formatter(printf)
    if level == "info":
        stream.setLevel(logging.INFO)
    elif level == "print":
        stream.setLevel(logging.PRINT)
    elif level == "warning":
        stream.setLevel(logging.WARNING)
    stream.setFormatter(streamformat)

    # Flush handlers (for compatibility with R)
    if logger.hasHandlers():
        logger.handlers.clear()

    # Then, add handlers
    logger.addHandler(file)
    logger.addHandler(stream)