loggingTools: move here the LastResortLogger from py23

and add a small test
This commit is contained in:
Cosimo Lupo 2018-06-19 16:54:50 +01:00
parent e6a5db543d
commit d9d30c819a
No known key found for this signature in database
GPG Key ID: 59D54DB0C9976482
3 changed files with 100 additions and 51 deletions

View File

@ -527,6 +527,67 @@ def deprecateFunction(msg, category=UserWarning):
return decorator
class LastResortLogger(logging.Logger):
""" Adds support for 'lastResort' handler introduced in Python 3.2.
It allows to print messages to sys.stderr even when no explicit handler
was configured.
To enable it, you can do:
import logging
logging.lastResort = StderrHandler(logging.WARNING)
logging.setLoggerClass(LastResortLogger)
"""
def callHandlers(self, record):
# this is the same as Python 3.5's logging.Logger.callHandlers
c = self
found = 0
while c:
for hdlr in c.handlers:
found = found + 1
if record.levelno >= hdlr.level:
hdlr.handle(record)
if not c.propagate:
c = None # break out
else:
c = c.parent
if found == 0:
if logging.lastResort:
if record.levelno >= logging.lastResort.level:
logging.lastResort.handle(record)
elif (
logging.raiseExceptions
and not self.manager.emittedNoHandlerWarning
):
sys.stderr.write(
"No handlers could be found for logger"
' "%s"\n' % self.name
)
self.manager.emittedNoHandlerWarning = True
class StderrHandler(logging.StreamHandler):
""" This class is like a StreamHandler using sys.stderr, but always uses
whateve sys.stderr is currently set to rather than the value of
sys.stderr at handler construction time.
"""
def __init__(self, level=logging.NOTSET):
"""
Initialize the handler.
"""
logging.Handler.__init__(self, level)
@property
def stream(self):
# the try/execept avoids failures during interpreter shutdown, when
# globals are set to None
try:
return sys.stderr
except AttributeError:
return __import__("sys").stderr
if __name__ == "__main__":
import doctest
sys.exit(doctest.testmod(optionflags=doctest.ELLIPSIS).failed)

View File

@ -419,56 +419,6 @@ else:
round = round3
import logging
class _Logger(logging.Logger):
""" Add support for 'lastResort' handler introduced in Python 3.2. """
def callHandlers(self, record):
# this is the same as Python 3.5's logging.Logger.callHandlers
c = self
found = 0
while c:
for hdlr in c.handlers:
found = found + 1
if record.levelno >= hdlr.level:
hdlr.handle(record)
if not c.propagate:
c = None # break out
else:
c = c.parent
if (found == 0):
if logging.lastResort:
if record.levelno >= logging.lastResort.level:
logging.lastResort.handle(record)
elif logging.raiseExceptions and not self.manager.emittedNoHandlerWarning:
sys.stderr.write("No handlers could be found for logger"
" \"%s\"\n" % self.name)
self.manager.emittedNoHandlerWarning = True
class _StderrHandler(logging.StreamHandler):
""" This class is like a StreamHandler using sys.stderr, but always uses
whatever sys.stderr is currently set to rather than the value of
sys.stderr at handler construction time.
"""
def __init__(self, level=logging.NOTSET):
"""
Initialize the handler.
"""
logging.Handler.__init__(self, level)
@property
def stream(self):
# the try/execept avoids failures during interpreter shutdown, when
# globals are set to None
try:
return sys.stderr
except AttributeError:
return __import__('sys').stderr
try:
from types import SimpleNamespace
except ImportError:

View File

@ -1,11 +1,20 @@
from __future__ import print_function, division, absolute_import
from fontTools.misc.py23 import *
from fontTools.misc.loggingTools import (
LevelFormatter, Timer, configLogger, ChannelsFilter, LogMixin)
LevelFormatter,
Timer,
configLogger,
ChannelsFilter,
LogMixin,
StderrHandler,
LastResortLogger,
_resetExistingLoggers,
)
import logging
import textwrap
import time
import re
import sys
import pytest
@ -170,3 +179,32 @@ def test_LogMixin():
assert isinstance(b.log, logging.Logger)
assert a.log.name == "loggingTools_test.A"
assert b.log.name == "loggingTools_test.B"
@pytest.mark.skipif(sys.version_info[:2] > (2, 7), reason="only for python2.7")
@pytest.mark.parametrize(
"reset", [True, False], ids=["reset", "no-reset"]
)
def test_LastResortLogger(reset, capsys, caplog):
current = logging.getLoggerClass()
msg = "The quick brown fox jumps over the lazy dog"
try:
if reset:
_resetExistingLoggers()
else:
caplog.set_level(logging.ERROR, logger="myCustomLogger")
logging.lastResort = StderrHandler(logging.WARNING)
logging.setLoggerClass(LastResortLogger)
logger = logging.getLogger("myCustomLogger")
logger.error(msg)
finally:
del logging.lastResort
logging.setLoggerClass(current)
captured = capsys.readouterr()
if reset:
assert msg in captured.err
msg not in caplog.text
else:
msg in caplog.text
msg not in captured.err