diff --git a/Doc/library/logging.rst b/Doc/library/logging.rst index 10772b48837..96fd4283e2a 100644 --- a/Doc/library/logging.rst +++ b/Doc/library/logging.rst @@ -894,6 +894,16 @@ instantiated directly, but always through the module-level function :const:`NOTSET` is found, and that value is returned. +.. method:: Logger.getChild(suffix) + + Returns a logger which is a descendant to this logger, as determined by the suffix. + Thus, ``logging.getLogger('abc').getChild('def.ghi')`` would return the same + logger as would be returned by ``logging.getLogger('abc.def.ghi')``. This is a + convenience method, useful when the parent logger is named using e.g. ``__name__`` + rather than a literal string. + + .. versionadded:: 2.7 + .. method:: Logger.debug(msg[, *args[, **kwargs]]) Logs a message with level :const:`DEBUG` on this logger. The *msg* is the @@ -2472,6 +2482,11 @@ methods of :class:`Logger`, i.e. :meth:`debug`, :meth:`info`, :meth:`warning`, methods have the same signatures as their counterparts in :class:`Logger`, so you can use the two types of instances interchangeably. +.. versionchanged:: 2.7 + +The :meth:`isEnabledFor` method was added to :class:`LoggerAdapter`. This method +delegates to the underlying logger. + Thread Safety ------------- diff --git a/Lib/logging/__init__.py b/Lib/logging/__init__.py index 088c1fc9ca0..239ae61fadb 100644 --- a/Lib/logging/__init__.py +++ b/Lib/logging/__init__.py @@ -1316,6 +1316,25 @@ class Logger(Filterer): return 0 return level >= self.getEffectiveLevel() + def getChild(self, suffix): + """ + Get a logger which is a descendant to this one. + + This is a convenience method, such that + + logging.getLogger('abc').getChild('def.ghi') + + is the same as + + logging.getLogger('abc.def.ghi') + + It's useful, for example, when the parent logger is named using + __name__ rather than a literal string. + """ + if self.root is not self: + suffix = '.'.join((self.name, suffix)) + return self.manager.getLogger(suffix) + class RootLogger(Logger): """ A root logger is not that different to any other logger, except that @@ -1420,6 +1439,12 @@ class LoggerAdapter(object): msg, kwargs = self.process(msg, kwargs) self.logger.log(level, msg, *args, **kwargs) + def isEnabledFor(self, level): + """ + See if the underlying logger is enabled for the specified level. + """ + return self.logger.isEnabledFor(level) + root = RootLogger(WARNING) Logger.root = root Logger.manager = Manager(Logger.root) diff --git a/Lib/test/test_logging.py b/Lib/test/test_logging.py index a918d6eca70..432493b8e5b 100644 --- a/Lib/test/test_logging.py +++ b/Lib/test/test_logging.py @@ -1736,6 +1736,23 @@ class ManagerTest(BaseTest): self.assertEqual(logged, ['should appear in logged']) +class ChildLoggerTest(BaseTest): + def test_child_loggers(self): + r = logging.getLogger() + l1 = logging.getLogger('abc') + l2 = logging.getLogger('def.ghi') + c1 = r.getChild('xyz') + c2 = r.getChild('uvw.xyz') + self.assertTrue(c1 is logging.getLogger('xyz')) + self.assertTrue(c2 is logging.getLogger('uvw.xyz')) + c1 = l1.getChild('def') + c2 = c1.getChild('ghi') + c3 = l1.getChild('def.ghi') + self.assertTrue(c1 is logging.getLogger('abc.def')) + self.assertTrue(c2 is logging.getLogger('abc.def.ghi')) + self.assertTrue(c2 is c3) + + # Set the locale to the platform-dependent default. I have no idea # why the test does this, but in any case we save the current locale # first and restore it at the end. @@ -1744,7 +1761,8 @@ def test_main(): run_unittest(BuiltinLevelsTest, BasicFilterTest, CustomLevelsAndFiltersTest, MemoryHandlerTest, ConfigFileTest, SocketHandlerTest, MemoryTest, - EncodingTest, WarningsTest, ConfigDictTest, ManagerTest) + EncodingTest, WarningsTest, ConfigDictTest, ManagerTest, + ChildLoggerTest) if __name__ == "__main__": test_main() diff --git a/Misc/NEWS b/Misc/NEWS index 08e7760bd1e..f2876d637fe 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -29,6 +29,9 @@ Core and Builtins Library ------- +- logging: Added getChild utility method to Logger and added isEnabledFor + method to LoggerAdapter. + - Issue #8201: logging: Handle situation of non-ASCII and Unicode logger names existing at the same time, causing a Unicode error when configuration code attempted to sort the existing loggers.