Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Preformatted class for logging preformatted messages #2998

Merged
merged 4 commits into from
Sep 24, 2023
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 17 additions & 1 deletion pyomo/common/log.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,11 +107,14 @@ def __init__(self, **kwds):
super(WrappingFormatter, self).__init__(**kwds)

def format(self, record):
msg = record.getMessage()
if record.msg.__class__ is not str and isinstance(record.msg, Preformatted):
return msg

_orig = {
k: getattr(record, k) for k in ('msg', 'args', 'pathname', 'levelname')
}
_id = getattr(record, 'id', None)
msg = record.getMessage()
record.msg = self._flag
record.args = None
if _id:
Expand Down Expand Up @@ -212,6 +215,19 @@ def emit(self, record):
super(StdoutHandler, self).emit(record)


class Preformatted(object):
__slots__ = ('msg',)

def __init__(self, msg):
self.msg = msg

def __str__(self):
return str(self.msg)

def __repr__(self):
return f'Preformatted({self.msg!r})'


class _GlobalLogFilter(object):
def __init__(self):
self.logger = logging.getLogger()
Expand Down
68 changes: 66 additions & 2 deletions pyomo/common/tests/test_log.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,12 @@
import pyomo.common.unittest as unittest

from pyomo.common.log import (
LoggingIntercept,
WrappingFormatter,
LegacyPyomoFormatter,
LoggingIntercept,
LogHandler,
LogStream,
Preformatted,
WrappingFormatter,
pyomo_formatter,
)

Expand Down Expand Up @@ -271,6 +272,54 @@ def test_numbered_level(self):
)
self.assertEqual(self.stream.getvalue(), ans)

def test_preformatted(self):
self.handler.setFormatter(
LegacyPyomoFormatter(
base=os.path.dirname(__file__),
verbosity=lambda: logger.isEnabledFor(logging.DEBUG),
)
)

msg = """This is a long multi-line message that in normal circumstances \
would be line-wrapped
with additional information
that normally be combined."""
jsiirola marked this conversation as resolved.
Show resolved Hide resolved

logger.setLevel(logging.WARNING)
logger.info(msg)
self.assertEqual(self.stream.getvalue(), "")

logger.warning(Preformatted(msg))
ans = msg + "\n"
self.assertEqual(self.stream.getvalue(), ans)

logger.warning(msg)
ans += (
"WARNING: This is a long multi-line message that in normal "
"circumstances would\n"
"be line-wrapped with additional information that normally be combined.\n"
jsiirola marked this conversation as resolved.
Show resolved Hide resolved
)
self.assertEqual(self.stream.getvalue(), ans)

logger.setLevel(logging.DEBUG)

logger.warning(Preformatted(msg))
ans += msg + "\n"
self.assertEqual(self.stream.getvalue(), ans)

logger.warning(msg)
lineno = getframeinfo(currentframe()).lineno - 1
ans += 'WARNING: "[base]%stest_log.py", %d, test_preformatted\n' % (
os.path.sep,
lineno,
)
ans += (
" This is a long multi-line message that in normal "
"circumstances would be\n"
" line-wrapped with additional information that normally be combined.\n"
jsiirola marked this conversation as resolved.
Show resolved Hide resolved
)
self.assertEqual(self.stream.getvalue(), ans)

def test_long_messages(self):
self.handler.setFormatter(
LegacyPyomoFormatter(
Expand Down Expand Up @@ -495,3 +544,18 @@ def test_log_stream(self):
self.assertEqual(OUT.getvalue(), "INFO: line 1\n")
# Exiting the context manager flushes the LogStream
self.assertEqual(OUT.getvalue(), "INFO: line 1\nINFO: line 2\n")


class TestPreformatted(unittest.TestCase):
def test_preformatted_api(self):
ref = 'a message'
msg = Preformatted(ref)
self.assertIs(msg.msg, ref)
self.assertEqual(str(msg), ref)
self.assertEqual(repr(msg), "Preformatted('a message')")

ref = 2
msg = Preformatted(ref)
self.assertIs(msg.msg, ref)
self.assertEqual(str(msg), '2')
self.assertEqual(repr(msg), "Preformatted(2)")