From d7c68639795a576ff58b6479c8bb34c113df3618 Mon Sep 17 00:00:00 2001 From: Mario Corchero Date: Mon, 24 Jan 2022 13:39:50 +0100 Subject: [PATCH] bpo-41906: Accept built filters in dictConfig (GH-30756) When configuring the logging stack, accept already built filters (or just callables) in the filters array of loggers and handlers. This facilitates passing quick callables as filters. Automerge-Triggered-By: GH:vsajip --- Doc/library/logging.config.rst | 10 +++++ Lib/logging/config.py | 6 ++- Lib/test/test_logging.py | 38 +++++++++++++++++++ .../2022-01-21-18-19-45.bpo-41906.YBaquj.rst | 2 + 4 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 Misc/NEWS.d/next/Library/2022-01-21-18-19-45.bpo-41906.YBaquj.rst diff --git a/Doc/library/logging.config.rst b/Doc/library/logging.config.rst index a1b8dc755ba..c979961a221 100644 --- a/Doc/library/logging.config.rst +++ b/Doc/library/logging.config.rst @@ -288,6 +288,9 @@ otherwise, the context is used to determine what to instantiate. * ``filters`` (optional). A list of ids of the filters for this handler. + .. versionchanged:: 3.11 + ``filters`` can take filter instances in addition to ids. + All *other* keys are passed through as keyword arguments to the handler's constructor. For example, given the snippet: @@ -326,6 +329,9 @@ otherwise, the context is used to determine what to instantiate. * ``filters`` (optional). A list of ids of the filters for this logger. + .. versionchanged:: 3.11 + ``filters`` can take filter instances in addition to ids. + * ``handlers`` (optional). A list of ids of the handlers for this logger. @@ -524,6 +530,10 @@ valid keyword parameter name, and so will not clash with the names of the keyword arguments used in the call. The ``'()'`` also serves as a mnemonic that the corresponding value is a callable. + .. versionchanged:: 3.11 + The ``filters`` member of ``handlers`` and ``loggers`` can take + filter instances in addition to ids. + .. _logging-config-dict-externalobj: diff --git a/Lib/logging/config.py b/Lib/logging/config.py index 9bc07eddd76..86a1e4eaf4c 100644 --- a/Lib/logging/config.py +++ b/Lib/logging/config.py @@ -694,7 +694,11 @@ def add_filters(self, filterer, filters): """Add filters to a filterer from a list of names.""" for f in filters: try: - filterer.addFilter(self.config['filters'][f]) + if callable(f) or callable(getattr(f, 'filter', None)): + filter_ = f + else: + filter_ = self.config['filters'][f] + filterer.addFilter(filter_) except Exception as e: raise ValueError('Unable to add filter %r' % f) from e diff --git a/Lib/test/test_logging.py b/Lib/test/test_logging.py index 7c38676012b..4f3315161cf 100644 --- a/Lib/test/test_logging.py +++ b/Lib/test/test_logging.py @@ -3447,6 +3447,44 @@ def emit(self, record): logging.info('some log') self.assertEqual(stderr.getvalue(), 'some log my_type\n') + def test_config_callable_filter_works(self): + def filter_(_): + return 1 + self.apply_config({ + "version": 1, "root": {"level": "DEBUG", "filters": [filter_]} + }) + assert logging.getLogger().filters[0] is filter_ + logging.getLogger().filters = [] + + def test_config_filter_works(self): + filter_ = logging.Filter("spam.eggs") + self.apply_config({ + "version": 1, "root": {"level": "DEBUG", "filters": [filter_]} + }) + assert logging.getLogger().filters[0] is filter_ + logging.getLogger().filters = [] + + def test_config_filter_method_works(self): + class FakeFilter: + def filter(self, _): + return 1 + filter_ = FakeFilter() + self.apply_config({ + "version": 1, "root": {"level": "DEBUG", "filters": [filter_]} + }) + assert logging.getLogger().filters[0] is filter_ + logging.getLogger().filters = [] + + def test_invalid_type_raises(self): + class NotAFilter: pass + for filter_ in [None, 1, NotAFilter()]: + self.assertRaises( + ValueError, + self.apply_config, + {"version": 1, "root": {"level": "DEBUG", "filters": [filter_]}} + ) + + class ManagerTest(BaseTest): def test_manager_loggerclass(self): logged = [] diff --git a/Misc/NEWS.d/next/Library/2022-01-21-18-19-45.bpo-41906.YBaquj.rst b/Misc/NEWS.d/next/Library/2022-01-21-18-19-45.bpo-41906.YBaquj.rst new file mode 100644 index 00000000000..be707130875 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2022-01-21-18-19-45.bpo-41906.YBaquj.rst @@ -0,0 +1,2 @@ +Support passing filter instances in the ``filters`` values of ``handlers`` and +``loggers`` in the dictionary passed to :func:`logging.config.dictConfig`.