feat: improve colorized logging

This commit is contained in:
sebthom
2024-12-27 15:35:58 +01:00
parent f90f848cba
commit e077f8d86d
4 changed files with 47 additions and 51 deletions

42
pdm.lock generated
View File

@@ -5,7 +5,7 @@
groups = ["default", "dev"]
strategy = []
lock_version = "4.5.0"
content_hash = "sha256:6aa6f02f71070c93d191e7242d0986a66d73173b39bfbc6568ffcbf3deb9f647"
content_hash = "sha256:819a55a6259056418a7d6ba23fefef909ad33f9f73d626662e28a18438b199e0"
[[metadata.targets]]
requires_python = ">=3.10,<3.14"
@@ -112,19 +112,6 @@ files = [
{file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"},
]
[[package]]
name = "coloredlogs"
version = "15.0.1"
requires_python = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
summary = "Colored terminal output for Python's logging module"
dependencies = [
"humanfriendly>=9.1",
]
files = [
{file = "coloredlogs-15.0.1-py2.py3-none-any.whl", hash = "sha256:612ee75c546f53e92e70049c9dbfcc18c935a2b9a53b66085ce9ef6a6e5c0934"},
{file = "coloredlogs-15.0.1.tar.gz", hash = "sha256:7c991aa71a4577af2f82600d8f8f3a89f936baeaf9b50a9c197da014e5bf16b0"},
]
[[package]]
name = "deprecated"
version = "1.2.15"
@@ -158,21 +145,6 @@ files = [
{file = "exceptiongroup-1.2.2.tar.gz", hash = "sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc"},
]
[[package]]
name = "humanfriendly"
version = "10.0"
requires_python = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
summary = "Human friendly output for text interfaces using Python"
dependencies = [
"monotonic; python_version == \"2.7\"",
"pyreadline3; sys_platform == \"win32\" and python_version >= \"3.8\"",
"pyreadline; sys_platform == \"win32\" and python_version < \"3.8\"",
]
files = [
{file = "humanfriendly-10.0-py2.py3-none-any.whl", hash = "sha256:1697e1a8a8f550fd43c2865cd84542fc175a61dcb779b6fee18cf6b6ccba1477"},
{file = "humanfriendly-10.0.tar.gz", hash = "sha256:6b0b831ce8f15f7300721aa49829fc4e83921a9a301cc7f606be6686a2288ddc"},
]
[[package]]
name = "iniconfig"
version = "2.0.0"
@@ -362,7 +334,7 @@ version = "0.38.post1"
requires_python = ">=3.9"
git = "https://github.com/ultrafunkamsterdam/nodriver.git"
revision = "ec6c3fcd8ea18638d6d2b76d5245bed11cbf4aa2"
summary = "\r\n [Docs here](https://ultrafunkamsterdam.github.io/nodriver)\r\n\r\n * Official successor of Undetected Chromedriver\r\n * Can be made to work for for all chromium based browsers.\r\n * Dropped selenium and chromedriver binary requirements.\r\n * fully asynchronous == bizarre performance gains, and more granular control\r\n\r\n Part of undetected-chromedriver, or merely the successor of it, this library is a full rewrite, providing a\r\n fast framework for web automation, webscraping, bots and any other creative ideas which are normally\r\n hindered by annoying anti bot systems like Captcha / CloudFlare / Imperva / hCaptcha and other\r\n big corp \"ai\" money machines using your input to make even more $$ (http://tinyurl.com/bigcorp-ai-inputs)\r\n\r\n The webdriver/selenium requirement is dropped entirely, since this library communicates directly to the browser.\r\n Being fully asynchronous, this adds massive performance improvements and more detailed control possibilities.\r\n\r\n As usual ( like undetected chromedriver) all config details and best practices are built-in, which means\r\n up and running with just a line of code.\r\n\r\n This makes it simple to use for quick prototyping, and perfect for interactive interpreter use (eg: IPython).\r\n\r\n\r\n WARNING:\r\n - results may vary due to many factors. No guarantees are given whatsoever.\r\n - Running from bad IP or datacenter may still cause captcha's and/or other problems.\r\n - With great power comes ... etc etc etc\r\n no but SERIOUS: for your own benefit, make sure \"they\" have no reason for upscaling anti-bot measurements.\r\n there might be one day it would not be feasible anymore to work up against big corp, and provide upgrades\r\n and free libraries.\r\n\r\n"
summary = "[Docs here](https://ultrafunkamsterdam.github.io/nodriver)"
dependencies = [
"deprecated",
"mss",
@@ -523,16 +495,6 @@ files = [
{file = "pylint-3.3.3.tar.gz", hash = "sha256:07c607523b17e6d16e2ae0d7ef59602e332caa762af64203c24b41c27139f36a"},
]
[[package]]
name = "pyreadline3"
version = "3.5.4"
requires_python = ">=3.8"
summary = "A python implementation of GNU readline."
files = [
{file = "pyreadline3-3.5.4-py3-none-any.whl", hash = "sha256:eaf8e6cc3c49bcccf145fc6067ba8643d1df34d604a1ec0eccbf7a18e6d3fae6"},
{file = "pyreadline3-3.5.4.tar.gz", hash = "sha256:8d57d53039a1c75adba8e50dd3d992b28143480816187ea5efbd5c78e6c885b7"},
]
[[package]]
name = "pyright"
version = "1.1.391"

View File

@@ -18,7 +18,6 @@ datas = [
excluded_modules = [
"_aix_support",
"_pydecimal",
"argparse",
"bz2",
"ftplib",

View File

@@ -33,7 +33,6 @@ classifiers = [ # https://pypi.org/classifiers/
requires-python = ">=3.10,<3.14"
dependencies = [
"colorama",
"coloredlogs",
"nodriver @ git+https://github.com/ultrafunkamsterdam/nodriver.git",
"jaraco.text", # required by pkg_resources during runtime
"ruamel.yaml",

View File

@@ -11,7 +11,7 @@ from gettext import gettext as _
from types import FrameType, ModuleType, TracebackType
from typing import Any, Final, TypeVar
import coloredlogs
import colorama
from ruamel.yaml import YAML
from .i18n import get_translating_logger
@@ -154,17 +154,53 @@ def safe_get(a_map:dict[Any, Any], *keys:str) -> Any:
def configure_console_logging() -> None:
class LevelTranslatingFormatter(coloredlogs.ColoredFormatter): # type: ignore
class CustomFormatter(logging.Formatter):
LEVEL_COLORS = {
logging.DEBUG: colorama.Fore.BLACK + colorama.Style.BRIGHT,
logging.INFO: colorama.Fore.BLACK + colorama.Style.BRIGHT,
logging.WARNING: colorama.Fore.YELLOW,
logging.ERROR: colorama.Fore.RED,
logging.CRITICAL: colorama.Fore.RED,
}
MESSAGE_COLORS = {
logging.DEBUG: colorama.Fore.BLACK + colorama.Style.BRIGHT,
logging.INFO: colorama.Fore.RESET,
logging.WARNING: colorama.Fore.YELLOW,
logging.ERROR: colorama.Fore.RED,
logging.CRITICAL: colorama.Fore.RED + colorama.Style.BRIGHT,
}
VALUE_COLORS = {
logging.DEBUG: colorama.Fore.BLACK + colorama.Style.BRIGHT,
logging.INFO: colorama.Fore.MAGENTA,
logging.WARNING: colorama.Fore.MAGENTA,
logging.ERROR: colorama.Fore.MAGENTA,
logging.CRITICAL: colorama.Fore.MAGENTA,
}
def format(self, record:logging.LogRecord) -> str:
msg:str = super().format(record)
if record.levelno > logging.DEBUG:
levelname = _(record.levelname)
if levelname != record.levelname:
msg = msg.replace(record.levelname, levelname, 1)
return msg
record = copy.deepcopy(record)
formatter = LevelTranslatingFormatter("[%(levelname)s] %(message)s")
level_color = self.LEVEL_COLORS.get(record.levelno, "")
msg_color = self.MESSAGE_COLORS.get(record.levelno, "")
value_color = self.VALUE_COLORS.get(record.levelno, "")
# translate and colorize log level name
levelname = _(record.levelname) if record.levelno > logging.DEBUG else record.levelname
record.levelname = f"{level_color}[{levelname}]{colorama.Style.RESET_ALL}"
# highlight message values enclosed by [...], "...", and '...'
record.msg = re.sub(
r"\[([^\]]+)\]|\"([^\"]+)\"|\'([^\']+)\'",
lambda match: f"[{value_color}{match.group(1) or match.group(2) or match.group(3)}{colorama.Fore.RESET}{msg_color}]",
str(record.msg),
)
# colorize message
record.msg = f"{msg_color}{record.msg}{colorama.Style.RESET_ALL}"
return super().format(record)
formatter = CustomFormatter("%(levelname)s %(message)s")
stdout_log = logging.StreamHandler(sys.stderr)
stdout_log.setLevel(logging.DEBUG)