Skip to content

Commit

Permalink
gh-103606: Improve error message from logging.config.FileConfig (GH-1…
Browse files Browse the repository at this point in the history
  • Loading branch information
Agent-Hellboy committed May 18, 2023
1 parent c5b670e commit 152227b
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 6 deletions.
8 changes: 8 additions & 0 deletions Doc/library/logging.config.rst
Expand Up @@ -87,6 +87,10 @@ in :mod:`logging` itself) and defining handlers which are declared either in
provides a mechanism to present the choices and load the chosen
configuration).

It will raise :exc:`FileNotFoundError` if the file
doesn't exist and :exc:`ValueError` if the file is invalid or
empty.

: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
Expand Down Expand Up @@ -126,6 +130,10 @@ in :mod:`logging` itself) and defining handlers which are declared either in
.. versionadded:: 3.10
The *encoding* parameter is added.

.. versionadded:: 3.12
An exception will be thrown if the provided file
doesn't exist or is invalid or empty.

.. function:: listen(port=DEFAULT_LOGGING_CONFIG_PORT, verify=None)

Starts up a socket server on the specified port, and listens for new
Expand Down
22 changes: 16 additions & 6 deletions Lib/logging/config.py
Expand Up @@ -29,6 +29,7 @@
import io
import logging
import logging.handlers
import os
import queue
import re
import struct
Expand Down Expand Up @@ -60,15 +61,24 @@ def fileConfig(fname, defaults=None, disable_existing_loggers=True, encoding=Non
"""
import configparser

if isinstance(fname, str):
if not os.path.exists(fname):
raise FileNotFoundError(f"{fname} doesn't exist")
elif not os.path.getsize(fname):
raise ValueError(f'{fname} is an empty file')

if isinstance(fname, configparser.RawConfigParser):
cp = fname
else:
cp = configparser.ConfigParser(defaults)
if hasattr(fname, 'readline'):
cp.read_file(fname)
else:
encoding = io.text_encoding(encoding)
cp.read(fname, encoding=encoding)
try:
cp = configparser.ConfigParser(defaults)
if hasattr(fname, 'readline'):
cp.read_file(fname)
else:
encoding = io.text_encoding(encoding)
cp.read(fname, encoding=encoding)
except configparser.ParsingError as e:
raise ValueError(f'{fname} is invalid: {e}')

formatters = _create_formatters(cp)

Expand Down
36 changes: 36 additions & 0 deletions Lib/test/test_logging.py
Expand Up @@ -1756,6 +1756,42 @@ def test_config_set_handler_names(self):
self.apply_config(test_config)
self.assertEqual(logging.getLogger().handlers[0].name, 'hand1')

def test_exception_if_confg_file_is_invalid(self):
test_config = """
[loggers]
keys=root
[handlers]
keys=hand1
[formatters]
keys=form1
[logger_root]
handlers=hand1
[handler_hand1]
class=StreamHandler
formatter=form1
[formatter_form1]
format=%(levelname)s ++ %(message)s
prince
"""

file = io.StringIO(textwrap.dedent(test_config))
self.assertRaises(ValueError, logging.config.fileConfig, file)

def test_exception_if_confg_file_is_empty(self):
fd, fn = tempfile.mkstemp(prefix='test_empty_', suffix='.ini')
os.close(fd)
self.assertRaises(ValueError, logging.config.fileConfig, fn)
os.remove(fn)

def test_exception_if_config_file_does_not_exist(self):
self.assertRaises(FileNotFoundError, logging.config.fileConfig, 'filenotfound')

def test_defaults_do_no_interpolation(self):
"""bpo-33802 defaults should not get interpolated"""
ini = textwrap.dedent("""
Expand Down

0 comments on commit 152227b

Please sign in to comment.