1 # Copyright 2018 ke liang <lokyse@163.com>.
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
7 # http://www.apache.org/licenses/LICENSE-2.0
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
17 from logging import Formatter, LogRecord
18 from deprecated import deprecated
19 from warnings import warn
20 from typing import Optional, Union, Dict
22 from onaplogging.utils.system import is_above_python_2_7, is_above_python_3_2
23 from onaplogging.utils.styles import (
37 class BaseColorFormatter(Formatter):
38 """Text color formatter class.
40 Wraps the logging. Uses Git shell coloring codes. Doesn't support Windows
41 CMD yet. If `fmt` is not suppied, the `style` is used. Eventually converts
42 a LogRecord object to "colored" text.
45 Support for Windows CMD.
49 style : '%', '{' or '$' formatting.
50 datefrmt : ISO8601-like (or RFC 3339-like) format.
52 fmt : human-readable format. Defaults to None.
53 datefmt : ISO8601-like (or RFC 3339-like) format. Defaults to None.
54 colorfmt : Color schemas for logging levels. Defaults to None.
55 style : '%', '{' or '$' formatting. Defaults to '%'.
57 format : formats a LogRecord record.
58 _parseColor : selects colors based on a logging levels.
64 return self.__style # name mangling with __ to avoid accidents
69 return self.__colorfmt
72 def style(self, value):
74 """Assign new style."""
78 def colorfmt(self, value):
80 """Assign new color format."""
81 self.__colorfmt = value
84 fmt=None, # type: Optional[str]
85 datefmt=None, # type: Optional[str]
86 colorfmt=None, # type: Optional[Dict]
87 style="%"): # type: Optional[str]
89 if is_above_python_3_2():
90 super(BaseColorFormatter, self). \
91 __init__(fmt=fmt, # noqa: E122
95 elif is_above_python_2_7():
96 super(BaseColorFormatter, self). \
97 __init__(fmt, datefmt) # noqa: E122
101 __init__(self, fmt, datefmt) # noqa: E122
103 self.colorfmt = colorfmt
105 def format(self, record):
108 Connects 2 methods. First it extract a level and a colors
109 assigned to this level in the BaseColorFormatter class.
110 Second it applied the colors to the text.
113 record : an instance of a logged event.
115 str : "colored" text (formatted text).
118 if is_above_python_2_7():
119 s = super(BaseColorFormatter, self). \
126 color, highlight, attribute = self._parse_color(record)
128 return apply_color(s, color, highlight, attrs=attribute)
130 def _parse_color(self, record):
131 # type: (LogRecord) -> (Optional[str], Optional[str], Optional[str])
132 """Color formatter based on the logging level.
134 This method formats the record according to its level
135 and a color format set for that level. If the level is
136 not found, then this method will eventually return None.
139 record : an instance of a logged event.
142 str : Hightlight tag.
145 if self.colorfmt and \
146 isinstance(self.colorfmt, dict):
148 level = record.levelname
149 colors = self.colorfmt.get(level, None)
151 if colors is not None and \
152 isinstance(colors, dict):
153 return (colors.get(COLOR_TAG, None), # noqa: E201
154 colors.get(HIGHLIGHT_TAG, None),
155 colors.get(ATTRIBUTE_TAG, None)) # noqa: E202
156 return None, None, None
158 @deprecated(reason="Will be removed. Use _parse_color(record) instead.")
159 def _parseColor(self, record):
161 Color based on logging level.
162 See method _parse_color(record).
164 return self._parse_color(record)
167 def apply_color(text, # type: str
168 color=None, # type: Optional[str]
169 on_color=None, # type: Optional[str]
170 attrs=None): # type: Optional[Union[str, list]]
172 """Applies color codes to the text.
175 text : text to be "colored" (formatted).
176 color : Color in human-readable format. Defaults to None.
177 highlight : Hightlight color in human-readable format.
178 Previously called "on_color". Defaults to None.
179 attrs : Colors for attribute(s). Defaults to None.
181 str : "colored" text (formatted text).
183 warn("`on_color` will be replaced with `highlight`.", DeprecationWarning)
184 highlight = on_color # replace the parameter and remove
186 if os.name in ('nt', 'ce'):
189 if isinstance(attrs, str):
192 ansi_disabled = os.getenv('ANSI_COLORS_DISABLED', None)
194 if ansi_disabled is None:
196 if color is not None and \
197 isinstance(color, str):
198 text = FMT_STR % (COLORS.get(color, 0), text)
200 if highlight is not None and \
201 isinstance(highlight, str):
202 text = FMT_STR % (HIGHLIGHTS.get(highlight, 0), text)
204 if attrs is not None:
206 text = FMT_STR % (ATTRIBUTES.get(attr, 0), text)
208 text += RESET # keep origin color for tail spaces
213 @deprecated(reason="Will be removed. Call apply_color(...) instead.")
214 def colored(text, color=None, on_color=None, attrs=None):
216 Format text with color codes.
217 See method apply_color(text, color, on_color, attrs).
219 return apply_color(text, color, on_color, attrs)