Skip to content

Commit 58b42d0

Browse files
committed
logging: Improve formatting of multiline message
1 parent df3d417 commit 58b42d0

File tree

3 files changed

+64
-0
lines changed

3 files changed

+64
-0
lines changed

changelog/5312.feature.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Improved formatting of multiline log messages.

src/_pytest/logging.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,36 @@ def format(self, record):
7171
return super(ColoredLevelFormatter, self).format(record)
7272

7373

74+
if not six.PY2:
75+
76+
class PercentStyleMultiline(logging.PercentStyle):
77+
"""A logging style with special support for multiline messages.
78+
79+
If the message of a record consists of multiple lines, this style
80+
formats the message as if each line were logged separately.
81+
"""
82+
83+
@staticmethod
84+
def _update_message(record_dict, message):
85+
tmp = record_dict.copy()
86+
tmp["message"] = message
87+
return tmp
88+
89+
def format(self, record):
90+
if "\n" in record.message:
91+
fmt = self._fmt
92+
dct = record.__dict__
93+
94+
data_seq = [
95+
# fmt % {**dct, "message": line}
96+
fmt % self._update_message(dct, line)
97+
for line in record.message.splitlines()
98+
]
99+
return "\n".join(data_seq)
100+
else:
101+
return self._fmt % record.__dict__
102+
103+
74104
def get_option_ini(config, *names):
75105
for name in names:
76106
ret = config.getoption(name) # 'default' arg won't work as expected
@@ -438,6 +468,9 @@ def _create_formatter(self, log_format, log_date_format):
438468
)
439469
else:
440470
formatter = logging.Formatter(log_format, log_date_format)
471+
472+
if not six.PY2:
473+
formatter._style = PercentStyleMultiline(formatter._style._fmt)
441474
return formatter
442475

443476
def _setup_cli_logging(self):

testing/logging/test_formatter.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import logging
22

33
import py.io
4+
import six
45

6+
import pytest
57
from _pytest.logging import ColoredLevelFormatter
68

79

@@ -34,3 +36,31 @@ class option(object):
3436
formatter = ColoredLevelFormatter(tw, logfmt)
3537
output = formatter.format(record)
3638
assert output == ("dummypath 10 INFO Test Message")
39+
40+
41+
@pytest.mark.skipif(
42+
six.PY2, reason="Formatter classes don't support format styles in PY2"
43+
)
44+
def test_multiline_message():
45+
from _pytest.logging import PercentStyleMultiline
46+
47+
logfmt = "%(filename)-25s %(lineno)4d %(levelname)-8s %(message)s"
48+
49+
record = logging.LogRecord(
50+
name="dummy",
51+
level=logging.INFO,
52+
pathname="dummypath",
53+
lineno=10,
54+
msg="Test Message line1\nline2",
55+
args=(),
56+
exc_info=False,
57+
)
58+
# this is called by logging.Formatter.format
59+
record.message = record.getMessage()
60+
61+
style = PercentStyleMultiline(logfmt)
62+
output = style.format(record)
63+
assert output == (
64+
"dummypath 10 INFO Test Message line1\n"
65+
"dummypath 10 INFO line2"
66+
)

0 commit comments

Comments
 (0)