Skip to content

Commit

Permalink
[3.11] pythongh-103606: Improve error message from logging.config.Fil…
Browse files Browse the repository at this point in the history
…eConfig (pythonGH-103628) (python#104687)

* pythongh-103606: Improve error message from logging.config.FileConfig (pythonGH-103628)

(cherry picked from commit 152227b)

plus backport the followup exception change fix to that in python#104701
  • Loading branch information
Agent-Hellboy committed May 21, 2023
1 parent e033eda commit 2ade563
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 6 deletions.
8 changes: 8 additions & 0 deletions Doc/library/logging.config.rst
Original file line number Diff line number Diff line change
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:`RuntimeError` 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.

.. versionchanged:: 3.11.4
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
23 changes: 17 additions & 6 deletions Lib/logging/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
import io
import logging
import logging.handlers
import os
import queue
import re
import struct
import threading
Expand Down Expand Up @@ -58,15 +60,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 RuntimeError(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 RuntimeError(f'{fname} is invalid: {e}')

formatters = _create_formatters(cp)

Expand Down
36 changes: 36 additions & 0 deletions Lib/test/test_logging.py
Original file line number Diff line number Diff line change
Expand Up @@ -1645,6 +1645,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(RuntimeError, 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(RuntimeError, 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 2ade563

Please sign in to comment.