From 68fb5ab615b58e9e09f330c468428f647a0b5a74 Mon Sep 17 00:00:00 2001 From: Matt Wala Date: Sun, 9 Apr 2017 20:13:44 -0500 Subject: [PATCH 1/4] [WIP] --- pytential/__init__.py | 9 +++++ pytential/log.py | 80 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 89 insertions(+) create mode 100644 pytential/log.py diff --git a/pytential/__init__.py b/pytential/__init__.py index 9be87e78..1c4cf0c3 100644 --- a/pytential/__init__.py +++ b/pytential/__init__.py @@ -30,6 +30,15 @@ from pytential.symbolic.execution import bind from pytools import memoize_on_first_arg +import os + + +PYTENTIAL_DEBUG = os.environ.get("PYTENTIAL_DEBUG") + +if PYTENTIAL_DEBUG: + from pytential.log import set_up_logging + set_up_logging(PYTENTIAL_DEBUG.split(":")) + @memoize_on_first_arg def _integral_op(discr): diff --git a/pytential/log.py b/pytential/log.py new file mode 100644 index 00000000..c5215ac4 --- /dev/null +++ b/pytential/log.py @@ -0,0 +1,80 @@ +__copyright__ = "Copyright (C) 2017 Matt Wala" + +__license__ = """ +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +""" + +import logging + + +def set_up_logging(modules, level=logging.DEBUG): + """ + Based heavily on + http://stackoverflow.com/questions/384076/how-can-i-color-python-logging-output + + :arg modules: A list of modules for which logging output should be enabled + """ + BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE = range(8) + + #These are the sequences need to get colored ouput + RESET_SEQ = "\033[0m" + COLOR_SEQ = "\033[1;%dm" + BOLD_SEQ = "\033[1m" + + def formatter_message(message, use_color = True): + if use_color: + message = message.replace("$RESET", RESET_SEQ).replace("$BOLD", BOLD_SEQ) + else: + message = message.replace("$RESET", "").replace("$BOLD", "") + return message + + COLORS = { + 'WARNING': YELLOW, + 'INFO': CYAN, + 'DEBUG': WHITE, + 'CRITICAL': YELLOW, + 'ERROR': RED + } + + class ColoredFormatter(logging.Formatter): + + def __init__(self, msg, use_color = True): + logging.Formatter.__init__(self, msg) + self.use_color = use_color + + def format(self, record): + levelname = record.levelname + if self.use_color and levelname in COLORS: + levelname_color = ( + COLOR_SEQ % (30 + COLORS[levelname]) + levelname + RESET_SEQ) + record.levelname = levelname_color + return logging.Formatter.format(self, record) + + FORMAT = "[$BOLD%(name)s$RESET][%(levelname)s] %(message)s " \ + "($BOLD%(filename)s$RESET:%(lineno)d)" + COLOR_FORMAT = formatter_message(FORMAT, True) + color_formatter = ColoredFormatter(COLOR_FORMAT) + + handler = logging.StreamHandler() + handler.setFormatter(color_formatter) + + for module in modules: + logger = logging.getLogger(module) + logger.addHandler(handler) + logger.setLevel(level) -- GitLab From 382fac2a5bce13ddbbf6b96cde0fff612d780c92 Mon Sep 17 00:00:00 2001 From: Matt Wala Date: Thu, 13 Apr 2017 11:02:04 -0500 Subject: [PATCH 2/4] Add support for color-enabled, module selective logging. This introduces a function pytential.log.set_up_logging() which takes a list of modules and creates a configurable logger and formatter for each of those modules. Logging may be controlled through environment variables. Example: PYTENTIAL_LOG_DEBUG=pytential:loopy PYTENTIAL_LOG_INFO=boxtree python test.py This command will set up debug logging for pytential and loopy and set up info level logging for boxtree. Note that this feature shouldn't be used with code that calls logging.basicConfig(), as logging.basicConfig() sets up a root handler which overrides everything that we do. See also: #9 --- pytential/__init__.py | 17 +++++-- pytential/log.py | 104 ++++++++++++++++++++++++++---------------- 2 files changed, 78 insertions(+), 43 deletions(-) diff --git a/pytential/__init__.py b/pytential/__init__.py index 1c4cf0c3..5d8c61fc 100644 --- a/pytential/__init__.py +++ b/pytential/__init__.py @@ -33,11 +33,22 @@ from pytools import memoize_on_first_arg import os -PYTENTIAL_DEBUG = os.environ.get("PYTENTIAL_DEBUG") +PYTENTIAL_LOG_DEBUG = os.environ.get("PYTENTIAL_LOG_DEBUG") -if PYTENTIAL_DEBUG: + +if PYTENTIAL_LOG_DEBUG is not None: + import logging + from pytential.log import set_up_logging + set_up_logging(PYTENTIAL_LOG_DEBUG.split(":"), level=logging.DEBUG) + + +PYTENTIAL_LOG_INFO = os.environ.get("PYTENTIAL_LOG_INFO") + + +if PYTENTIAL_LOG_INFO is not None: + import logging from pytential.log import set_up_logging - set_up_logging(PYTENTIAL_DEBUG.split(":")) + set_up_logging(PYTENTIAL_LOG_INFO.split(":"), level=logging.INFO) @memoize_on_first_arg diff --git a/pytential/log.py b/pytential/log.py index c5215ac4..a133ebdc 100644 --- a/pytential/log.py +++ b/pytential/log.py @@ -22,54 +22,78 @@ THE SOFTWARE. import logging +# +# This file is based heavily on +# http://stackoverflow.com/questions/384076/how-can-i-color-python-logging-output +# -def set_up_logging(modules, level=logging.DEBUG): - """ - Based heavily on - http://stackoverflow.com/questions/384076/how-can-i-color-python-logging-output - :arg modules: A list of modules for which logging output should be enabled - """ +# {{{ constants + +class colors: # noqa BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE = range(8) - #These are the sequences need to get colored ouput + +class term_seq: # noqa RESET_SEQ = "\033[0m" COLOR_SEQ = "\033[1;%dm" BOLD_SEQ = "\033[1m" - def formatter_message(message, use_color = True): - if use_color: - message = message.replace("$RESET", RESET_SEQ).replace("$BOLD", BOLD_SEQ) - else: - message = message.replace("$RESET", "").replace("$BOLD", "") - return message - - COLORS = { - 'WARNING': YELLOW, - 'INFO': CYAN, - 'DEBUG': WHITE, - 'CRITICAL': YELLOW, - 'ERROR': RED - } - - class ColoredFormatter(logging.Formatter): - - def __init__(self, msg, use_color = True): - logging.Formatter.__init__(self, msg) - self.use_color = use_color - - def format(self, record): - levelname = record.levelname - if self.use_color and levelname in COLORS: - levelname_color = ( - COLOR_SEQ % (30 + COLORS[levelname]) + levelname + RESET_SEQ) - record.levelname = levelname_color - return logging.Formatter.format(self, record) - - FORMAT = "[$BOLD%(name)s$RESET][%(levelname)s] %(message)s " \ - "($BOLD%(filename)s$RESET:%(lineno)d)" - COLOR_FORMAT = formatter_message(FORMAT, True) - color_formatter = ColoredFormatter(COLOR_FORMAT) + +LEVEL_TO_COLOR = { + 'WARNING': colors.YELLOW, + 'INFO': colors.CYAN, + 'DEBUG': colors.WHITE, + 'CRITICAL': colors.YELLOW, + 'ERROR': colors.RED +} + + +PYTENTIAL_LOG_FORMAT = ( + "[$BOLD%(name)s$RESET][%(levelname)s] %(message)s " + "($BOLD%(filename)s$RESET:%(lineno)d)" +) + +# }}} + + +# {{{ formatting + +class ColoredFormatter(logging.Formatter): + + def __init__(self, msg, use_color=True): + logging.Formatter.__init__(self, msg) + self.use_color = use_color + + def format(self, record): + levelname = record.levelname + if self.use_color and levelname in LEVEL_TO_COLOR: + levelname_color = ( + (term_seq.COLOR_SEQ % (30 + LEVEL_TO_COLOR[levelname])) + + levelname + term_seq.RESET_SEQ) + record.levelname = levelname_color + return logging.Formatter.format(self, record) + + +def make_formatter_message(message, use_color=True): + if use_color: + message = (message + .replace("$RESET", term_seq.RESET_SEQ) + .replace("$BOLD", term_seq.BOLD_SEQ)) + else: + message = message.replace("$RESET", "").replace("$BOLD", "") + return message + +# }}} + + +def set_up_logging(modules, level=logging.DEBUG, use_color=True): + """ + :arg modules: A list of modules for which logging output should be enabled + """ + + color_formatter = ColoredFormatter( + make_formatter_message(PYTENTIAL_LOG_FORMAT, use_color), use_color) handler = logging.StreamHandler() handler.setFormatter(color_formatter) -- GitLab From 47a643394d503a88c987dc9a3bfddeba97c8d243 Mon Sep 17 00:00:00 2001 From: Matt Wala Date: Thu, 13 Apr 2017 11:12:34 -0500 Subject: [PATCH 3/4] Don't use default level argument. --- pytential/log.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pytential/log.py b/pytential/log.py index a133ebdc..000d9885 100644 --- a/pytential/log.py +++ b/pytential/log.py @@ -87,7 +87,7 @@ def make_formatter_message(message, use_color=True): # }}} -def set_up_logging(modules, level=logging.DEBUG, use_color=True): +def set_up_logging(modules, level, use_color=True): """ :arg modules: A list of modules for which logging output should be enabled """ -- GitLab From 4e0a7c3ec6287e2fedc583ce96d8a4b4b5b83ae5 Mon Sep 17 00:00:00 2001 From: Matt Wala Date: Thu, 13 Apr 2017 11:33:01 -0500 Subject: [PATCH 4/4] Make make_formatter_message() a static method of the formatter. --- pytential/log.py | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/pytential/log.py b/pytential/log.py index 000d9885..651afb4b 100644 --- a/pytential/log.py +++ b/pytential/log.py @@ -61,8 +61,19 @@ PYTENTIAL_LOG_FORMAT = ( class ColoredFormatter(logging.Formatter): - def __init__(self, msg, use_color=True): - logging.Formatter.__init__(self, msg) + @staticmethod + def make_formatter_message(message, use_color): + if use_color: + message = (message + .replace("$RESET", term_seq.RESET_SEQ) + .replace("$BOLD", term_seq.BOLD_SEQ)) + else: + message = message.replace("$RESET", "").replace("$BOLD", "") + return message + + def __init__(self, use_color=True): + logging.Formatter.__init__( + self, self.make_formatter_message(PYTENTIAL_LOG_FORMAT, use_color)) self.use_color = use_color def format(self, record): @@ -74,16 +85,6 @@ class ColoredFormatter(logging.Formatter): record.levelname = levelname_color return logging.Formatter.format(self, record) - -def make_formatter_message(message, use_color=True): - if use_color: - message = (message - .replace("$RESET", term_seq.RESET_SEQ) - .replace("$BOLD", term_seq.BOLD_SEQ)) - else: - message = message.replace("$RESET", "").replace("$BOLD", "") - return message - # }}} @@ -92,8 +93,7 @@ def set_up_logging(modules, level, use_color=True): :arg modules: A list of modules for which logging output should be enabled """ - color_formatter = ColoredFormatter( - make_formatter_message(PYTENTIAL_LOG_FORMAT, use_color), use_color) + color_formatter = ColoredFormatter(use_color) handler = logging.StreamHandler() handler.setFormatter(color_formatter) -- GitLab