Skip to content

Commit

Permalink
Merge pull request #61 from FoamyGuy/formatters
Browse files Browse the repository at this point in the history
Adding Formatter and example including timestamp
  • Loading branch information
tannewt committed Aug 7, 2024
2 parents ef3336d + c9ae545 commit cf88c44
Show file tree
Hide file tree
Showing 2 changed files with 130 additions and 2 deletions.
84 changes: 82 additions & 2 deletions adafruit_logging.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@

try:
# pylint: disable=deprecated-class
from typing import Optional, Hashable
from typing import Optional, Hashable, Dict
from typing_extensions import Protocol

class WriteableStream(Protocol):
Expand Down Expand Up @@ -148,12 +148,85 @@ def _logRecordFactory(name, level, msg, args):
return LogRecord(name, level, _level_for(level), msg, time.monotonic(), args)


class Formatter:
"""
Responsible for converting a LogRecord to an output string to be
interpreted by a human or external system.
Only implements a sub-set of CPython logging.Formatter behavior,
but retains all the same arguments in order to match the API.
The only init arguments currently supported are: fmt, defaults and
style. All others are currently ignored
The only two styles currently supported are '%' and '{'. The default
style is '{'
"""

def __init__( # pylint: disable=too-many-arguments
self,
fmt: Optional[str] = None,
datefmt: Optional[str] = None,
style: str = "%",
validate: bool = True,
defaults: Dict = None,
):
self.fmt = fmt
self.datefmt = datefmt
self.style = style
if self.style not in ("{", "%"):
raise ValueError(
"Only '%' and '{' formatting style are supported at this time."
)

self.validate = validate
self.defaults = defaults

def format(self, record: LogRecord) -> str:
"""
Format the given LogRecord into an output string
"""
if self.fmt is None:
return record.msg

vals = {
"name": record.name,
"levelno": record.levelno,
"levelname": record.levelname,
"message": record.msg,
"created": record.created,
"args": record.args,
}
if "{asctime}" in self.fmt or "%(asctime)s" in self.fmt:
now = time.localtime()
# pylint: disable=line-too-long
vals[
"asctime"
] = f"{now.tm_year}-{now.tm_mon:02d}-{now.tm_mday:02d} {now.tm_hour:02d}:{now.tm_min:02d}:{now.tm_sec:02d}"

if self.defaults:
for key, val in self.defaults.items():
if key not in vals:
vals[key] = val

if self.style not in ("{", "%"):
raise ValueError(
"Only '%' and '{' formatting style are supported at this time."
)

if self.style == "%":
return self.fmt % vals

return self.fmt.format(**vals)


class Handler:
"""Base logging message handler."""

def __init__(self, level: int = NOTSET) -> None:
"""Create Handler instance"""
self.level = level
self.formatter = None

def setLevel(self, level: int) -> None:
"""
Expand All @@ -167,7 +240,8 @@ def format(self, record: LogRecord) -> str:
:param record: The record (message object) to be logged
"""

if self.formatter:
return self.formatter.format(record)
return f"{record.created:<0.3f}: {record.levelname} - {record.msg}"

def emit(self, record: LogRecord) -> None:
Expand All @@ -182,6 +256,12 @@ def emit(self, record: LogRecord) -> None:
def flush(self) -> None:
"""Placeholder for flush function in subclasses."""

def setFormatter(self, formatter: Formatter) -> None:
"""
Set the Formatter to be used by this Handler.
"""
self.formatter = formatter


# pylint: disable=too-few-public-methods
class StreamHandler(Handler):
Expand Down
48 changes: 48 additions & 0 deletions examples/logging_formatter_example.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# SPDX-FileCopyrightText: 2024 Tim Cocks
# SPDX-License-Identifier: MIT


"""Illustrate usage of default and custom Formatters including
one with timestamps."""

import adafruit_logging as logging

# To test on CPython, un-comment below and comment out above
# import logging


logger = logging.getLogger("example")
logger.setLevel(logging.INFO)
print_handler = logging.StreamHandler()
logger.addHandler(print_handler)

default_formatter = logging.Formatter()

print_handler.setFormatter(default_formatter)
logger.info("Default formatter example")


timestamp_formatter = logging.Formatter(fmt="%(asctime)s %(levelname)s: %(message)s")
print_handler.setFormatter(timestamp_formatter)
logger.info("Timestamp formatter example")


custom_vals_formatter = logging.Formatter(
fmt="%(ip)s %(levelname)s: %(message)s", defaults={"ip": "192.168.1.188"}
)
print_handler.setFormatter(custom_vals_formatter)
logger.info("Custom formatter example")


bracket_timestamp_formatter = logging.Formatter(
fmt="{asctime} {levelname}: {message}", style="{"
)
print_handler.setFormatter(bracket_timestamp_formatter)
logger.info("Timestamp formatter bracket style example")


bracket_custom_vals_formatter = logging.Formatter(
fmt="{ip} {levelname}: {message}", style="{", defaults={"ip": "192.168.1.188"}
)
print_handler.setFormatter(bracket_custom_vals_formatter)
logger.info("Custom formatter bracket style example")

0 comments on commit cf88c44

Please sign in to comment.