Source code for pymor.discretizers.builtin.gui.jupyter.logging
import ipywidgets
import logging
from IPython.display import display
from pymor.core import logger
from pymor.core.logger import ColoredFormatter
[docs]class LogViewer(logging.Handler):
out = None
def __init__(self, out, accordion=None):
super().__init__()
self.out = out
self.accordion = accordion
self.setFormatter(ColoredFormatter())
self.first_emit = True
[docs] def emit(self, record):
if self.first_emit:
if self.accordion:
display(self.accordion)
self.first_emit = False
record = self.formatter.format_html(record)
self.out.value += f'<p style="line-height:120%">{record}</p>'
@property
def empty(self):
return len(self.out.value) == 0
[docs] def close(self):
if self.empty and self.accordion:
self.accordion.close()
[docs] def __repr__(self):
return '<%s %s>' % (self.__class__.__name__, self.out)
[docs]class LoggingRedirector:
def __init__(self):
self.old_handlers = None
self.old_default = None
self.new_handler = None
self.accordion = None
def __enter__(self):
self.start()
def __exit__(self, exc_type, exc_val, exc_tb):
self.stop()
def start(self):
out = ipywidgets.HTML(layout=ipywidgets.Layout(width='100%', height='16em', overflow_y='auto'))
self.accordion = ipywidgets.widgets.Accordion(children=[out])
self.accordion.set_title(0, 'Log Output')
# start collapsed
self.accordion.selected_index = None
self.new_handler = LogViewer(out, self.accordion)
def _new_default(_):
return [self.new_handler]
self.old_default = logger.default_handler
logger.default_handler = _new_default
self.old_handlers = {name: logging.getLogger(name).handlers for name in logging.root.manager.loggerDict}
for name in logging.root.manager.loggerDict:
logging.getLogger(name).handlers = [self.new_handler]
def stop(self):
if self.old_default is None:
# %load_ext in the frist cell triggers a post_run_cell with no matching pre_run_cell event before
return
self.new_handler.close()
logger.default_handler = self.old_default
for name in logging.root.manager.loggerDict:
try:
logging.getLogger(name).handlers = self.old_handlers[name]
except KeyError:
# loggers that have been created during the redirect get a default handler
logging.getLogger(name).handlers = logger.default_handler()
redirect_logging = LoggingRedirector()