1#!/usr/bin/env python
2"""Log utilities for tmuxp.
3
4tmuxp.log
5~~~~~~~~~
6
7"""
8import logging
9import time
10
11from colorama import Fore, Style
12
13LEVEL_COLORS = {
14    'DEBUG': Fore.BLUE,  # Blue
15    'INFO': Fore.GREEN,  # Green
16    'WARNING': Fore.YELLOW,
17    'ERROR': Fore.RED,
18    'CRITICAL': Fore.RED,
19}
20
21LOG_LEVELS = {
22    'CRITICAL': 50,
23    'ERROR': 40,
24    'WARNING': 30,
25    'INFO': 20,
26    'DEBUG': 10,
27    'NOTSET': 0,
28}
29
30
31def set_style(
32    message, stylized, style_before=None, style_after=None, prefix='', suffix=''
33):
34    if stylized:
35        return prefix + style_before + message + style_after + suffix
36
37    return prefix + message + suffix
38
39
40def default_log_template(self, record, stylized=False):
41    """
42    Return the prefix for the log message. Template for Formatter.
43
44    Parameters
45    ----------
46    :py:class:`logging.LogRecord` :
47        object. this is passed in from inside the
48        :py:meth:`logging.Formatter.format` record.
49
50    Returns
51    -------
52    str
53        template for logger message
54    """
55
56    reset = Style.RESET_ALL
57    levelname = set_style(
58        '(%(levelname)s)',
59        stylized,
60        style_before=(LEVEL_COLORS.get(record.levelname) + Style.BRIGHT),
61        style_after=Style.RESET_ALL,
62        suffix=' ',
63    )
64    asctime = set_style(
65        '%(asctime)s',
66        stylized,
67        style_before=(Fore.BLACK + Style.DIM + Style.BRIGHT),
68        style_after=(Fore.RESET + Style.RESET_ALL),
69        prefix='[',
70        suffix=']',
71    )
72    name = set_style(
73        '%(name)s',
74        stylized,
75        style_before=(Fore.WHITE + Style.DIM + Style.BRIGHT),
76        style_after=(Fore.RESET + Style.RESET_ALL),
77        prefix=' ',
78        suffix=' ',
79    )
80
81    if stylized:
82        return reset + levelname + asctime + name + reset
83
84    return levelname + asctime + name
85
86
87class LogFormatter(logging.Formatter):
88    template = default_log_template
89
90    def __init__(self, color=True, *args, **kwargs):
91        logging.Formatter.__init__(self, *args, **kwargs)
92
93    def format(self, record):
94        try:
95            record.message = record.getMessage()
96        except Exception as e:
97            record.message = "Bad message (%r): %r" % (e, record.__dict__)
98
99        date_format = '%H:%m:%S'
100        record.asctime = time.strftime(date_format, self.converter(record.created))
101
102        prefix = self.template(record) % record.__dict__
103
104        parts = prefix.split(record.message)
105        formatted = prefix + " " + record.message
106        return formatted.replace("\n", "\n" + parts[0] + " ")
107
108
109def debug_log_template(self, record):
110    """
111    Return the prefix for the log message. Template for Formatter.
112
113    Parameters
114    ----------
115    record :  :py:class:`logging.LogRecord`
116        This is passed in from inside the :py:meth:`logging.Formatter.format`
117        record.
118
119    Returns
120    -------
121    str
122        Log template.
123    """
124
125    reset = Style.RESET_ALL
126    levelname = (
127        LEVEL_COLORS.get(record.levelname)
128        + Style.BRIGHT
129        + '(%(levelname)1.1s)'
130        + Style.RESET_ALL
131        + ' '
132    )
133    asctime = (
134        '['
135        + Fore.BLACK
136        + Style.DIM
137        + Style.BRIGHT
138        + '%(asctime)s'
139        + Fore.RESET
140        + Style.RESET_ALL
141        + ']'
142    )
143    name = (
144        ' '
145        + Fore.WHITE
146        + Style.DIM
147        + Style.BRIGHT
148        + '%(name)s'
149        + Fore.RESET
150        + Style.RESET_ALL
151        + ' '
152    )
153    module_funcName = Fore.GREEN + Style.BRIGHT + '%(module)s.%(funcName)s()'
154    lineno = (
155        Fore.BLACK
156        + Style.DIM
157        + Style.BRIGHT
158        + ':'
159        + Style.RESET_ALL
160        + Fore.CYAN
161        + '%(lineno)d'
162    )
163
164    tpl = reset + levelname + asctime + name + module_funcName + lineno + reset
165
166    return tpl
167
168
169class DebugLogFormatter(LogFormatter):
170    """Provides greater technical details than standard log Formatter."""
171
172    template = debug_log_template
173