diff -r f051a545a38a Lib/logging/__init__.py --- a/Lib/logging/__init__.py Mon Jan 13 11:25:14 2014 -0800 +++ b/Lib/logging/__init__.py Mon Jan 13 11:36:12 2014 -0800 @@ -313,6 +313,33 @@ msg = msg % self.args return msg + +class StrFormatLogRecord(LogRecord): + def getMessage(self): + """ + Return the message for this LogRecord. + + Return the message for this LogRecord after merging any user-supplied + arguments with the message. + """ + msg = str(self.msg) + if self.args: + msg = msg.format(*self.args) + return msg + +class StringTemplateLogRecord(LogRecord): + def getMessage(self): + """ + Return the message for this LogRecord. + + Return the message for this LogRecord after merging any user-supplied + arguments with the message. + """ + msg = str(self.msg) + if self.args: + tpl = Template(msg) + msg = tpl.substitute(**self.args) + return msg # # Determine which class to use when instantiating log records. # @@ -391,9 +418,9 @@ return self._tpl.substitute(**record.__dict__) _STYLES = { - '%': PercentStyle, - '{': StrFormatStyle, - '$': StringTemplateStyle + '%': (PercentStyle, LogRecord), + '{': (StrFormatStyle, StrFormatLogRecord), + '$': (StringTemplateStyle, StringTemplateLogRecord) } class Formatter(object): @@ -458,7 +485,7 @@ if style not in _STYLES: raise ValueError('Style must be one of: %s' % ','.join( _STYLES.keys())) - self._style = _STYLES[style](fmt) + self._style = _STYLES[style][0](fmt) self._fmt = self._style._fmt self.datefmt = datefmt @@ -1724,6 +1751,7 @@ if fs is None and style == "%": fs = BASIC_FORMAT fmt = Formatter(fs, dfs, style) + setLogRecordFactory(_STYLES[style][1]) for h in handlers: if h.formatter is None: h.setFormatter(fmt) diff -r f051a545a38a Lib/test/test_logging.py --- a/Lib/test/test_logging.py Mon Jan 13 11:25:14 2014 -0800 +++ b/Lib/test/test_logging.py Mon Jan 13 11:36:12 2014 -0800 @@ -3517,6 +3517,22 @@ # level is not explicitly set self.assertEqual(logging.root.level, self.original_logging_level) + def test_percentstyle(self): + with captured_stdout() as output: + logging.basicConfig(stream=sys.stdout, style="%") + logging.error("Log an error") + sys.stdout.seek(0) + self.assertEqual(output.getvalue(), + "ERROR:root:Log an error\n") + + def test_percentstyle(self): + with captured_stdout() as output: + logging.basicConfig(stream=sys.stdout, style="%") + logging.error("Log %s", "an error") + sys.stdout.seek(0) + self.assertEqual(output.getvalue(), + "ERROR:root:Log an error\n") + def test_strformatstyle(self): with captured_stdout() as output: logging.basicConfig(stream=sys.stdout, style="{") @@ -3525,6 +3541,14 @@ self.assertEqual(output.getvalue(), "ERROR:root:Log an error\n") + def test_strformatstyle2(self): + with captured_stdout() as output: + logging.basicConfig(stream=sys.stdout, style="{") + logging.error("Log {}", "an error") + sys.stdout.seek(0) + self.assertEqual(output.getvalue(), + "ERROR:root:Log an error\n") + def test_stringtemplatestyle(self): with captured_stdout() as output: logging.basicConfig(stream=sys.stdout, style="$") @@ -3533,6 +3557,14 @@ self.assertEqual(output.getvalue(), "ERROR:root:Log an error\n") + def test_stringtemplatestyle2(self): + with captured_stdout() as output: + logging.basicConfig(stream=sys.stdout, style="$") + logging.error("Log $foo", {"foo":"an error"}) + sys.stdout.seek(0) + self.assertEqual(output.getvalue(), + "ERROR:root:Log an error\n") + def test_filename(self): def cleanup(h1, h2, fn):