mypydantic.helpers.logger

  1# pylint: disable = super-with-arguments,broad-exception-caught
  2import decimal
  3import json
  4import logging
  5import os
  6from datetime import datetime
  7from typing import Optional, Union
  8
  9import coloredlogs
 10
 11
 12class JsonHelper(json.JSONEncoder):
 13    def default(self, o):
 14        if isinstance(o, decimal.Decimal):
 15            return int(o)
 16        if isinstance(o, set):
 17            return list(o)
 18        if isinstance(o, bytes):
 19            return str(o)
 20        if isinstance(o, datetime):
 21            return str(o)
 22        return super(JsonHelper, self).default(o)
 23
 24
 25class CustomLogger:
 26    log_level = os.getenv("LOG_LEVEL", "INFO")
 27    local = False
 28    propogate = False
 29
 30    def log(self):
 31        logger = logging.getLogger(__name__)
 32        logger.handlers = []
 33        if self.log_level == "ERROR":
 34            coloredlogs.DEFAULT_FIELD_STYLES = {
 35                "asctime": {"bold": True, "color": "black"},
 36                "levelname": {"bold": True, "color": "red"},
 37            }
 38        elif self.log_level == "WARNING":
 39            coloredlogs.DEFAULT_FIELD_STYLES = {
 40                "asctime": {"bold": True, "color": "black"},
 41                "levelname": {"bold": True, "color": "yellow"},
 42            }
 43        elif self.log_level == "DEBUG":
 44            coloredlogs.DEFAULT_FIELD_STYLES = {
 45                "asctime": {"bold": True, "color": "black"},
 46                "levelname": {"bold": True, "color": "blue"},
 47            }
 48        else:
 49            coloredlogs.DEFAULT_FIELD_STYLES = {
 50                "asctime": {"bold": True, "color": "black"},
 51                "levelname": {"bold": True, "color": "blue"},
 52            }
 53        coloredlogs.DEFAULT_LOG_FORMAT = "%(levelname)s: %(asctime)s | %(message)s"
 54
 55        coloredlogs.install(level=self.log_level, logger=logger)
 56        logger.propagate = self.propogate
 57        return logger
 58
 59    def get_message(self, message, details: Optional[Union[list, dict]] = None):
 60        try:
 61            if isinstance(message, (list, dict)):
 62                if self.local:
 63                    message = json.dumps(message, indent=4, cls=JsonHelper)
 64                else:
 65                    message = json.dumps(message, cls=JsonHelper)
 66            if details:
 67                if message[-1] != ":":
 68                    message = f"{message}:"
 69                if isinstance(details, (list, dict)):
 70                    if self.local:
 71                        details = json.dumps(details, indent=4, cls=JsonHelper)
 72                    else:
 73                        details = json.dumps(details, cls=JsonHelper)
 74                message = f"{message}\n{details}"
 75            return message
 76        except Exception:
 77            return message
 78
 79    def info(self, message, details: Optional[Union[list, dict]] = None):
 80        message = self.get_message(message, details)
 81        self.log().info("%s", message)
 82
 83    def debug(self, message, details: Optional[Union[list, dict]] = None):
 84        message = self.get_message(message, details)
 85        self.log().debug("%s", message)
 86
 87    def warning(self, message, details: Optional[Union[list, dict]] = None):
 88        message = self.get_message(message, details)
 89        self.log().warning("%s", message)
 90
 91    def error(self, message, details: Optional[Union[list, dict]] = None):
 92        message = self.get_message(message, details)
 93        self.log().error("%s", message)
 94
 95    def output(self, values: dict):
 96        wrkdir = os.getcwd()
 97        file_path = "output_logs.json"
 98        with open(file_path, "w", encoding="utf-8") as out_file:
 99            out_file.write(json.dumps(values, indent=4, cls=JsonHelper))
100        self.log().info("Logs output to: %s/%s", wrkdir, file_path)
class JsonHelper(json.encoder.JSONEncoder):
13class JsonHelper(json.JSONEncoder):
14    def default(self, o):
15        if isinstance(o, decimal.Decimal):
16            return int(o)
17        if isinstance(o, set):
18            return list(o)
19        if isinstance(o, bytes):
20            return str(o)
21        if isinstance(o, datetime):
22            return str(o)
23        return super(JsonHelper, self).default(o)

Extensible JSON http://json.org encoder for Python data structures.

Supports the following objects and types by default:

+-------------------+---------------+ | Python | JSON | +===================+===============+ | dict | object | +-------------------+---------------+ | list, tuple | array | +-------------------+---------------+ | str | string | +-------------------+---------------+ | int, float | number | +-------------------+---------------+ | True | true | +-------------------+---------------+ | False | false | +-------------------+---------------+ | None | null | +-------------------+---------------+

To extend this to recognize other objects, subclass and implement a .default() method with another method that returns a serializable object for o if possible, otherwise it should call the superclass implementation (to raise TypeError).

def default(self, o):
14    def default(self, o):
15        if isinstance(o, decimal.Decimal):
16            return int(o)
17        if isinstance(o, set):
18            return list(o)
19        if isinstance(o, bytes):
20            return str(o)
21        if isinstance(o, datetime):
22            return str(o)
23        return super(JsonHelper, self).default(o)

Implement this method in a subclass such that it returns a serializable object for o, or calls the base implementation (to raise a TypeError).

For example, to support arbitrary iterators, you could implement default like this::

def default(self, o):
    try:
        iterable = iter(o)
    except TypeError:
        pass
    else:
        return list(iterable)
    # Let the base class default method raise the TypeError
    return JSONEncoder.default(self, o)
Inherited Members
json.encoder.JSONEncoder
JSONEncoder
encode
iterencode
class CustomLogger:
 26class CustomLogger:
 27    log_level = os.getenv("LOG_LEVEL", "INFO")
 28    local = False
 29    propogate = False
 30
 31    def log(self):
 32        logger = logging.getLogger(__name__)
 33        logger.handlers = []
 34        if self.log_level == "ERROR":
 35            coloredlogs.DEFAULT_FIELD_STYLES = {
 36                "asctime": {"bold": True, "color": "black"},
 37                "levelname": {"bold": True, "color": "red"},
 38            }
 39        elif self.log_level == "WARNING":
 40            coloredlogs.DEFAULT_FIELD_STYLES = {
 41                "asctime": {"bold": True, "color": "black"},
 42                "levelname": {"bold": True, "color": "yellow"},
 43            }
 44        elif self.log_level == "DEBUG":
 45            coloredlogs.DEFAULT_FIELD_STYLES = {
 46                "asctime": {"bold": True, "color": "black"},
 47                "levelname": {"bold": True, "color": "blue"},
 48            }
 49        else:
 50            coloredlogs.DEFAULT_FIELD_STYLES = {
 51                "asctime": {"bold": True, "color": "black"},
 52                "levelname": {"bold": True, "color": "blue"},
 53            }
 54        coloredlogs.DEFAULT_LOG_FORMAT = "%(levelname)s: %(asctime)s | %(message)s"
 55
 56        coloredlogs.install(level=self.log_level, logger=logger)
 57        logger.propagate = self.propogate
 58        return logger
 59
 60    def get_message(self, message, details: Optional[Union[list, dict]] = None):
 61        try:
 62            if isinstance(message, (list, dict)):
 63                if self.local:
 64                    message = json.dumps(message, indent=4, cls=JsonHelper)
 65                else:
 66                    message = json.dumps(message, cls=JsonHelper)
 67            if details:
 68                if message[-1] != ":":
 69                    message = f"{message}:"
 70                if isinstance(details, (list, dict)):
 71                    if self.local:
 72                        details = json.dumps(details, indent=4, cls=JsonHelper)
 73                    else:
 74                        details = json.dumps(details, cls=JsonHelper)
 75                message = f"{message}\n{details}"
 76            return message
 77        except Exception:
 78            return message
 79
 80    def info(self, message, details: Optional[Union[list, dict]] = None):
 81        message = self.get_message(message, details)
 82        self.log().info("%s", message)
 83
 84    def debug(self, message, details: Optional[Union[list, dict]] = None):
 85        message = self.get_message(message, details)
 86        self.log().debug("%s", message)
 87
 88    def warning(self, message, details: Optional[Union[list, dict]] = None):
 89        message = self.get_message(message, details)
 90        self.log().warning("%s", message)
 91
 92    def error(self, message, details: Optional[Union[list, dict]] = None):
 93        message = self.get_message(message, details)
 94        self.log().error("%s", message)
 95
 96    def output(self, values: dict):
 97        wrkdir = os.getcwd()
 98        file_path = "output_logs.json"
 99        with open(file_path, "w", encoding="utf-8") as out_file:
100            out_file.write(json.dumps(values, indent=4, cls=JsonHelper))
101        self.log().info("Logs output to: %s/%s", wrkdir, file_path)
def log(self):
31    def log(self):
32        logger = logging.getLogger(__name__)
33        logger.handlers = []
34        if self.log_level == "ERROR":
35            coloredlogs.DEFAULT_FIELD_STYLES = {
36                "asctime": {"bold": True, "color": "black"},
37                "levelname": {"bold": True, "color": "red"},
38            }
39        elif self.log_level == "WARNING":
40            coloredlogs.DEFAULT_FIELD_STYLES = {
41                "asctime": {"bold": True, "color": "black"},
42                "levelname": {"bold": True, "color": "yellow"},
43            }
44        elif self.log_level == "DEBUG":
45            coloredlogs.DEFAULT_FIELD_STYLES = {
46                "asctime": {"bold": True, "color": "black"},
47                "levelname": {"bold": True, "color": "blue"},
48            }
49        else:
50            coloredlogs.DEFAULT_FIELD_STYLES = {
51                "asctime": {"bold": True, "color": "black"},
52                "levelname": {"bold": True, "color": "blue"},
53            }
54        coloredlogs.DEFAULT_LOG_FORMAT = "%(levelname)s: %(asctime)s | %(message)s"
55
56        coloredlogs.install(level=self.log_level, logger=logger)
57        logger.propagate = self.propogate
58        return logger
def get_message(self, message, details: Union[list, dict, NoneType] = None):
60    def get_message(self, message, details: Optional[Union[list, dict]] = None):
61        try:
62            if isinstance(message, (list, dict)):
63                if self.local:
64                    message = json.dumps(message, indent=4, cls=JsonHelper)
65                else:
66                    message = json.dumps(message, cls=JsonHelper)
67            if details:
68                if message[-1] != ":":
69                    message = f"{message}:"
70                if isinstance(details, (list, dict)):
71                    if self.local:
72                        details = json.dumps(details, indent=4, cls=JsonHelper)
73                    else:
74                        details = json.dumps(details, cls=JsonHelper)
75                message = f"{message}\n{details}"
76            return message
77        except Exception:
78            return message
def info(self, message, details: Union[list, dict, NoneType] = None):
80    def info(self, message, details: Optional[Union[list, dict]] = None):
81        message = self.get_message(message, details)
82        self.log().info("%s", message)
def debug(self, message, details: Union[list, dict, NoneType] = None):
84    def debug(self, message, details: Optional[Union[list, dict]] = None):
85        message = self.get_message(message, details)
86        self.log().debug("%s", message)
def warning(self, message, details: Union[list, dict, NoneType] = None):
88    def warning(self, message, details: Optional[Union[list, dict]] = None):
89        message = self.get_message(message, details)
90        self.log().warning("%s", message)
def error(self, message, details: Union[list, dict, NoneType] = None):
92    def error(self, message, details: Optional[Union[list, dict]] = None):
93        message = self.get_message(message, details)
94        self.log().error("%s", message)
def output(self, values: dict):
 96    def output(self, values: dict):
 97        wrkdir = os.getcwd()
 98        file_path = "output_logs.json"
 99        with open(file_path, "w", encoding="utf-8") as out_file:
100            out_file.write(json.dumps(values, indent=4, cls=JsonHelper))
101        self.log().info("Logs output to: %s/%s", wrkdir, file_path)