summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Doc/library/logging.rst12
-rw-r--r--Lib/logging/__init__.py19
-rw-r--r--Lib/test/test_logging.py14
-rw-r--r--Misc/NEWS.d/next/Library/2022-08-29-07-04-03.gh-issue-89258.ri7ncj.rst2
4 files changed, 47 insertions, 0 deletions
diff --git a/Doc/library/logging.rst b/Doc/library/logging.rst
index 319340a..c3806b6 100644
--- a/Doc/library/logging.rst
+++ b/Doc/library/logging.rst
@@ -170,6 +170,18 @@ is the module's name in the Python package namespace.
.. versionadded:: 3.2
+ .. method:: Logger.getChildren()
+
+ Returns a set of loggers which are immediate children of this logger. So for
+ example ``logging.getLogger().getChildren()`` might return a set containing
+ loggers named ``foo`` and ``bar``, but a logger named ``foo.bar`` wouldn't be
+ included in the set. Likewise, ``logging.getLogger('foo').getChildren()`` might
+ return a set including a logger named ``foo.bar``, but it wouldn't include one
+ named ``foo.bar.baz``.
+
+ .. versionadded:: 3.12
+
+
.. method:: Logger.debug(msg, *args, **kwargs)
Logs a message with level :const:`DEBUG` on this logger. The *msg* is the
diff --git a/Lib/logging/__init__.py b/Lib/logging/__init__.py
index c3208a2..86e1efe 100644
--- a/Lib/logging/__init__.py
+++ b/Lib/logging/__init__.py
@@ -1828,6 +1828,25 @@ class Logger(Filterer):
suffix = '.'.join((self.name, suffix))
return self.manager.getLogger(suffix)
+ def getChildren(self):
+
+ def _hierlevel(logger):
+ if logger is logger.manager.root:
+ return 0
+ return 1 + logger.name.count('.')
+
+ d = self.manager.loggerDict
+ _acquireLock()
+ try:
+ # exclude PlaceHolders - the last check is to ensure that lower-level
+ # descendants aren't returned - if there are placeholders, a logger's
+ # parent field might point to a grandparent or ancestor thereof.
+ return set(item for item in d.values()
+ if isinstance(item, Logger) and item.parent is self and
+ _hierlevel(item) == 1 + _hierlevel(item.parent))
+ finally:
+ _releaseLock()
+
def __repr__(self):
level = getLevelName(self.getEffectiveLevel())
return '<%s %s (%s)>' % (self.__class__.__name__, self.name, level)
diff --git a/Lib/test/test_logging.py b/Lib/test/test_logging.py
index a67ed07..0c852fc1 100644
--- a/Lib/test/test_logging.py
+++ b/Lib/test/test_logging.py
@@ -3717,6 +3717,20 @@ class ChildLoggerTest(BaseTest):
self.assertIs(c2, logging.getLogger('abc.def.ghi'))
self.assertIs(c2, c3)
+ def test_get_children(self):
+ r = logging.getLogger()
+ l1 = logging.getLogger('foo')
+ l2 = logging.getLogger('foo.bar')
+ l3 = logging.getLogger('foo.bar.baz.bozz')
+ l4 = logging.getLogger('bar')
+ kids = r.getChildren()
+ expected = {l1, l4}
+ self.assertEqual(expected, kids & expected) # might be other kids for root
+ self.assertNotIn(l2, expected)
+ kids = l1.getChildren()
+ self.assertEqual({l2}, kids)
+ kids = l2.getChildren()
+ self.assertEqual(set(), kids)
class DerivedLogRecord(logging.LogRecord):
pass
diff --git a/Misc/NEWS.d/next/Library/2022-08-29-07-04-03.gh-issue-89258.ri7ncj.rst b/Misc/NEWS.d/next/Library/2022-08-29-07-04-03.gh-issue-89258.ri7ncj.rst
new file mode 100644
index 0000000..74300c1
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2022-08-29-07-04-03.gh-issue-89258.ri7ncj.rst
@@ -0,0 +1,2 @@
+Added a :meth:`~logging.Logger.getChildren` method to
+:class:`logging.Logger`, to get the immediate child loggers of a logger.