Skip to content

Commit

Permalink
logging: Improve formatting of multiline message
Browse files Browse the repository at this point in the history
  • Loading branch information
twmr committed May 25, 2019
1 parent df3d417 commit 58b42d0
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 0 deletions.
1 change: 1 addition & 0 deletions changelog/5312.feature.rst
@@ -0,0 +1 @@
Improved formatting of multiline log messages.
33 changes: 33 additions & 0 deletions src/_pytest/logging.py
Expand Up @@ -71,6 +71,36 @@ def format(self, record):
return super(ColoredLevelFormatter, self).format(record)


if not six.PY2:

class PercentStyleMultiline(logging.PercentStyle):
"""A logging style with special support for multiline messages.
If the message of a record consists of multiple lines, this style
formats the message as if each line were logged separately.
"""

@staticmethod
def _update_message(record_dict, message):
tmp = record_dict.copy()
tmp["message"] = message
return tmp

def format(self, record):
if "\n" in record.message:
fmt = self._fmt
dct = record.__dict__

data_seq = [
# fmt % {**dct, "message": line}
fmt % self._update_message(dct, line)
for line in record.message.splitlines()
]
return "\n".join(data_seq)
else:
return self._fmt % record.__dict__


def get_option_ini(config, *names):
for name in names:
ret = config.getoption(name) # 'default' arg won't work as expected
Expand Down Expand Up @@ -438,6 +468,9 @@ def _create_formatter(self, log_format, log_date_format):
)
else:
formatter = logging.Formatter(log_format, log_date_format)

if not six.PY2:
formatter._style = PercentStyleMultiline(formatter._style._fmt)
return formatter

def _setup_cli_logging(self):
Expand Down
30 changes: 30 additions & 0 deletions testing/logging/test_formatter.py
@@ -1,7 +1,9 @@
import logging

import py.io
import six

import pytest
from _pytest.logging import ColoredLevelFormatter


Expand Down Expand Up @@ -34,3 +36,31 @@ class option(object):
formatter = ColoredLevelFormatter(tw, logfmt)
output = formatter.format(record)
assert output == ("dummypath 10 INFO Test Message")


@pytest.mark.skipif(
six.PY2, reason="Formatter classes don't support format styles in PY2"
)
def test_multiline_message():
from _pytest.logging import PercentStyleMultiline

logfmt = "%(filename)-25s %(lineno)4d %(levelname)-8s %(message)s"

record = logging.LogRecord(
name="dummy",
level=logging.INFO,
pathname="dummypath",
lineno=10,
msg="Test Message line1\nline2",
args=(),
exc_info=False,
)
# this is called by logging.Formatter.format
record.message = record.getMessage()

style = PercentStyleMultiline(logfmt)
output = style.format(record)
assert output == (
"dummypath 10 INFO Test Message line1\n"
"dummypath 10 INFO line2"
)

0 comments on commit 58b42d0

Please sign in to comment.