Closes #16110: fileConfig now accepts a pre-initialised ConfigParser instance.

This commit is contained in:
Vinay Sajip 2012-10-09 09:06:03 +01:00
parent 96df7da0ac
commit cf9e2f2420
3 changed files with 52 additions and 9 deletions

View File

@ -76,11 +76,23 @@ in :mod:`logging` itself) and defining handlers which are declared either in
.. function:: fileConfig(fname, defaults=None, disable_existing_loggers=True)
Reads the logging configuration from a :mod:`configparser`\-format file
named *fname*. This function can be called several times from an
application, allowing an end user to select from various pre-canned
configurations (if the developer provides a mechanism to present the choices
and load the chosen configuration).
Reads the logging configuration from a :mod:`configparser`\-format file.
This function can be called several times from an application, allowing an
end user to select from various pre-canned configurations (if the developer
provides a mechanism to present the choices and load the chosen
configuration).
:param fname: A filename, or a file-like object, or an instance derived
from :class:`~configparser.RawConfigParser`. If a
``RawConfigParser``-derived instance is passed, it is used as
is. Otherwise, a :class:`~configparser.Configparser` is
instantiated, and the configuration read by it from the
object passed in ``fname``. If that has a :meth:`readline`
method, it is assumed to be a file-like object and read using
:meth:`~configparser.ConfigParser.read_file`; otherwise,
it is assumed to be a filename and passed to
:meth:`~configparser.ConfigParser.read`.
:param defaults: Defaults to be passed to the ConfigParser can be specified
in this argument.
@ -94,6 +106,15 @@ in :mod:`logging` itself) and defining handlers which are declared either in
their ancestors are explicitly named in the
logging configuration.
.. versionchanged:: 3.4
An instance of a subclass of :class:`~configparser.RawConfigParser` is
now accepted as a value for ``fname``. This facilitates:
* Use of a configuration file where logging configuration is just part
of the overall application configuration.
* Use of a configuration read from a file, and then modified by the using
application (e.g. based on command-line parameters or other aspects
of the runtime environment) before being passed to ``fileConfig``.
.. function:: listen(port=DEFAULT_LOGGING_CONFIG_PORT, verify=None)

View File

@ -61,11 +61,14 @@ def fileConfig(fname, defaults=None, disable_existing_loggers=True):
"""
import configparser
cp = configparser.ConfigParser(defaults)
if hasattr(fname, 'readline'):
cp.read_file(fname)
if isinstance(fname, configparser.RawConfigParser):
cp = fname
else:
cp.read(fname)
cp = configparser.ConfigParser(defaults)
if hasattr(fname, 'readline'):
cp.read_file(fname)
else:
cp.read(fname)
formatters = _create_formatters(cp)

View File

@ -26,6 +26,7 @@ import logging.handlers
import logging.config
import codecs
import configparser
import datetime
import pickle
import io
@ -1279,6 +1280,24 @@ class ConfigFileTest(BaseTest):
# Original logger output is empty.
self.assert_log_lines([])
def test_config0_using_cp_ok(self):
# A simple config file which overrides the default settings.
with captured_stdout() as output:
file = io.StringIO(textwrap.dedent(self.config0))
cp = configparser.ConfigParser()
cp.read_file(file)
logging.config.fileConfig(cp)
logger = logging.getLogger()
# Won't output anything
logger.info(self.next_message())
# Outputs a message
logger.error(self.next_message())
self.assert_log_lines([
('ERROR', '2'),
], stream=output)
# Original logger output is empty.
self.assert_log_lines([])
def test_config1_ok(self, config=config1):
# A config file defining a sub-parser as well.
with captured_stdout() as output: