bpo-31457: Don't omit inner `process()` calls with nested LogAdapters (#4044)

This used to be the case on Python 2.  Commit
212b590e11 changed the implementation for Python
3, making the `log()` method of LogAdapter call `logger._log()` directly.  This
makes nested log adapters not execute their ``process()`` method.  This patch
fixes the issue.

Also, now proxying `name`, too, to make `repr()` work with nested log adapters.

New tests added.
This commit is contained in:
Łukasz Langa 2017-10-19 10:24:55 -07:00 committed by GitHub
parent 05a634b12a
commit ce9e625445
3 changed files with 21 additions and 7 deletions

View file

@ -1713,7 +1713,7 @@ def log(self, level, msg, *args, **kwargs):
""" """
if self.isEnabledFor(level): if self.isEnabledFor(level):
msg, kwargs = self.process(msg, kwargs) msg, kwargs = self.process(msg, kwargs)
self.logger._log(level, msg, args, **kwargs) self.logger.log(level, msg, *args, **kwargs)
def isEnabledFor(self, level): def isEnabledFor(self, level):
""" """
@ -1760,6 +1760,10 @@ def manager(self):
def manager(self, value): def manager(self, value):
self.logger.manager = value self.logger.manager = value
@property
def name(self):
return self.logger.name
def __repr__(self): def __repr__(self):
logger = self.logger logger = self.logger
level = getLevelName(logger.getEffectiveLevel()) level = getLevelName(logger.getEffectiveLevel())

View file

@ -3904,7 +3904,6 @@ def test_critical(self):
class LoggerAdapterTest(unittest.TestCase): class LoggerAdapterTest(unittest.TestCase):
def setUp(self): def setUp(self):
super(LoggerAdapterTest, self).setUp() super(LoggerAdapterTest, self).setUp()
old_handler_list = logging._handlerList[:] old_handler_list = logging._handlerList[:]
@ -3979,27 +3978,36 @@ def test_has_handlers(self):
self.assertFalse(self.adapter.hasHandlers()) self.assertFalse(self.adapter.hasHandlers())
def test_nested(self): def test_nested(self):
class Adapter(logging.LoggerAdapter):
prefix = 'Adapter'
def process(self, msg, kwargs):
return f"{self.prefix} {msg}", kwargs
msg = 'Adapters can be nested, yo.' msg = 'Adapters can be nested, yo.'
adapter_adapter = logging.LoggerAdapter(logger=self.adapter, extra=None) adapter = Adapter(logger=self.logger, extra=None)
adapter_adapter = Adapter(logger=adapter, extra=None)
adapter_adapter.prefix = 'AdapterAdapter'
self.assertEqual(repr(adapter), repr(adapter_adapter))
adapter_adapter.log(logging.CRITICAL, msg, self.recording) adapter_adapter.log(logging.CRITICAL, msg, self.recording)
self.assertEqual(len(self.recording.records), 1) self.assertEqual(len(self.recording.records), 1)
record = self.recording.records[0] record = self.recording.records[0]
self.assertEqual(record.levelno, logging.CRITICAL) self.assertEqual(record.levelno, logging.CRITICAL)
self.assertEqual(record.msg, msg) self.assertEqual(record.msg, f"Adapter AdapterAdapter {msg}")
self.assertEqual(record.args, (self.recording,)) self.assertEqual(record.args, (self.recording,))
orig_manager = adapter_adapter.manager orig_manager = adapter_adapter.manager
self.assertIs(self.adapter.manager, orig_manager) self.assertIs(adapter.manager, orig_manager)
self.assertIs(self.logger.manager, orig_manager) self.assertIs(self.logger.manager, orig_manager)
temp_manager = object() temp_manager = object()
try: try:
adapter_adapter.manager = temp_manager adapter_adapter.manager = temp_manager
self.assertIs(adapter_adapter.manager, temp_manager) self.assertIs(adapter_adapter.manager, temp_manager)
self.assertIs(self.adapter.manager, temp_manager) self.assertIs(adapter.manager, temp_manager)
self.assertIs(self.logger.manager, temp_manager) self.assertIs(self.logger.manager, temp_manager)
finally: finally:
adapter_adapter.manager = orig_manager adapter_adapter.manager = orig_manager
self.assertIs(adapter_adapter.manager, orig_manager) self.assertIs(adapter_adapter.manager, orig_manager)
self.assertIs(self.adapter.manager, orig_manager) self.assertIs(adapter.manager, orig_manager)
self.assertIs(self.logger.manager, orig_manager) self.assertIs(self.logger.manager, orig_manager)

View file

@ -0,0 +1,2 @@
If nested log adapters are used, the inner ``process()`` methods are no
longer omitted.