Skip to content

Commit

Permalink
refine logging (#38)
Browse files Browse the repository at this point in the history
* refine logging
  • Loading branch information
rkaminsk authored Feb 23, 2024
1 parent 03fa0a5 commit 6bc2ceb
Show file tree
Hide file tree
Showing 5 changed files with 90 additions and 71 deletions.
7 changes: 5 additions & 2 deletions src/fillname/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
The main entry point for the application.
"""

from .utils.logger import setup_logger
import sys

from .utils.logging import configure_logging, get_logger
from .utils.parser import get_parser


Expand All @@ -12,8 +14,9 @@ def main() -> None:
"""
parser = get_parser()
args = parser.parse_args()
log = setup_logger("main", args.log)
configure_logging(sys.stderr, args.log, sys.stderr.isatty())

log = get_logger("main")
log.info("info")
log.warning("warning")
log.debug("debug")
Expand Down
61 changes: 0 additions & 61 deletions src/fillname/utils/logger.py

This file was deleted.

79 changes: 79 additions & 0 deletions src/fillname/utils/logging.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
"""
Setup project wide loggers.
This is a thin wrapper around Python's logging module. It supports colored
logging.
"""

import logging
from typing import TextIO

NOTSET = logging.NOTSET
DEBUG = logging.DEBUG
INFO = logging.INFO
WARNING = logging.WARNING
ERROR = logging.ERROR
CRITICAL = logging.CRITICAL

COLORS = {
"GREY": "\033[90m",
"BLUE": "\033[94m",
"GREEN": "\033[92m",
"YELLOW": "\033[93m",
"RED": "\033[91m",
"NORMAL": "\033[0m",
}


class SingleLevelFilter(logging.Filter):
"""
Filter levels.
"""

passlevel: int
reject: bool

def __init__(self, passlevel: int, reject: bool):
# pylint: disable=super-init-not-called
self.passlevel = passlevel
self.reject = reject

def filter(self, record: logging.LogRecord) -> bool:
if self.reject:
return record.levelno != self.passlevel # nocoverage

return record.levelno == self.passlevel


def configure_logging(stream: TextIO, level: int, use_color: bool) -> None:
"""
Configure application logging.
"""

def format_str(color: str) -> str:
if use_color:
return f"{COLORS[color]}%(levelname)s:{COLORS['GREY']} - %(message)s{COLORS['NORMAL']}"
return "%(levelname)s: - %(message)s" # nocoverage

def make_handler(level: int, color: str) -> "logging.StreamHandler[TextIO]":
handler = logging.StreamHandler(stream)
handler.addFilter(SingleLevelFilter(level, False))
handler.setLevel(level)
formatter = logging.Formatter(format_str(color))
handler.setFormatter(formatter)
return handler

handlers = [
make_handler(logging.INFO, "GREEN"),
make_handler(logging.WARNING, "YELLOW"),
make_handler(logging.DEBUG, "BLUE"),
make_handler(logging.ERROR, "RED"),
]
logging.basicConfig(handlers=handlers, level=level)


def get_logger(name: str) -> logging.Logger:
"""
Get a logger with the given name.
"""
return logging.getLogger(name)
4 changes: 2 additions & 2 deletions src/fillname/utils/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@
The command line parser for the project.
"""

import logging
import sys
from argparse import ArgumentParser
from textwrap import dedent
from typing import Any, Optional, cast

from . import logging

__all__ = ["get_parser"]

if sys.version_info[1] < 8:
Expand All @@ -31,7 +32,6 @@ def get_parser() -> ArgumentParser:
"""
),
)

levels = [
("error", logging.ERROR),
("warning", logging.WARNING),
Expand Down
10 changes: 4 additions & 6 deletions tests/test_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@
Test cases for main application functionality.
"""

import logging
from io import StringIO
from unittest import TestCase

from fillname.utils.logger import setup_logger
from fillname.utils import logging
from fillname.utils.logging import configure_logging, get_logger
from fillname.utils.parser import get_parser


Expand All @@ -19,11 +19,9 @@ def test_logger(self) -> None:
"""
Test the logger.
"""
log = setup_logger("global", logging.INFO)
sio = StringIO()
for handler in log.handlers:
assert isinstance(handler, logging.StreamHandler)
handler.setStream(sio)
configure_logging(sio, logging.INFO, True)
log = get_logger("main")
log.info("test123")
self.assertRegex(sio.getvalue(), "test123")

Expand Down

0 comments on commit 6bc2ceb

Please sign in to comment.