kopia lustrzana https://github.com/micropython/micropython-lib
246 wiersze
5.6 KiB
Python
246 wiersze
5.6 KiB
Python
from micropython import const
|
|
|
|
import sys
|
|
import time
|
|
|
|
CRITICAL = const(50)
|
|
ERROR = const(40)
|
|
WARNING = const(30)
|
|
INFO = const(20)
|
|
DEBUG = const(10)
|
|
NOTSET = const(0)
|
|
|
|
_DEFAULT_LEVEL = const(WARNING)
|
|
|
|
_level_dict = {
|
|
CRITICAL: "CRITICAL",
|
|
ERROR: "ERROR",
|
|
WARNING: "WARNING",
|
|
INFO: "INFO",
|
|
DEBUG: "DEBUG",
|
|
NOTSET: "NOTSET",
|
|
}
|
|
|
|
_loggers = {}
|
|
_stream = sys.stderr
|
|
_default_fmt = "%(levelname)s:%(name)s:%(message)s"
|
|
_default_datefmt = "%Y-%m-%d %H:%M:%S"
|
|
|
|
|
|
class LogRecord:
|
|
def set(self, name, level, message):
|
|
self.name = name
|
|
self.levelno = level
|
|
self.levelname = _level_dict[level]
|
|
self.message = message
|
|
self.ct = time.time()
|
|
self.msecs = int((self.ct - int(self.ct)) * 1000)
|
|
self.asctime = None
|
|
|
|
|
|
class Handler:
|
|
def __init__(self, level=NOTSET):
|
|
self.level = level
|
|
self.formatter = None
|
|
|
|
def close(self):
|
|
pass
|
|
|
|
def setLevel(self, level):
|
|
self.level = level
|
|
|
|
def setFormatter(self, formatter):
|
|
self.formatter = formatter
|
|
|
|
def format(self, record):
|
|
return self.formatter.format(record)
|
|
|
|
|
|
class StreamHandler(Handler):
|
|
def __init__(self, stream=None):
|
|
self.stream = _stream if stream is None else stream
|
|
self.terminator = "\n"
|
|
|
|
def close(self):
|
|
if hasattr(self.stream, "flush"):
|
|
self.stream.flush()
|
|
|
|
def emit(self, record):
|
|
if record.levelno >= self.level:
|
|
self.stream.write(self.format(record) + self.terminator)
|
|
|
|
|
|
class FileHandler(StreamHandler):
|
|
def __init__(self, filename, mode="a", encoding="UTF-8"):
|
|
super().__init__(stream=open(filename, mode=mode, encoding=encoding))
|
|
|
|
def close(self):
|
|
super().close()
|
|
self.stream.close()
|
|
|
|
|
|
class Formatter:
|
|
def __init__(self, fmt=None, datefmt=None):
|
|
self.fmt = _default_fmt if fmt is None else fmt
|
|
self.datefmt = _default_datefmt if datefmt is None else datefmt
|
|
|
|
def usesTime(self):
|
|
return "asctime" in self.fmt
|
|
|
|
def formatTime(self, datefmt, record):
|
|
if hasattr(time, "strftime"):
|
|
return time.strftime(datefmt, time.localtime(record.ct))
|
|
return None
|
|
|
|
def format(self, record):
|
|
if self.usesTime():
|
|
record.asctime = self.formatTime(self.datefmt, record)
|
|
return self.fmt % {
|
|
"name": record.name,
|
|
"message": record.message,
|
|
"msecs": record.msecs,
|
|
"asctime": record.asctime,
|
|
"levelname": record.levelname,
|
|
}
|
|
|
|
|
|
class Logger:
|
|
def __init__(self, name, level=NOTSET):
|
|
self.name = name
|
|
self.level = level
|
|
self.handlers = []
|
|
self.record = LogRecord()
|
|
|
|
def setLevel(self, level):
|
|
self.level = level
|
|
|
|
def isEnabledFor(self, level):
|
|
return level >= self.getEffectiveLevel()
|
|
|
|
def getEffectiveLevel(self):
|
|
return self.level or getLogger().level or _DEFAULT_LEVEL
|
|
|
|
def log(self, level, msg, *args):
|
|
if self.isEnabledFor(level):
|
|
if args:
|
|
if isinstance(args[0], dict):
|
|
args = args[0]
|
|
msg = msg % args
|
|
self.record.set(self.name, level, msg)
|
|
handlers = self.handlers
|
|
if not handlers:
|
|
handlers = getLogger().handlers
|
|
for h in handlers:
|
|
h.emit(self.record)
|
|
|
|
def debug(self, msg, *args):
|
|
self.log(DEBUG, msg, *args)
|
|
|
|
def info(self, msg, *args):
|
|
self.log(INFO, msg, *args)
|
|
|
|
def warning(self, msg, *args):
|
|
self.log(WARNING, msg, *args)
|
|
|
|
def error(self, msg, *args):
|
|
self.log(ERROR, msg, *args)
|
|
|
|
def critical(self, msg, *args):
|
|
self.log(CRITICAL, msg, *args)
|
|
|
|
def exception(self, msg, *args):
|
|
self.log(ERROR, msg, *args)
|
|
if hasattr(sys, "exc_info"):
|
|
sys.print_exception(sys.exc_info()[1], _stream)
|
|
|
|
def addHandler(self, handler):
|
|
self.handlers.append(handler)
|
|
|
|
def hasHandlers(self):
|
|
return len(self.handlers) > 0
|
|
|
|
|
|
def getLogger(name=None):
|
|
if name is None:
|
|
name = "root"
|
|
if name not in _loggers:
|
|
_loggers[name] = Logger(name)
|
|
if name == "root":
|
|
basicConfig()
|
|
return _loggers[name]
|
|
|
|
|
|
def log(level, msg, *args):
|
|
getLogger().log(level, msg, *args)
|
|
|
|
|
|
def debug(msg, *args):
|
|
getLogger().debug(msg, *args)
|
|
|
|
|
|
def info(msg, *args):
|
|
getLogger().info(msg, *args)
|
|
|
|
|
|
def warning(msg, *args):
|
|
getLogger().warning(msg, *args)
|
|
|
|
|
|
def error(msg, *args):
|
|
getLogger().error(msg, *args)
|
|
|
|
|
|
def critical(msg, *args):
|
|
getLogger().critical(msg, *args)
|
|
|
|
|
|
def exception(msg, *args):
|
|
getLogger().exception(msg, *args)
|
|
|
|
|
|
def shutdown():
|
|
for k, logger in _loggers.items():
|
|
for h in logger.handlers:
|
|
h.close()
|
|
_loggers.pop(logger, None)
|
|
|
|
|
|
def addLevelName(level, name):
|
|
_level_dict[level] = name
|
|
|
|
|
|
def basicConfig(
|
|
filename=None,
|
|
filemode="a",
|
|
format=None,
|
|
datefmt=None,
|
|
level=WARNING,
|
|
stream=None,
|
|
encoding="UTF-8",
|
|
force=False,
|
|
):
|
|
if "root" not in _loggers:
|
|
_loggers["root"] = Logger("root")
|
|
|
|
logger = _loggers["root"]
|
|
|
|
if force or not logger.handlers:
|
|
for h in logger.handlers:
|
|
h.close()
|
|
logger.handlers = []
|
|
|
|
if filename is None:
|
|
handler = StreamHandler(stream)
|
|
else:
|
|
handler = FileHandler(filename, filemode, encoding)
|
|
|
|
handler.setLevel(level)
|
|
handler.setFormatter(Formatter(format, datefmt))
|
|
|
|
logger.setLevel(level)
|
|
logger.addHandler(handler)
|
|
|
|
|
|
if hasattr(sys, "atexit"):
|
|
sys.atexit(shutdown)
|