Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"

[project]
name = "zenlib"
version = "3.0.0"
version = "3.0.1"
authors = [
{ name="Desultory", email="[email protected]" },
]
Expand Down
5 changes: 3 additions & 2 deletions src/zenlib/logging/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from .colorlognameformatter import ColorLognameFormatter
from .classlogger import ClassLogger
from .loggify import loggify
from .loggermixin import LoggerMixIn
from .log_call import log_call
from .classlogger import ClassLogger

__all__ = ['ColorLognameFormatter', 'loggify', 'log_call', 'ClassLogger']
__all__ = ["ColorLognameFormatter", "loggify", "LoggerMixIn", "log_call", "ClassLogger"]
24 changes: 4 additions & 20 deletions src/zenlib/logging/classlogger.py
Original file line number Diff line number Diff line change
@@ -1,28 +1,12 @@
__author__ = "desultory"
__version__ = "2.2.0"
__version__ = "3.0.0"

from .utils import add_handler_if_not_exists, log_init, handle_additional_logging
from .loggermixin import LoggerMixIn

from logging import Logger, getLogger


class ClassLogger:
class ClassLogger(LoggerMixIn):
def __init__(self, *args, **kwargs):
# Get the parent logger from the root if one was not passed
parent_logger = kwargs.pop('logger') if isinstance(kwargs.get('logger'), Logger) else getLogger()
# Get a child logger from the parent logger, set self.logger
self.logger = parent_logger.getChild(self.__class__.__name__)
# Bump the log level if _log_bump is passed
self.logger.setLevel(self.logger.parent.level + kwargs.pop('_log_bump', 0))

# Add a colored stream handler if one does not exist
add_handler_if_not_exists(self.logger)

# Log class init if _log_init is passed
log_init(self, args, kwargs)

# Add logging to _log_setattr if set
handle_additional_logging(self, kwargs)
self.init_logger(args, kwargs)

if super().__class__.__class__ is not type:
super().__init__(*args, **kwargs)
10 changes: 5 additions & 5 deletions src/zenlib/logging/colorlognameformatter.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
__author__ = "desultory"
__version__ = "3.0.0"
__version__ = "3.1.0"

from logging import Formatter

from zenlib.util import colorize


class ColorLognameFormatter(Formatter):
"""A logging formatter which colors the levelname of the log message.
Uses the zenlib.util.colorize function to color the levelname.
Normal levelnames are padded to the length of the longest levelname."""

level_colors = {
"DEBUG": {"color": "white"},
"DEBUG": {"color": "white", "bright": True},
"INFO": {"color": "blue"},
"WARNING": {"color": "yellow"},
"ERROR": {"color": "red", "bold": True},
Expand All @@ -21,11 +19,13 @@ class ColorLognameFormatter(Formatter):

def __init__(self, fmt="%(levelname)s | %(message)s", *args, **kwargs):
super().__init__(fmt, *args, **kwargs)
self.level_str_width = max(len(name) for name in self.level_colors) - 1
self.level_str_width = max(len(name) for name in self.level_colors)

def format(self, record):
# When calling format, replace the levelname with a colored version
# Note: the string size is greatly increased because of the color codes
from zenlib.util import colorize

old_levelname = record.levelname
color_info = self.level_colors.get(record.levelname, {"color": "white"})
record.levelname = colorize(record.levelname.ljust(self.level_str_width), **color_info)
Expand Down
25 changes: 25 additions & 0 deletions src/zenlib/logging/loggermixin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
__author__ = "desultory"
__version__ = "1.2.0"

from logging import Logger, getLogger

from .utils import add_handler_if_not_exists, handle_additional_logging, log_init


class LoggerMixIn:
def init_logger(self, args, kwargs):
# Get the parent logger from the root if one was not passed
parent_logger = kwargs.pop("logger") if isinstance(kwargs.get("logger"), Logger) else getLogger()
# Get a child logger from the parent logger, set self.logger
self.logger = parent_logger.getChild(self.__class__.__name__)
# Bump the log level if _log_bump is passed
self.logger.setLevel(self.logger.parent.level + kwargs.pop("_log_bump", 0))

# Add a colored stream handler if one does not exist
add_handler_if_not_exists(self.logger)

# Log class init if _log_init is passed
log_init(self, args, kwargs)

# Add logging to _log_setattr if set
handle_additional_logging(self, kwargs)
25 changes: 4 additions & 21 deletions src/zenlib/logging/loggify.py
Original file line number Diff line number Diff line change
@@ -1,32 +1,15 @@
__author__ = "desultory"
__version__ = "2.4.2"

from logging import Logger, getLogger
__version__ = "3.0.0"

from zenlib.util import merge_class

from .utils import add_handler_if_not_exists, log_init, handle_additional_logging
from .loggermixin import LoggerMixIn


def loggify(cls):
class ClassLogger(cls):
class ClassLogger(cls, LoggerMixIn):
def __init__(self, *args, **kwargs):
# Get the parent logger from the root if one was not passed
parent_logger = kwargs.pop("logger") if isinstance(kwargs.get("logger"), Logger) else getLogger()
# Get a child logger from the parent logger, set self.logger
self.logger = parent_logger.getChild(cls.__name__)
# Bump the log level if _log_bump is passed
self.logger.setLevel(self.logger.parent.level + kwargs.pop("_log_bump", 0))

# Add a colored stream handler if one does not exist
add_handler_if_not_exists(self.logger)

# Log class init if _log_init is passed
log_init(self, args, kwargs)

# Add logging to _log_setattr if set
handle_additional_logging(self, kwargs)

self.init_logger(args, kwargs)
super().__init__(*args, **kwargs)

merge_class(cls, ClassLogger, ignored_attributes=["__setattr__"])
Expand Down
8 changes: 4 additions & 4 deletions src/zenlib/types/validated_dataclass.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
from dataclasses import dataclass
from typing import get_type_hints

from zenlib.util import merge_class
from zenlib.logging import loggify


def validatedDataclass(cls):
from zenlib.logging import loggify
from zenlib.util import merge_class

cls = loggify(dataclass(cls))

class ValidatedDataclass(cls):
Expand All @@ -28,5 +28,5 @@ def _validate_attribute(self, attribute, value):
raise TypeError(f"[{attribute}] Type mismatch: '{expected_type}' != {type(value)}")
return value

merge_class(cls, ValidatedDataclass, ignored_attributes = ["__setattr__"])
merge_class(cls, ValidatedDataclass, ignored_attributes=["__setattr__"])
return ValidatedDataclass
3 changes: 2 additions & 1 deletion src/zenlib/util/__init__.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
from .dict_check import contains, unset
from .colorize import colorize
from .dict_check import contains, unset
from .handle_plural import handle_plural
from .main_funcs import get_args_n_logger, get_kwargs, get_kwargs_from_args, init_argparser, init_logger, process_args
from .merge_class import merge_class
from .pretty_print import pretty_print
from .replace_file_line import replace_file_line
from ..types import NoDupFlatList

__all__ = [
"handle_plural",
Expand Down
4 changes: 4 additions & 0 deletions tests/test_nodupflatlist.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@


class TestNoDupFlatList(TestCase):
def test_util_import(self):
from zenlib.util import NoDupFlatList as NDFL
self.assertEqual(NoDupFlatList, NDFL)

def test_dedup1(self):
test_list = NoDupFlatList(no_warn=True)
test_list += 1
Expand Down
Loading