From f7dc544add8acc98fb76696b9aa2cb0cfd54a684 Mon Sep 17 00:00:00 2001 From: foamyguy Date: Mon, 5 Aug 2024 18:15:36 -0500 Subject: [PATCH 1/5] adding Formatter and example including timestamp --- adafruit_logging.py | 68 ++++++++++++++++++++++++++- examples/logging_formatter_example.py | 33 +++++++++++++ 2 files changed, 100 insertions(+), 1 deletion(-) create mode 100644 examples/logging_formatter_example.py diff --git a/adafruit_logging.py b/adafruit_logging.py index 6394f16..4d0ae46 100644 --- a/adafruit_logging.py +++ b/adafruit_logging.py @@ -148,12 +148,71 @@ 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 and defaults. + All others are currently ignored + + The only style value currently supported is '{'. CPython has support + for some others, but this implementation does not. Additionally, the + default value for style in this implementation is '{' whereas the default + style value in CPython is '%' + """ + + def __init__( # pylint: disable=too-many-arguments + self, fmt=None, datefmt=None, style="{", validate=True, defaults=None + ): + self.fmt = fmt + self.datefmt = datefmt + self.style = style + if self.style != "{": + raise ValueError("Only '{' formatting sytle is 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: + now = time.localtime() + vals["asctime"] = ( + f"{now.tm_year}-{now.tm_mon:02d}-{now.tm_mday:02d} " + f"{now.tm_hour:02d}:{now.tm_min:02d}:{now.tm_sec:02d}" + ) + + if self.defaults: + for key, val in self.defaults.items(): + vals[key] = val + + 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: """ @@ -167,7 +226,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: @@ -182,6 +242,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): diff --git a/examples/logging_formatter_example.py b/examples/logging_formatter_example.py new file mode 100644 index 0000000..5e35e37 --- /dev/null +++ b/examples/logging_formatter_example.py @@ -0,0 +1,33 @@ +# SPDX-FileCopyrightText: 2024 Tim Cocks +# SPDX-License-Identifier: MIT + + +"""Briefly exercise the logger and null logger.""" + +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} {levelname}: {message}", style="{" +) +print_handler.setFormatter(timestamp_formatter) +logger.info("Timestamp formatter example") + + +custom_vals_formatter = logging.Formatter( + fmt="{ip} {levelname}: {message}", style="{", defaults={"ip": "192.168.1.188"} +) +print_handler.setFormatter(custom_vals_formatter) +logger.info("Custom formatter example") From 8f53ae15afafde6bb0c3e7abefdc079d43e18296 Mon Sep 17 00:00:00 2001 From: foamyguy Date: Mon, 5 Aug 2024 18:33:48 -0500 Subject: [PATCH 2/5] update comment --- examples/logging_formatter_example.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/examples/logging_formatter_example.py b/examples/logging_formatter_example.py index 5e35e37..460e028 100644 --- a/examples/logging_formatter_example.py +++ b/examples/logging_formatter_example.py @@ -2,9 +2,11 @@ # SPDX-License-Identifier: MIT -"""Briefly exercise the logger and null logger.""" +"""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 From 555981ac12e5937b3fa05560b214242ca277edc2 Mon Sep 17 00:00:00 2001 From: foamyguy Date: Mon, 5 Aug 2024 18:38:38 -0500 Subject: [PATCH 3/5] fix unsupported syntx --- adafruit_logging.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/adafruit_logging.py b/adafruit_logging.py index 4d0ae46..f2041b8 100644 --- a/adafruit_logging.py +++ b/adafruit_logging.py @@ -194,10 +194,10 @@ def format(self, record: LogRecord) -> str: } if "{asctime}" in self.fmt: now = time.localtime() - vals["asctime"] = ( - f"{now.tm_year}-{now.tm_mon:02d}-{now.tm_mday:02d} " - f"{now.tm_hour:02d}:{now.tm_min:02d}:{now.tm_sec:02d}" - ) + # 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(): From ef8c237e276e34af2a54b17a4e6d9eae899b5b9f Mon Sep 17 00:00:00 2001 From: foamyguy Date: Tue, 6 Aug 2024 10:52:17 -0500 Subject: [PATCH 4/5] implement % sytle and change default to it --- adafruit_logging.py | 35 ++++++++++++++++++--------- examples/logging_formatter_example.py | 21 +++++++++++++--- 2 files changed, 41 insertions(+), 15 deletions(-) diff --git a/adafruit_logging.py b/adafruit_logging.py index f2041b8..029b834 100644 --- a/adafruit_logging.py +++ b/adafruit_logging.py @@ -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): @@ -156,23 +156,28 @@ class Formatter: 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 and defaults. - All others are currently ignored + The only init arguments currently supported are: fmt, defaults and + style. All others are currently ignored - The only style value currently supported is '{'. CPython has support - for some others, but this implementation does not. Additionally, the - default value for style in this implementation is '{' whereas the default - style value in CPython is '%' + The only two styles currently supported are '%' and '{'. The default + style is '{' """ def __init__( # pylint: disable=too-many-arguments - self, fmt=None, datefmt=None, style="{", validate=True, defaults=None + 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 != "{": - raise ValueError("Only '{' formatting sytle is supported at this time.") + if self.style not in ("{", "%"): + raise ValueError( + "Only '%' and '{' formatting style are supported at this time." + ) self.validate = validate self.defaults = defaults @@ -192,7 +197,7 @@ def format(self, record: LogRecord) -> str: "created": record.created, "args": record.args, } - if "{asctime}" in self.fmt: + if "{asctime}" in self.fmt or "%(asctime)s" in self.fmt: now = time.localtime() # pylint: disable=line-too-long vals[ @@ -203,6 +208,14 @@ def format(self, record: LogRecord) -> str: for key, val in self.defaults.items(): 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) diff --git a/examples/logging_formatter_example.py b/examples/logging_formatter_example.py index 460e028..ccd2eea 100644 --- a/examples/logging_formatter_example.py +++ b/examples/logging_formatter_example.py @@ -17,19 +17,32 @@ logger.addHandler(print_handler) default_formatter = logging.Formatter() + print_handler.setFormatter(default_formatter) logger.info("Default formatter example") -timestamp_formatter = logging.Formatter( - fmt="{asctime} {levelname}: {message}", style="{" -) +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} {levelname}: {message}", style="{", defaults={"ip": "192.168.1.188"} + 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") From c9ae545190816800bb564892e1fd786ab7adba14 Mon Sep 17 00:00:00 2001 From: foamyguy Date: Tue, 6 Aug 2024 13:12:53 -0500 Subject: [PATCH 5/5] prevent defaults from clobbering --- adafruit_logging.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/adafruit_logging.py b/adafruit_logging.py index 029b834..d037b15 100644 --- a/adafruit_logging.py +++ b/adafruit_logging.py @@ -206,7 +206,8 @@ def format(self, record: LogRecord) -> str: if self.defaults: for key, val in self.defaults.items(): - vals[key] = val + if key not in vals: + vals[key] = val if self.style not in ("{", "%"): raise ValueError( pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy