TouchPortalAPI v1.7.8

TouchPortalAPI.logger

  1__copyright__ = """
  2    This file is part of the TouchPortal-API project.
  3    Copyright (c) TouchPortal-API Developers/Contributors
  4    All rights reserved.
  5
  6    This program is free software: you can redistribute it and/or modify
  7    it under the terms of the GNU General Public License as published by
  8    the Free Software Foundation, either version 3 of the License, or
  9    (at your option) any later version.
 10
 11    This program is distributed in the hope that it will be useful,
 12    but WITHOUT ANY WARRANTY; without even the implied warranty of
 13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 14    GNU General Public License for more details.
 15
 16    You should have received a copy of the GNU General Public License
 17    along with this program.  If not, see <https://www.gnu.org/licenses/>.
 18"""
 19
 20import os
 21import sys
 22from dataclasses import asdict, is_dataclass
 23from datetime import datetime, date, time
 24from json import JSONEncoder, dumps
 25from logging import Formatter, getLogger, getLevelName, StreamHandler, NullHandler, Handler
 26from logging.handlers import TimedRotatingFileHandler
 27
 28class Logger:
 29    """ A helper class for common logging requirements, which can be configured via the constructor and provides some convenience
 30    methods.
 31
 32    It uses an instance of Python's `logging.Logger()` class, either the one specified in the `logger` constructor parameter,
 33    or, if `logger` is `None`, one obtained with `logging.getLogger(name=name)`.
 34    Any logger interactions which are not directly supported by this helper class can be accessed directly via `Logger.logger` member.
 35
 36    Due to the how Python's logger works, the first ("root") instance of the logger will define the defaults for any named loggers
 37    added later. These defaults can optionally be overridden per child instance by passing the desired parameters to the constructor
 38    or via the `setLogLevel()`, `setStreamDestination()`, and `setFileDestination()` methods.
 39
 40    The class provides aliases for the `logging.Logger` log writing methodss like `debug()`, `info()`, 'log()', etc.
 41    In addition, some shorter aliases are provided (`dbg()`, `inf()`, `wrn()/warn()`, `err()`, `crt()/fatal()`).
 42
 43    For further details on Python's built-in logging, see: https://docs.python.org/3/library/logging.html
 44    """
 45
 46    """ The default options to use for `TimedRotatingFileHandler`. """
 47    DEFAULT_FILE_HANDLER_OPTS:dict = {'when': 'D', 'backupCount': 7, 'delay': True}
 48    """ The default log formatter for stream and file logger handlers. """
 49    DEFAULT_LOG_FORMATTER = Formatter(
 50        fmt="{asctime:s}.{msecs:03.0f} [{levelname:.1s}] [{filename:s}:{lineno:d}] {message:s}",
 51        datefmt="%H:%M:%S", style="{"
 52    )
 53
 54    def __init__(self, name=None, level=None, stream=None, filename=None, logger=None,
 55                formatter=DEFAULT_LOG_FORMATTER,
 56                fileHandlerOpts=DEFAULT_FILE_HANDLER_OPTS ):
 57        """
 58        Creates an instance of the logger.
 59
 60        Args:
 61            `name`: A name for this logger instance. Each named logger is a global instance, specifying an existing name will use that instance.
 62                The "root" logger has no name.
 63            `level`: Logging level for this logger. `None` will keep the default (root or existing) logger level.
 64            `stream`: Add an instance of `logging.StreamHandler()` with specified stream (eg. `os.stderr`).
 65            `filename`: Add an instance of `logging.handlers.TimedRotatingFileHandler()` with specified file name.
 66                By default the logs are rotated daily and the last 7 files are preserved. This can be changed via the `fileHandlerOpts` argument.
 67            `logger`: Use specified `logging.Logger()` instance. By default a logger instance is created/retreived using `logging.getLogger(name=name)`.
 68            `formatter`: Use specified `logging.Formatter()` as the formatter for the added stream and/or file handlers.
 69                By default the static `DEFAULT_LOG_FORMATTER` is used.
 70            `fileHandlerOpts`: Additional parameters for `TimedRotatingFileHandler` logger.
 71        """
 72        # Create/get logger instance unless specified
 73        self.logger = logger if logger else getLogger(name=name)
 74        # use default formatter unless specified
 75        self.formatter = formatter if formatter else self.DEFAULT_LOG_FORMATTER
 76        # store instance of file/stream handler for possible future access to them (eg. to set logging level)
 77        self.fileHandler = None
 78        self.streamHandler = None
 79        self.nullHandler = None
 80        # logging function aliases
 81        self.log                              = self.logger.log
 82        self.dbg = self.debug                 = self.logger.debug
 83        self.inf = self.info                  = self.logger.info
 84        self.wrn = self.warn  = self.warning  = self.logger.warning
 85        self.err = self.error                 = self.logger.error
 86        self.crt = self.fatal = self.critical = self.logger.critical
 87        self.exception                        = self.logger.exception
 88        # set logging level if specified
 89        if level:
 90            self.setLogLevel(level)
 91        # add file log if a filename was specified
 92        if filename:
 93            self.setFileDestination(filename, fileHandlerOpts)
 94        # add a stream handler if requested or as fallback for failed file logger above
 95        if stream:
 96            self.setStreamDestination(stream)
 97
 98    def setLogLevel(self, level, logger=None):
 99        """
100        Set the miniimum logging level, either globally for all log handlers (`logger=None`, the default), or a specific instance.
101        `level` can be one of:  "CRITICAL", "ERROR", "WARNING", "INFO", "DEBUG" (or equivalent Py `logging` module Level constants),
102        or `None` to disable all logging.
103        """
104        if logger:
105            if isinstance(level, Handler):
106                logger.setLevel(level)
107            return
108
109        currentLevel = None if self.nullHandler else self.logger.getEffectiveLevel()
110        if level and isinstance(level, str):
111            level = getLevelName(level)  # actually gets the numeric value from a name
112        if level == currentLevel:
113            return
114        if level:
115            self.logger.setLevel(level)
116            # if switching from null logging, remove null handler and re-add stream/file handler(s)
117            if self.nullHandler:
118                self.logger.removeHandler(self.nullHandler)
119                self.nullHandler = None
120                if self.fileHandler:
121                    self.logger.addHandler(self.fileHandler)
122                if self.streamHandler:
123                    self.logger.addHandler(self.streamHandler)
124        else:
125            # switch to null logging, remove known file handlers if they exist and set null handler with critical level
126            if self.fileHandler:
127                self.logger.removeHandler(self.fileHandler)
128            if self.streamHandler:
129                self.logger.removeHandler(self.streamHandler)
130            self.nullHandler = NullHandler()
131            self.logger.addHandler(self.nullHandler)
132            self.logger.setLevel("CRITICAL")
133
134    def setStreamDestination(self, stream):
135        """ Set a destination for the StreamHandler logger. `stream` should be a file stream type (eg. os.stderr) or `None` to disable. """
136        if self.streamHandler:
137            self.logger.removeHandler(self.streamHandler)
138            self.streamHandler = None
139        if stream:
140            try:
141                self.streamHandler = StreamHandler(stream)
142                self.streamHandler.setFormatter(self.formatter)
143                self.logger.addHandler(self.streamHandler)
144            except Exception as e:
145                print(f"Error while creating stream logger: \n{repr(e)}")
146
147    def setFileDestination(self, filename, handlerOpts = DEFAULT_FILE_HANDLER_OPTS):
148        """ Set a destination for the File logger. `filename` should be a file name (with or w/out a path) or `None` to disable the file logger. """
149        if self.fileHandler:
150            self.logger.removeHandler(self.fileHandler)
151            self.fileHandler = None
152        if filename:
153            try:
154                if not os.path.splitext(filename)[1]:
155                    filename += ".log"
156                self.fileHandler = TimedRotatingFileHandler(str(filename), **handlerOpts)
157                self.fileHandler.setFormatter(self.formatter)
158                self.logger.addHandler(self.fileHandler)
159            except Exception as e:
160                print(f"Error while creating file logger: \n{repr(e)}")
161
162    class JsonEncoder(JSONEncoder):
163        """ Custom JSON encoder for handling `dataclass` types and pretty-printing date/time types. Used for `format_json()` method. """
164        def default(self, obj):
165            if is_dataclass(obj):
166                return asdict(obj)
167            if isinstance(obj, (datetime, date, time)):
168                return obj.isoformat()
169            return super(Logger.JsonEncoder, self).default(obj)
170
171    @staticmethod
172    def format_json(data, indent=2):
173        """ Returns a string representation of an object, serialized to JSON and formatted for human-readable output (such as logging). """
174        return dumps(data, cls=Logger.JsonEncoder, indent=indent)
class Logger:
 29class Logger:
 30    """ A helper class for common logging requirements, which can be configured via the constructor and provides some convenience
 31    methods.
 32
 33    It uses an instance of Python's `logging.Logger()` class, either the one specified in the `logger` constructor parameter,
 34    or, if `logger` is `None`, one obtained with `logging.getLogger(name=name)`.
 35    Any logger interactions which are not directly supported by this helper class can be accessed directly via `Logger.logger` member.
 36
 37    Due to the how Python's logger works, the first ("root") instance of the logger will define the defaults for any named loggers
 38    added later. These defaults can optionally be overridden per child instance by passing the desired parameters to the constructor
 39    or via the `setLogLevel()`, `setStreamDestination()`, and `setFileDestination()` methods.
 40
 41    The class provides aliases for the `logging.Logger` log writing methodss like `debug()`, `info()`, 'log()', etc.
 42    In addition, some shorter aliases are provided (`dbg()`, `inf()`, `wrn()/warn()`, `err()`, `crt()/fatal()`).
 43
 44    For further details on Python's built-in logging, see: https://docs.python.org/3/library/logging.html
 45    """
 46
 47    """ The default options to use for `TimedRotatingFileHandler`. """
 48    DEFAULT_FILE_HANDLER_OPTS:dict = {'when': 'D', 'backupCount': 7, 'delay': True}
 49    """ The default log formatter for stream and file logger handlers. """
 50    DEFAULT_LOG_FORMATTER = Formatter(
 51        fmt="{asctime:s}.{msecs:03.0f} [{levelname:.1s}] [{filename:s}:{lineno:d}] {message:s}",
 52        datefmt="%H:%M:%S", style="{"
 53    )
 54
 55    def __init__(self, name=None, level=None, stream=None, filename=None, logger=None,
 56                formatter=DEFAULT_LOG_FORMATTER,
 57                fileHandlerOpts=DEFAULT_FILE_HANDLER_OPTS ):
 58        """
 59        Creates an instance of the logger.
 60
 61        Args:
 62            `name`: A name for this logger instance. Each named logger is a global instance, specifying an existing name will use that instance.
 63                The "root" logger has no name.
 64            `level`: Logging level for this logger. `None` will keep the default (root or existing) logger level.
 65            `stream`: Add an instance of `logging.StreamHandler()` with specified stream (eg. `os.stderr`).
 66            `filename`: Add an instance of `logging.handlers.TimedRotatingFileHandler()` with specified file name.
 67                By default the logs are rotated daily and the last 7 files are preserved. This can be changed via the `fileHandlerOpts` argument.
 68            `logger`: Use specified `logging.Logger()` instance. By default a logger instance is created/retreived using `logging.getLogger(name=name)`.
 69            `formatter`: Use specified `logging.Formatter()` as the formatter for the added stream and/or file handlers.
 70                By default the static `DEFAULT_LOG_FORMATTER` is used.
 71            `fileHandlerOpts`: Additional parameters for `TimedRotatingFileHandler` logger.
 72        """
 73        # Create/get logger instance unless specified
 74        self.logger = logger if logger else getLogger(name=name)
 75        # use default formatter unless specified
 76        self.formatter = formatter if formatter else self.DEFAULT_LOG_FORMATTER
 77        # store instance of file/stream handler for possible future access to them (eg. to set logging level)
 78        self.fileHandler = None
 79        self.streamHandler = None
 80        self.nullHandler = None
 81        # logging function aliases
 82        self.log                              = self.logger.log
 83        self.dbg = self.debug                 = self.logger.debug
 84        self.inf = self.info                  = self.logger.info
 85        self.wrn = self.warn  = self.warning  = self.logger.warning
 86        self.err = self.error                 = self.logger.error
 87        self.crt = self.fatal = self.critical = self.logger.critical
 88        self.exception                        = self.logger.exception
 89        # set logging level if specified
 90        if level:
 91            self.setLogLevel(level)
 92        # add file log if a filename was specified
 93        if filename:
 94            self.setFileDestination(filename, fileHandlerOpts)
 95        # add a stream handler if requested or as fallback for failed file logger above
 96        if stream:
 97            self.setStreamDestination(stream)
 98
 99    def setLogLevel(self, level, logger=None):
100        """
101        Set the miniimum logging level, either globally for all log handlers (`logger=None`, the default), or a specific instance.
102        `level` can be one of:  "CRITICAL", "ERROR", "WARNING", "INFO", "DEBUG" (or equivalent Py `logging` module Level constants),
103        or `None` to disable all logging.
104        """
105        if logger:
106            if isinstance(level, Handler):
107                logger.setLevel(level)
108            return
109
110        currentLevel = None if self.nullHandler else self.logger.getEffectiveLevel()
111        if level and isinstance(level, str):
112            level = getLevelName(level)  # actually gets the numeric value from a name
113        if level == currentLevel:
114            return
115        if level:
116            self.logger.setLevel(level)
117            # if switching from null logging, remove null handler and re-add stream/file handler(s)
118            if self.nullHandler:
119                self.logger.removeHandler(self.nullHandler)
120                self.nullHandler = None
121                if self.fileHandler:
122                    self.logger.addHandler(self.fileHandler)
123                if self.streamHandler:
124                    self.logger.addHandler(self.streamHandler)
125        else:
126            # switch to null logging, remove known file handlers if they exist and set null handler with critical level
127            if self.fileHandler:
128                self.logger.removeHandler(self.fileHandler)
129            if self.streamHandler:
130                self.logger.removeHandler(self.streamHandler)
131            self.nullHandler = NullHandler()
132            self.logger.addHandler(self.nullHandler)
133            self.logger.setLevel("CRITICAL")
134
135    def setStreamDestination(self, stream):
136        """ Set a destination for the StreamHandler logger. `stream` should be a file stream type (eg. os.stderr) or `None` to disable. """
137        if self.streamHandler:
138            self.logger.removeHandler(self.streamHandler)
139            self.streamHandler = None
140        if stream:
141            try:
142                self.streamHandler = StreamHandler(stream)
143                self.streamHandler.setFormatter(self.formatter)
144                self.logger.addHandler(self.streamHandler)
145            except Exception as e:
146                print(f"Error while creating stream logger: \n{repr(e)}")
147
148    def setFileDestination(self, filename, handlerOpts = DEFAULT_FILE_HANDLER_OPTS):
149        """ Set a destination for the File logger. `filename` should be a file name (with or w/out a path) or `None` to disable the file logger. """
150        if self.fileHandler:
151            self.logger.removeHandler(self.fileHandler)
152            self.fileHandler = None
153        if filename:
154            try:
155                if not os.path.splitext(filename)[1]:
156                    filename += ".log"
157                self.fileHandler = TimedRotatingFileHandler(str(filename), **handlerOpts)
158                self.fileHandler.setFormatter(self.formatter)
159                self.logger.addHandler(self.fileHandler)
160            except Exception as e:
161                print(f"Error while creating file logger: \n{repr(e)}")
162
163    class JsonEncoder(JSONEncoder):
164        """ Custom JSON encoder for handling `dataclass` types and pretty-printing date/time types. Used for `format_json()` method. """
165        def default(self, obj):
166            if is_dataclass(obj):
167                return asdict(obj)
168            if isinstance(obj, (datetime, date, time)):
169                return obj.isoformat()
170            return super(Logger.JsonEncoder, self).default(obj)
171
172    @staticmethod
173    def format_json(data, indent=2):
174        """ Returns a string representation of an object, serialized to JSON and formatted for human-readable output (such as logging). """
175        return dumps(data, cls=Logger.JsonEncoder, indent=indent)

A helper class for common logging requirements, which can be configured via the constructor and provides some convenience methods.

It uses an instance of Python's logging.Logger() class, either the one specified in the logger constructor parameter, or, if logger is None, one obtained with logging.getLogger(name=name). Any logger interactions which are not directly supported by this helper class can be accessed directly via Logger.logger member.

Due to the how Python's logger works, the first ("root") instance of the logger will define the defaults for any named loggers added later. These defaults can optionally be overridden per child instance by passing the desired parameters to the constructor or via the setLogLevel(), setStreamDestination(), and setFileDestination() methods.

The class provides aliases for the logging.Logger log writing methodss like debug(), info(), 'log()', etc. In addition, some shorter aliases are provided (dbg(), inf(), wrn()/warn(), err(), crt()/fatal()).

For further details on Python's built-in logging, see: https://docs.python.org/3/library/logging.html

Logger( name=None, level=None, stream=None, filename=None, logger=None, formatter=<logging.Formatter object>, fileHandlerOpts={'when': 'D', 'backupCount': 7, 'delay': True})
55    def __init__(self, name=None, level=None, stream=None, filename=None, logger=None,
56                formatter=DEFAULT_LOG_FORMATTER,
57                fileHandlerOpts=DEFAULT_FILE_HANDLER_OPTS ):
58        """
59        Creates an instance of the logger.
60
61        Args:
62            `name`: A name for this logger instance. Each named logger is a global instance, specifying an existing name will use that instance.
63                The "root" logger has no name.
64            `level`: Logging level for this logger. `None` will keep the default (root or existing) logger level.
65            `stream`: Add an instance of `logging.StreamHandler()` with specified stream (eg. `os.stderr`).
66            `filename`: Add an instance of `logging.handlers.TimedRotatingFileHandler()` with specified file name.
67                By default the logs are rotated daily and the last 7 files are preserved. This can be changed via the `fileHandlerOpts` argument.
68            `logger`: Use specified `logging.Logger()` instance. By default a logger instance is created/retreived using `logging.getLogger(name=name)`.
69            `formatter`: Use specified `logging.Formatter()` as the formatter for the added stream and/or file handlers.
70                By default the static `DEFAULT_LOG_FORMATTER` is used.
71            `fileHandlerOpts`: Additional parameters for `TimedRotatingFileHandler` logger.
72        """
73        # Create/get logger instance unless specified
74        self.logger = logger if logger else getLogger(name=name)
75        # use default formatter unless specified
76        self.formatter = formatter if formatter else self.DEFAULT_LOG_FORMATTER
77        # store instance of file/stream handler for possible future access to them (eg. to set logging level)
78        self.fileHandler = None
79        self.streamHandler = None
80        self.nullHandler = None
81        # logging function aliases
82        self.log                              = self.logger.log
83        self.dbg = self.debug                 = self.logger.debug
84        self.inf = self.info                  = self.logger.info
85        self.wrn = self.warn  = self.warning  = self.logger.warning
86        self.err = self.error                 = self.logger.error
87        self.crt = self.fatal = self.critical = self.logger.critical
88        self.exception                        = self.logger.exception
89        # set logging level if specified
90        if level:
91            self.setLogLevel(level)
92        # add file log if a filename was specified
93        if filename:
94            self.setFileDestination(filename, fileHandlerOpts)
95        # add a stream handler if requested or as fallback for failed file logger above
96        if stream:
97            self.setStreamDestination(stream)

Creates an instance of the logger.

Args
  • name: A name for this logger instance. Each named logger is a global instance, specifying an existing name will use that instance. The "root" logger has no name.
  • level: Logging level for this logger. None will keep the default (root or existing) logger level.
  • stream: Add an instance of logging.StreamHandler() with specified stream (eg. os.stderr).
  • filename: Add an instance of logging.handlers.TimedRotatingFileHandler() with specified file name. By default the logs are rotated daily and the last 7 files are preserved. This can be changed via the fileHandlerOpts argument.
  • logger: Use specified logging.Logger() instance. By default a logger instance is created/retreived using logging.getLogger(name=name).
  • formatter: Use specified logging.Formatter() as the formatter for the added stream and/or file handlers. By default the static DEFAULT_LOG_FORMATTER is used.
  • fileHandlerOpts: Additional parameters for TimedRotatingFileHandler logger.
DEFAULT_FILE_HANDLER_OPTS: dict = {'when': 'D', 'backupCount': 7, 'delay': True}

The default log formatter for stream and file logger handlers.

DEFAULT_LOG_FORMATTER = <logging.Formatter object>
def setLogLevel(self, level, logger=None)
 99    def setLogLevel(self, level, logger=None):
100        """
101        Set the miniimum logging level, either globally for all log handlers (`logger=None`, the default), or a specific instance.
102        `level` can be one of:  "CRITICAL", "ERROR", "WARNING", "INFO", "DEBUG" (or equivalent Py `logging` module Level constants),
103        or `None` to disable all logging.
104        """
105        if logger:
106            if isinstance(level, Handler):
107                logger.setLevel(level)
108            return
109
110        currentLevel = None if self.nullHandler else self.logger.getEffectiveLevel()
111        if level and isinstance(level, str):
112            level = getLevelName(level)  # actually gets the numeric value from a name
113        if level == currentLevel:
114            return
115        if level:
116            self.logger.setLevel(level)
117            # if switching from null logging, remove null handler and re-add stream/file handler(s)
118            if self.nullHandler:
119                self.logger.removeHandler(self.nullHandler)
120                self.nullHandler = None
121                if self.fileHandler:
122                    self.logger.addHandler(self.fileHandler)
123                if self.streamHandler:
124                    self.logger.addHandler(self.streamHandler)
125        else:
126            # switch to null logging, remove known file handlers if they exist and set null handler with critical level
127            if self.fileHandler:
128                self.logger.removeHandler(self.fileHandler)
129            if self.streamHandler:
130                self.logger.removeHandler(self.streamHandler)
131            self.nullHandler = NullHandler()
132            self.logger.addHandler(self.nullHandler)
133            self.logger.setLevel("CRITICAL")

Set the miniimum logging level, either globally for all log handlers (logger=None, the default), or a specific instance. level can be one of: "CRITICAL", "ERROR", "WARNING", "INFO", "DEBUG" (or equivalent Py logging module Level constants), or None to disable all logging.

def setStreamDestination(self, stream)
135    def setStreamDestination(self, stream):
136        """ Set a destination for the StreamHandler logger. `stream` should be a file stream type (eg. os.stderr) or `None` to disable. """
137        if self.streamHandler:
138            self.logger.removeHandler(self.streamHandler)
139            self.streamHandler = None
140        if stream:
141            try:
142                self.streamHandler = StreamHandler(stream)
143                self.streamHandler.setFormatter(self.formatter)
144                self.logger.addHandler(self.streamHandler)
145            except Exception as e:
146                print(f"Error while creating stream logger: \n{repr(e)}")

Set a destination for the StreamHandler logger. stream should be a file stream type (eg. os.stderr) or None to disable.

def setFileDestination( self, filename, handlerOpts={'when': 'D', 'backupCount': 7, 'delay': True})
148    def setFileDestination(self, filename, handlerOpts = DEFAULT_FILE_HANDLER_OPTS):
149        """ Set a destination for the File logger. `filename` should be a file name (with or w/out a path) or `None` to disable the file logger. """
150        if self.fileHandler:
151            self.logger.removeHandler(self.fileHandler)
152            self.fileHandler = None
153        if filename:
154            try:
155                if not os.path.splitext(filename)[1]:
156                    filename += ".log"
157                self.fileHandler = TimedRotatingFileHandler(str(filename), **handlerOpts)
158                self.fileHandler.setFormatter(self.formatter)
159                self.logger.addHandler(self.fileHandler)
160            except Exception as e:
161                print(f"Error while creating file logger: \n{repr(e)}")

Set a destination for the File logger. filename should be a file name (with or w/out a path) or None to disable the file logger.

@staticmethod
def format_json(data, indent=2)
172    @staticmethod
173    def format_json(data, indent=2):
174        """ Returns a string representation of an object, serialized to JSON and formatted for human-readable output (such as logging). """
175        return dumps(data, cls=Logger.JsonEncoder, indent=indent)

Returns a string representation of an object, serialized to JSON and formatted for human-readable output (such as logging).

class Logger.JsonEncoder(json.encoder.JSONEncoder):
163    class JsonEncoder(JSONEncoder):
164        """ Custom JSON encoder for handling `dataclass` types and pretty-printing date/time types. Used for `format_json()` method. """
165        def default(self, obj):
166            if is_dataclass(obj):
167                return asdict(obj)
168            if isinstance(obj, (datetime, date, time)):
169                return obj.isoformat()
170            return super(Logger.JsonEncoder, self).default(obj)

Custom JSON encoder for handling dataclass types and pretty-printing date/time types. Used for format_json() method.

def default(self, obj)
165        def default(self, obj):
166            if is_dataclass(obj):
167                return asdict(obj)
168            if isinstance(obj, (datetime, date, time)):
169                return obj.isoformat()
170            return super(Logger.JsonEncoder, self).default(obj)

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
item_separator
key_separator
encode
iterencode