diff options
author | Vinay Sajip <vinay_sajip@yahoo.co.uk> | 2011-03-07 18:14:36 (GMT) |
---|---|---|
committer | Vinay Sajip <vinay_sajip@yahoo.co.uk> | 2011-03-07 18:14:36 (GMT) |
commit | 4bcfb92168aeb358479f9149461ac23983a50232 (patch) | |
tree | bc86c39e48182aef401af186903873fc7784f885 | |
parent | 52d3e7e6a59954bd375369843dabdea23bb1dfd3 (diff) | |
parent | 9f9991c2f565cc9494a7bac163f1e2c34afffc09 (diff) | |
download | cpython-4bcfb92168aeb358479f9149461ac23983a50232.zip cpython-4bcfb92168aeb358479f9149461ac23983a50232.tar.gz cpython-4bcfb92168aeb358479f9149461ac23983a50232.tar.bz2 |
Issue #11424: Merged fix from 3.2.
-rw-r--r-- | Lib/logging/config.py | 21 | ||||
-rw-r--r-- | Lib/test/test_logging.py | 218 |
2 files changed, 227 insertions, 12 deletions
diff --git a/Lib/logging/config.py b/Lib/logging/config.py index 5afdf9f..c7359ca 100644 --- a/Lib/logging/config.py +++ b/Lib/logging/config.py @@ -226,14 +226,14 @@ def _install_loggers(cp, handlers, disable_existing): propagate = section.getint("propagate", fallback=1) logger = logging.getLogger(qn) if qn in existing: - i = existing.index(qn) + i = existing.index(qn) + 1 # start with the entry after qn prefixed = qn + "." pflen = len(prefixed) num_existing = len(existing) - i = i + 1 # look at the entry after qn - while (i < num_existing) and (existing[i][:pflen] == prefixed): - child_loggers.append(existing[i]) - i = i + 1 + while i < num_existing: + if existing[i][:pflen] == prefixed: + child_loggers.append(existing[i]) + i += 1 existing.remove(qn) if "level" in section: level = section["level"] @@ -596,15 +596,14 @@ class DictConfigurator(BaseConfigurator): loggers = config.get('loggers', EMPTY_DICT) for name in loggers: if name in existing: - i = existing.index(name) + i = existing.index(name) + 1 # look after name prefixed = name + "." pflen = len(prefixed) num_existing = len(existing) - i = i + 1 # look at the entry after name - while (i < num_existing) and\ - (existing[i][:pflen] == prefixed): - child_loggers.append(existing[i]) - i = i + 1 + while i < num_existing: + if existing[i][:pflen] == prefixed: + child_loggers.append(existing[i]) + i += 1 existing.remove(name) try: self.configure_logger(name, loggers[name]) diff --git a/Lib/test/test_logging.py b/Lib/test/test_logging.py index b29d400..b62545c 100644 --- a/Lib/test/test_logging.py +++ b/Lib/test/test_logging.py @@ -611,6 +611,38 @@ class ConfigFileTest(BaseTest): datefmt= """ + # config1a moves the handler to the root. + config1a = """ + [loggers] + keys=root,parser + + [handlers] + keys=hand1 + + [formatters] + keys=form1 + + [logger_root] + level=WARNING + handlers=hand1 + + [logger_parser] + level=DEBUG + handlers= + propagate=1 + qualname=compiler.parser + + [handler_hand1] + class=StreamHandler + level=NOTSET + formatter=form1 + args=(sys.stdout,) + + [formatter_form1] + format=%(levelname)s ++ %(message)s + datefmt= + """ + # config2 has a subtle configuration error that should be reported config2 = config1.replace("sys.stdout", "sys.stbout") @@ -689,6 +721,44 @@ class ConfigFileTest(BaseTest): datefmt= """ + # config7 adds a compiler logger. + config7 = """ + [loggers] + keys=root,parser,compiler + + [handlers] + keys=hand1 + + [formatters] + keys=form1 + + [logger_root] + level=WARNING + handlers=hand1 + + [logger_compiler] + level=DEBUG + handlers= + propagate=1 + qualname=compiler + + [logger_parser] + level=DEBUG + handlers= + propagate=1 + qualname=compiler.parser + + [handler_hand1] + class=StreamHandler + level=NOTSET + formatter=form1 + args=(sys.stdout,) + + [formatter_form1] + format=%(levelname)s ++ %(message)s + datefmt= + """ + def apply_config(self, conf): file = io.StringIO(textwrap.dedent(conf)) logging.config.fileConfig(file) @@ -752,6 +822,49 @@ class ConfigFileTest(BaseTest): def test_config6_ok(self): self.test_config1_ok(config=self.config6) + def test_config7_ok(self): + with captured_stdout() as output: + self.apply_config(self.config1a) + logger = logging.getLogger("compiler.parser") + # See issue #11424. compiler-hyphenated sorts + # between compiler and compiler.xyz and this + # was preventing compiler.xyz from being included + # in the child loggers of compiler because of an + # overzealous loop termination condition. + hyphenated = logging.getLogger('compiler-hyphenated') + # All will output a message + logger.info(self.next_message()) + logger.error(self.next_message()) + hyphenated.critical(self.next_message()) + self.assert_log_lines([ + ('INFO', '1'), + ('ERROR', '2'), + ('CRITICAL', '3'), + ], stream=output) + # Original logger output is empty. + self.assert_log_lines([]) + with captured_stdout() as output: + self.apply_config(self.config7) + logger = logging.getLogger("compiler.parser") + self.assertFalse(logger.disabled) + # Both will output a message + logger.info(self.next_message()) + logger.error(self.next_message()) + logger = logging.getLogger("compiler.lexer") + # Both will output a message + logger.info(self.next_message()) + logger.error(self.next_message()) + # Will not appear + hyphenated.critical(self.next_message()) + self.assert_log_lines([ + ('INFO', '4'), + ('ERROR', '5'), + ('INFO', '6'), + ('ERROR', '7'), + ], stream=output) + # Original logger output is empty. + self.assert_log_lines([]) + class LogRecordStreamHandler(StreamRequestHandler): """Handler for a streaming logging request. It saves the log message in the @@ -1057,6 +1170,33 @@ class ConfigDictTest(BaseTest): }, } + # config1a moves the handler to the root. Used with config8a + config1a = { + 'version': 1, + 'formatters': { + 'form1' : { + 'format' : '%(levelname)s ++ %(message)s', + }, + }, + 'handlers' : { + 'hand1' : { + 'class' : 'logging.StreamHandler', + 'formatter' : 'form1', + 'level' : 'NOTSET', + 'stream' : 'ext://sys.stdout', + }, + }, + 'loggers' : { + 'compiler.parser' : { + 'level' : 'DEBUG', + }, + }, + 'root' : { + 'level' : 'WARNING', + 'handlers' : ['hand1'], + }, + } + # config2 has a subtle configuration error that should be reported config2 = { 'version': 1, @@ -1307,6 +1447,9 @@ class ConfigDictTest(BaseTest): }, } + # config8 defines both compiler and compiler.lexer + # so compiler.parser should not be disabled (since + # compiler is defined) config8 = { 'version': 1, 'disable_existing_loggers' : False, @@ -1336,6 +1479,36 @@ class ConfigDictTest(BaseTest): }, } + # config8a disables existing loggers + config8a = { + 'version': 1, + 'disable_existing_loggers' : True, + 'formatters': { + 'form1' : { + 'format' : '%(levelname)s ++ %(message)s', + }, + }, + 'handlers' : { + 'hand1' : { + 'class' : 'logging.StreamHandler', + 'formatter' : 'form1', + 'level' : 'NOTSET', + 'stream' : 'ext://sys.stdout', + }, + }, + 'loggers' : { + 'compiler' : { + 'level' : 'DEBUG', + 'handlers' : ['hand1'], + }, + 'compiler.lexer' : { + }, + }, + 'root' : { + 'level' : 'WARNING', + }, + } + config9 = { 'version': 1, 'formatters': { @@ -1636,7 +1809,7 @@ class ConfigDictTest(BaseTest): with captured_stdout() as output: self.apply_config(self.config1) logger = logging.getLogger("compiler.parser") - # Both will output a message + # All will output a message logger.info(self.next_message()) logger.error(self.next_message()) self.assert_log_lines([ @@ -1665,6 +1838,49 @@ class ConfigDictTest(BaseTest): # Original logger output is empty. self.assert_log_lines([]) + def test_config_8a_ok(self): + with captured_stdout() as output: + self.apply_config(self.config1a) + logger = logging.getLogger("compiler.parser") + # See issue #11424. compiler-hyphenated sorts + # between compiler and compiler.xyz and this + # was preventing compiler.xyz from being included + # in the child loggers of compiler because of an + # overzealous loop termination condition. + hyphenated = logging.getLogger('compiler-hyphenated') + # All will output a message + logger.info(self.next_message()) + logger.error(self.next_message()) + hyphenated.critical(self.next_message()) + self.assert_log_lines([ + ('INFO', '1'), + ('ERROR', '2'), + ('CRITICAL', '3'), + ], stream=output) + # Original logger output is empty. + self.assert_log_lines([]) + with captured_stdout() as output: + self.apply_config(self.config8a) + logger = logging.getLogger("compiler.parser") + self.assertFalse(logger.disabled) + # Both will output a message + logger.info(self.next_message()) + logger.error(self.next_message()) + logger = logging.getLogger("compiler.lexer") + # Both will output a message + logger.info(self.next_message()) + logger.error(self.next_message()) + # Will not appear + hyphenated.critical(self.next_message()) + self.assert_log_lines([ + ('INFO', '4'), + ('ERROR', '5'), + ('INFO', '6'), + ('ERROR', '7'), + ], stream=output) + # Original logger output is empty. + self.assert_log_lines([]) + def test_config_9_ok(self): with captured_stdout() as output: self.apply_config(self.config9) |